我知道这可能是一个非常愚蠢的问题,但我看了很多不同的来源,我似乎无法理解no-arg构造函数和带参数的构造函数之间的区别。我的印象是no-arg构造函数接受你想要的任意数量的参数,而带有2个参数的构造函数只接受2。
import java.io.*; //the File class
import java.util.*; //the Scanner class
public class Distance implements Comparable<Distance>
{
private int myFeet, myInches;
public Distance()
{
myFeet = myInches = 0;
}
public Distance(int f, int i)
{
myFeet = f;
myInches = i;
}
public Distance(Distance arg)
{
myFeet = arg.getFeet();
myInches = arg.getInches();
}
}
我只是不明白为什么必须同时包含Distance(int f,int i)和Distance(Distance arg)以及如何知道要使用哪些构造函数。另外,距离arg是什么? “arg”只是占位符变量还是实际的Java关键字?如果我能得到关于构造函数的解释,那就太好了!
答案 0 :(得分:2)
no-arg构造函数接受0个参数(无参数)。它只是在构造函数中运行代码,并且您经常会看到它用于将值初始化为某些预定义的默认值(就像您将其设置为英尺和英寸都为0)。相反,接受参数的构造函数可以在运行时将其值设置为不同的值。
此构造函数
public Distance(Distance arg)
称为 copy 构造函数。它接受同一个类的参数,只将其属性复制到正在构造的当前对象中。
您使用的构造函数完全基于您的需要。有些类不会定义所有类型的构造函数,因此您受到限制。其他人将定义几个构造函数,因此您可以使用这种情况所需的任何构造函数。
答案 1 :(得分:2)
简答:
我认为no-arg构造函数接受你想要的任意数量的参数,而带有2个参数的构造函数只接受2。
no-arg或无参数构造函数不接受任何参数。这是为了创建给定类的默认实例。实际上,如果您没有提供任何构造函数,Java编译器会为您的类提供默认的无参数构造函数。如果你声明一个带有n
参数的构造函数(例如public Person(String name, int age)
),那么通过调用该构造函数来构造该类的实例需要你提供正确的数字,类型和顺序那些论点(例如Person p = new Person("Larry", 32)
)。
也许你把这种类型的构造函数与vararg或变量arity方法混淆,后者接受给定类型的一个或多个参数(你应该阅读一些血腥细节)。由于类的构造函数与任何其他实例方法类似(存在差异),因此您可以使用变量arity构造函数,但它们很少使用:
class Chameleon {
private final String color;
private final String location;
private final int lifeSpanYears;
/**
* Constructs a default Chameleon that has GREEN color, is from Africa and
* has 5 years of life span.
*/
public Chameleon() {
this.color = "GREEN";
this.location = "Africa";
this.lifeSpanYears = 5;
}
/**
* Constructs a specific instance of Chameleon with given color, location
* and life span.
*/
public Chameleon(String color, String location, int lifeSpanYears) {
//validate arguments
this.color = color;
this.location = location;
this.lifeSpanYears = lifeSpanYears;
}
/* Constructs a Chameleon from given one or more string params.
If given, first argument is the color and if given, the second
argument is the location. Life span of the instance will be 5 years.
<b> Note: this is for illustration purposes only. </b>
*/
public Chameleon(String... props) {
if (props.length == 0) {
this.color = "GREEN";
this.location = "Africa";
} else if (props.length == 1) {
this.color = props[0];
this.location = "Africa";
} else {
this.color = props[0];
this.location = props[1];
}
this.lifeSpanYears = 5;
}
public Chameleon(Chameleon mold) {
this.color = mold.color;
this.location = mold.location;
this.lifeSpanYears = mold.lifeSpanYears;
}
public static void main(String[] args) {
Chameleon c = new Chameleon(); // no-arg constructor is called
System.out.println(c.color); // => GREEN
System.out.println(c.location); // => Africa
System.out.println(c.lifeSpanYears); // 5
Chameleon c2 = new Chameleon("BLACK", "Asia", 4); // specific constructor is called, right number, type and order of arguments is provided
System.out.println(c2.color); // => BLACK
System.out.println(c2.location); // => Asia
System.out.println(c2.lifeSpanYears); // 4
Chameleon c3 = new Chameleon("BROWN", "California"); // this time it should be the vararg constructor!
System.out.println(c3.color); // => BROWN
System.out.println(c3.location); // => California
System.out.println(c3.lifeSpanYears); // 5 again
Chameleon c4 = new Chameleon("BROWN"); // this time it should be the vararg constructor again!
System.out.println(c4.color); // => BROWN
System.out.println(c4.location); // => Africa
System.out.println(c4.lifeSpanYears); // 5 again
Chameleon c5 = new Chameleon(c2); // this time the _copy_ constructor is called. c5 is a copy of c2.
// although c5 is a copy of c2, it is a distinct entity; think of c5 as
// an identical twin of c2.
System.out.println(c5.color); // => BLACK
System.out.println(c5.location); // => Asia
System.out.println(c5.lifeSpanYears); // 4
}
}
我只是不明白为什么需要同时使用Distance(int f,int i)和Distance(Distance arg)
嗯,它本身并不是必要的。这很方便。启用此功能的基础机制称为方法重载,这意味着您可以在类中声明具有相同名称(在本例中为类名)的两个构造函数(或方法)。每个构造函数都可以按照它选择的方式构造类的实例。理想情况下,所有构造函数都应构造正确的初始化实例。如果你遵循一些基本的面向对象编程的良好实践,那么你不应该在这里出错。
在这种特殊情况下,你提供了两个构造函数:第一个采用英尺和英尺,另一个采用同一个类的另一个实例。第二个构造函数体现了所谓的复制构造函数,它应该创建传递参数的副本。因此,如果您有d
类的已有实例Distance
,则可以使用以下命令创建该副本:
// get d from somewhere
Distance dCopy = new Distance(d);
请参阅上面示例代码中提供的复制构造函数(及其 use )。
以及您如何知道使用哪些构造函数
在这里,您需要阅读您打算使用的类的文档或来源。像JDK这样写得很好的类提供了很好的文档供你查看。
另外,
Distance arg
是什么?
它是类Distance
的一个实例,用作构造函数参数。再次,请参阅main
示例的Chameleon
方法。
是&#34; arg&#34;只是占位符变量还是实际的Java关键字?
是的,前者。它通常被称为参数或形式参数。
答案 2 :(得分:1)
构造函数用于实例化一个Class。
可以有默认的构造函数,它不会初始化类中的任何属性。
在您的代码中,默认构造函数是:
public Distance()
{
myFeet = myInches = 0;
}
可以通过多种方式实例化类,并且需要构造函数。构造函数中可以有参数。这些参数自动在构造函数中设置类的属性。因此,我们不需要单独设置属性。
例如在您的代码中:
public Distance(int f, int i)
{
myFeet = f;
myInches = i;
}
public Distance(Distance arg)
{
myFeet = arg.getFeet();
myInches = arg.getInches();
}
在第一个构造函数中,属性在构造函数中单独设置。
在第二种情况下,它是从另一个距离对象设置的。
Args不是关键字,它是Distance
类型对象的名称。
答案 3 :(得分:1)
现在,如果您有像
这样的构造函数public A()
{
<something>
}
然后在创建对象时,你必须只写,
A objectA = new A();
如果您有像
这样的构造函数public A(int x)
{
<something>
}
然后声明你必须写,
A objectA = new A(<any integer>);
在这里你不能写,
A objectA = new A();
因此,当您声明构造函数时,只会考虑那些构造函数。 现在在你的代码中,
public Distance()
{
myFeet = myInches = 0;
}
public Distance(int f, int i)
{
myFeet = f;
myInches = i;
}
public Distance(Distance arg)
{
myFeet = arg.getFeet();
myInches = arg.getInches();
}
您可以用三种方式创建Distance类的对象,
Distance distance = new Distance();
Distance distance = new Distance(1,2);
Distance distance2 = new Distance();
Distance distance = new Distance(distance2);
因此,在所有情况下,都会创建对象并初始化值。但它以多种方式编写,以批准多种类型或有礼貌的编码,并为代码提供更多选项来创建对象。 最后, arg 只是一个变量名。