http://c.biancheng.net/view/784.html 位移
https://www.cnblogs.com/laiso/p/9256120.html java Integer与int详解
java引用变量分为编译时类型、运行时类型。编译时类型由申明该变量时使用的类型决定,运行时类型由实际赋给的对象决定。如果编译时类型和运行时类型不一致,就 可能出现所谓的多态。
Java多态的三个必要条件:
1、 继承
2、 子类重写父类方法
3、 父类引用指向子类对象
但是在java的引用中Father不但指定了c以何种方式访问内存,也规定了能够访问内存空间的大小。
我们看Father实例对象的大小是占两行,但Child实例对象占三行(这里就是简单量化一下)。
所以虽然c指向的是Child实例对象,但是前面有Father修饰它,它也只能访问两行的数据,也就是说c根本访问不到Child类中的age!!!只能访问到Father类的age,所以输出40
我们看到Parent的方法表占三行,Child的方法表占4行,c虽然指向了Child类的实例对象,
而对象中也有指针指向Child类的方法表,但是由于c受到了Father的修饰,通过c也只能访问到Child方法表中前3行的内容!!!!
然而前面说过,在方法表的形成过程中,子类重写的方法会覆盖掉表中原来的数据,也就是Child类的方法表的第三行是指向Child.eat的引用,
而不是指向Parent.eat(因为方法表产生了覆盖),所以c访问到的是Child.eat。也就是子类的方法!!!这种情况下,c是没有办法直接访问到父类的eat方法的
比如SubClass类继承BaseClass类
BaseClass bc = new SubClass();这时申明变量和运行变量就不一样了,方法使用是使用SubClass里面的
可以这样操作,是因为子类其实是一种特殊的父类。因此Java允许把一个子类对象直接赋给一个父类引用变量,无需任务类型转换。被称为向上转型,向上转型由系统自动完成。
PS:成员变量不会被继承,调用只能调用父类的成员变量。也可以理解为对象实例变量不具多态性。
引用变量只能引用到编译时的实例变量,但是运行时调用方法变量
编写 Java 程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法,即 使它实际所引用的对象确实包含该方法 如果需要让这个引用变量调用它运行时类型的方法,则必须把 它强制类型转换成运行时类型,强制类型转换需要借助于类型转换运算符
父类:
package extend; /** * * @ClassName: BaseClass * @Description: TODO **/ public class BaseClass { private String name = "aa"; private String id = "11"; public void fly(){ System.out.println("base的fly方法"); } public void printName(){ System.out.println(name); } }子类:
package extend; /** * * @ClassName: SubClass * @Description: TODO **/ public class SubClass extends BaseClass{ private String name = "bb"; public void subFly(){ System.out.println("base的fly方法"); } }测试:
package extend; /** * * @Description: TODO **/ public class Test { public static void main(String[] args) { BaseClass bc = new SubClass(); bc.fly(); //强制转换 ((SubClass) bc).subFly(); } }PS:强制转换原则:
基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括整数型、字符型和浮 点型 但数值类型和布尔类型之间不能进行类型转换引用类型之间的转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系 的类型,则无法进行类型转换,否则编译时就会出现错误 如果试图把 个父类实例转换成子 类类型,则这个对象必须实际上是子类实例才行(即编译时类型为父类类型,而运行时类型是 子类类型),否则将在运行时引发 assCastException 异常 Integer i = 5; //强转报错,因为String和Integer虽然都继承Object。 //但是String和Integer之间并没有继承关系所以报错 String s = (String)i;PS: 进行强制转换前,先用instanceof运算符判断下是否可以成功转换
if (i instanceof String){ String s = (String)i; }instanceof 算符的前一个操作数通常是一个引用类型变量,后 个操作数通常是 个类(也可以 是接口,可以把接口理解成 种特殊的类) ,它用于判断前面的对象是否是后面的类,或者其子类、实 现类的实例 。如果是 ,则返回 true ,否则返回 fals