以下案例,分别使用 Person 接口类型作为父类,依次调用 其子类的构造方法,创建了不同类型的实体:中国人、美国人和 印度人。 由于创建实体分别调用的是子类的构造方法,所以,可以分别调用各自的方法,显示各自的属性值。
interface Person {
/* 这里,不同人吃饭方法不一样,没有统一定义,
* 这时,只能在方法签名之前冠以关键字 abstract
*/
abstract String havingDinner();
}
class Chinese implements Person{ // 具体定义中国人
String name;
public Chinese(String name){
this.name=name;
}
public String havingDinner(){ //中国人吃饭具体化
return name + "用筷子吃饭。";
}
}
class American implements Person{ // 具体定义美国人
String name;
public American(String name){
this.name=name;
}
public String havingDinner(){ //美国人吃饭具体化
return name + "用刀叉吃饭。";
}
}
class Indian implements Person{ //具体定义印度人
String name;
public Indian(String name){
this.name=name;
}
public String havingDinner(){ //印度人吃饭具体化
return name + "用手抓着吃饭。";
}
}
public class InterfaceTest {
public static void main(String args[]){
/* 把不同的子类对象都当作父类 Person 来看,
* 可以屏蔽不同子类对象之间的差异*/
Person p[]=new Person[3];
p[0] = new Chinese("李明");
p[1] = new American("特朗普");
p[2] = new Indian("桑贾伊·甘地");
/* 写出通用的代码,做出通用的编程,
* 以适应需求的不断变化。*/
for (Person r: p)
System.out.println(r.havingDinner());
}
}
发布评论
评论(9)
以下案例,分别使用 Person 接口类型作为父类,依次调用 其子类的构造方法,创建了不同类型的实体:中国人、美国人和 印度人。
由于创建实体分别调用的是子类的构造方法,所以,可以分别调用各自的方法,显示各自的属性值。
DOS窗口:
java 语言规定,此案例的父类, 即接口 Person 中,必须标明 viod havingDinner() 这个抽象方法。否则,用父类型的句柄(引用)就找不到子类实体定义好的 viod havingDinner() 方法。
至于楼主的发问: 在他的案例中,"父类 (接口 TestInterface) 没有子类的方法", 即 "接口 TestInterface 没有规定子类必须定义任何 抽象方法",那麽 为什么用 JSON.toJSONString(...) 方法,就可以找出 子类的属性值呢? 其实,JSON.toJSONString(...) 方法之所以能够拿到 给定对象的 对应的属性值,是因为对应的子类 (并非 这个类的父类或父类型的接口) 定义好了 不容忽视的 getter, 通过 getter, 才能将对应的属性值找出来。换言之,调用 JSON.toJSONString(...) 方法 并没有要求 TestEntity 的父类 TestInterface 接口类型必须标明 getter 方法, 而是要求 TestEntity 类必须定义出 getter 方法, 才能将其对象的属性值,以字符串的形式,打印出来。就是说,在楼主的案例中, 父类 (接口 TestInterface) 没有表明任何方法,只要 子类 TestEntity 的定义包括了 getter 方法的定义, 那么调用 JSON.toJSONString(...) 方法 就可以找出该类的属性值。
总之,从楼主所示的代码行 "TestInterface testInterface = new TestEntity("张三",1);" 可见,testInterface 既是 TestInterface 接口类型(父类),也是 TestEntity 类(子类) 的 实体(对象)。并且,类 TestEntity 的定义中,必定包括了 getter 方法的定义 (虽然楼主没有出示有关代码)。这样,以 TestEntity 的对象 testEntity 作参数,调用 JSON.toJSONString(...) 方法, 尽管 父类接口为空,也必定能成功取到 TestEntity 类 对应的属性值的字符串形式。
你这只是接口跟实现的关系,跟父类子类不是一回事。虽然你拿接口作为实现类的类型,但是对象就是实现类,就好像我用“人类”来称呼你,你也还是你,你不会是我,“人类”只是个称呼
父类引用可以指向子类对象, 可以理解为编译期的事情, 编译器允许不报错.
运行期, 通过父类引用找到了子类实例对象, FastJson就开始对这个实例对象做操作了.
你说的父类中没有子类的属性, 这不重要, 重要的是父类引用指向的谁, 此时的父类引用只是指向子类实例的向导. 你用Object 都行.
Class<? extends SuperTest> class1 = testInterface.getClass();
Field[] fields = class1.getDeclaredFields();
System.out.println(fields[0].getName());
试试就知道了
反射获取,子类对象getClass获取到的class是实现类,并不是引用类型的类
new TestEntity 的地址给TestInterface ,并不是真的TestInterface。只是在主类的表现是TestInterface。你可以强行将Interface转换成Entity。
父类没有提供拿到属性的方法,为啥fastjson 可以拿到
回复
entity你实现了getter、setter方法吧,如果不实现的话是拿不到的
正如你所说,父类指向子类的对象,实际上在内存中,真正创建的是调用构造器创建的子类的对象,这个对象是有你说的方法的。说白了,那个父类的引用就像你的名字,而实际上的对象是你本人