我是一个java noob,因为我最近开始在一门课程中学习。我创建了一个类:人类,它可以存储自己的名字和年龄,还有一个子类学生,它扩展了人类,并添加了他们在那里开始学习的年份。我已经构建了一个randomHuman构造函数,在我的主类中调用它,并创建了一个包含人类的列表(带有随机名称和年龄)。我的问题是,当我想随机选择5名非人类学生和5名学生并创建这个列表时,我不知道如何找出发送给随机构造函数的对象类型,所以我知道是否应该给它一年时间。以及告诉构造函数返回什么类型。
很抱歉这变成了一篇文章,但如果有人能提供帮助,我将不胜感激
TLDR如何扩展randomHuman构造函数以获取两种类型的对象?
这是我的主要课程:
公共类Main{public static void main(String[]args){
Human newHuman = new Human( 18, "Tommy"); System.out.println("Age: " + newHuman.getAge()); System.out.println("Name: " + newHuman.getName()); System.out.println(newHuman.toString()); Human putte = new Human (25,"Putte"); System.out.println(putte); //Varför blir det så? //kanske lokal variabel //Array RandomHumans System.out.println(" "); System.out.println("Array Human"); ArrayList<Human> myAl = new ArrayList(); for(int i = 0; i<15; i++){ Human xx =Human.randomHuman(); myAl.add(xx); } //Array RandomFysiker for(int j = 0; j<myAl.size(); j++){ Human var = myAl.get(j); System.out.println(var.toString()); } System.out.println(" "); System.out.println("Array Fysiker"); ArrayList<Fysiker> myAl2 = new ArrayList(); //puts the Fysiker in an array for(int i = 0; i<15; i++){ Fysiker xx =Fysiker.randomHuman(); myAl2.add(xx); } //prints teh array for(int j = 0; j<myAl2.size(); j++){ Fysiker var = myAl2.get(j); System.out.println(var.toString()); }
}}
和我的人类类:
public class Human {
public String name;
public int age;
Human(int ageIn, String nameIn){ //Constructor
age=ageIn;
name=nameIn;
}
public int getAge(){
return age;
}
public String getName(){
return name;
}
public String toString(){
return "Name: " + getName() +"," + " Age: " + getAge();
}
//Random human
// Behöver ändra konstruktorn så att den kan kolla
// om objectet är Fysiker eller Human och sedan,
// Behandla dom olika
//Problem1: Hur kollar man? Föreslag if(obj instanceof Fysiker), men vad ska jag ha som obj
//Problem2: Vilken returtyp ska man då ha?
public static Human randomHuman(){
String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
int randomAge = (int) (100*Math.random());
String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
// if(xx instanceof Fysiker){
//
// }
return new Human(randomAge,randomName);
}
}
和子类Fysiker(又名学生):
/**
*
* @author Julian
*/
public class Fysiker extends Human{
public int schoolYear;
public Fysiker(int startYear,int ageIn, String nameIn){
super(ageIn, nameIn);
if (age>15){
if (startYear>2013){
} else if (startYear<1932){
} else {
schoolYear = startYear;
}
} else {
}
}
public int getYear(){
return schoolYear;
}
public String toString(){
return super.toString() +","+" Startyear: " +getYear();
}
}
实际上,正如注释中提到的,您的randomHuman()
方法根本不是构造函数。这是一个静态工厂方法,尽管我相信你还不知道这意味着什么。
基本上,构造函数根本不是一个方法,也没有返回类型。构造函数所做的是为使用new
创建的类的新实例提供初始化,尽管它可以执行不严格初始化该对象的字段的操作。
相反,一个方法可以返回一些东西。在您的特殊情况下,最后一行实际上告诉了它返回的内容——它正在为类Human
调用new
,因此它将返回类Human
的对象,而不是Student
。
事实上,类Human
并不知道类Student
。原则上,您可以在编写父类几年后为类编写子类。父类不需要知道它们的后代。他们只是决定允许这些后代改变什么,不允许他们改变什么。
理论上,您可以在Human
中放置一个方法来创建Student
实例。但我敢肯定,在目前的情况下,这是不需要的。
你可能想做的是填写一个Human
或Student
定义之外的人的列表。填写随机列表可能不是"成为一个人"或"成为一名学生"的一部分,所以你应该在Main
课上这样做,根据你的意愿调用new Human()
或new Student()
,并酌情填写。既然你知道你打电话给哪个new
,你也知道是否使用随机年份。
您可以在Main
类中的静态方法中执行此操作,以表示这是您为测试而执行的操作,而不是Human
或Student
逻辑的一部分。
至于能够说出你现在从列表中得到了哪个对象,你可以用instanceof
来做到这一点。但是,如果要访问其getYear()
方法,还需要将其类型转换为Student
。
然而——这就是多态性的巧妙之处——如果你只调用toString()
方法,甚至不检查对象的类型,如果它真的是Student
对象,你就会得到年份,如果它是普通的Human
对象,你就不会得到年份。
假设您的老师实际上希望您扩展randomHuman
方法,这样它有时会提供Human
实例,有时还会提供Students
实例。当它给出Student
时,它当然应该提供一年。
如上所述,这被称为父类和子类之间的紧密耦合,不推荐使用。如果我想构建另一个人类子类,比如Politician
,我必须打电话给你,让你发布一个新版本的Human
,它有时也会给出随机的Politician
秒。因此,在抗议之下,我将解释如何做到这一点。
您现有的功能是:
public static Human randomHuman(){
String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
int randomAge = (int) (100*Math.random());
String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
// if(xx instanceof Fysiker){
//
// }
return new Human(randomAge,randomName);
}
我们这样更改:
public static Human randomHuman(){
String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
int randomAge = (int) (100*Math.random());
String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
Human result = null;
if ( Math.random() < 0.5 ) {
// With a probability of 50%, create a plain human
result = new Human( randomAge, randomName );
} else {
// Create a student. Start by calculating a random year.
int randomYear = (int) (Math.random()*(2013-1932) + 1932);
result = new Fysiker( randomYear, randomAge, randomName );
}
return result;
}
因此,您决定要制作一个普通人,在该决定的范围内,使用new Human(...)
创建它,并将其分配给result
变量。
如果你决定培养一名学生,在这个决定的范围内,你可以随机计算一个年份,并用new Fysiker()
创建它。您可以将其分配给变量result
,因为从多晶型上讲,它是Human
。但实际上,在内部,它是一个学生。
返回result
变量,此时该变量可能包含Human
或Student
。
要确定对象实例的类型,请使用object instanceof class
或object.getClass().equals(Clazz.getSimpleName())
对于返回类型,只需使用superClass(或接口)。如果需要,你可以随时把它传给孩子。
如果你想创建每个类的5个类,你需要在方法声明中使用一个布尔值,并每次调用5次,以确保每个类有5个实例。
public static Human randomHuman(boolean isHuman){
如果这不重要,你可以添加一个随机布尔值,然后调用构造函数:
boolean isHuman = Math.random() < 0.5;
if(!isHuman){
int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
// create student
} else {
// create human
}