JavaSE——Java多态

来源:互联网 发布:二维数组的赋值 编辑:程序博客网 时间:2024/04/27 14:58


多态总结



本文根据毕老师Java基础视频和自己的理解总结了继承,接口实现, 多态和内部类的主要知识点

1. 什么是子父类的继承关系, 特点是什么?

a. 继承描述的是类与类的一种关系, 父类中描述的是所有继承子类所有的共性信息, 子类是父类的一个延续

b. 父类包含了一类事物的功能, 继承使子类无需自己创建就可直接获得这些功能 

c. 继承只能是单继承, 因为当多个父类中拥有多个同名方法时, 就不知道用那个方法了 

d. 而且, 如果有多级继承, 继承来的方法是直接父类的方法

e. 不可以在静态函数中使用 this/super关键字


2. 继承中, 子父类的成员变量是什么关系?

a. 子类自动得到父类的可访问变量, 即, 如未覆盖, 子类this引用自动指向父类的成员变量, 父类中的私有变量是得不到的

b. 内存中, 会先加载父类.class文件, 子父类同名的成员变量同时在内存中, 一个被this本类引用指向, 一个被super父类引用指向

c. 如果一定要调用父类的变量需要通过父类引用super.member来实现; 而a中情况,this,super指向内存中同一个继承来的变量

//成员变量的关系class First{     public String str="First str";      // --> 2.b     public String strF="strF";          // --> 2.a}class Second extends First{ public String str="Second str"; // --> 2.b public String strCompare="this.str="+super.str+"\nsuper.str="+this.str+"\ns.str="+str;         // --> 2.b,c}public class ExtendsDemo{        public static void main(String[] args){    Second s=new Second();        System.out.println(s.strF);        System.out.println(s.strCompare);         // System.out.println(this.str);  // --> 1.e       // System.out.println(super.str); // --> 1.e         }}
输出:

strF

this.str=First str

super.str=Second str

s.str=Second str

3. 继承中,子父类的方法是什么关系?

a. 子父类中一样的函数是复写关系

b. 复写的好处是, 避免了修改源码的过程, 通过继承老的类, 复写需要修改的方法

c.  复写时需要调用父类被复写方法的代码: method(){super.method();}

d. 子类复写父类, 需要保证子类的权限大于等于父类的权限

e. 静态只能复写静态

//成员方法的关系class First{     public void show(){       System.out.println("First's show");     }     public void firstOnly(){     System.out.println("First");   // --> 3.b     }     public void show0(){};// --> 3.d     public static void fee(){};// --> 3.e}class Second extends First{ public void show(){  System.out.println("Second's show"); } // void show0(){};  // --> 3.d // public void fee(){}; // --> 3.e public void showFirst(){  super.show();   // --> 3.c }}public class ExtendsDemo{    public static void main(String[] args){    Second s=new Second();    s.firstOnly();        // --> First    s.show();// --> Second's show    s.showFirst();                  // --> First's show    }}

4. 复写和重载的区别?

a. 复写的同名方法一定要子父类中一模一样

b. 重写的同名方法必须要求方法的参数列表不同

c. 只有返回类型值不同的方法是不容许定义的


5. 继承中,子父类的构造函数是什么关系?

a. 子类在加载时, 其构造函数上(无论是空否)都有一个隐式的super(); 相当于先加载父类的空构造函数,再加州本类的构造函数

b. 如果父类不存在空的构造函数,子类的构造函数中必须指定加载一个父类的构造函数

c. 总之, 子类必然要访问一个父类的构造函数,而且super()语句要写在子类构造函数的第一行

d. 复写时, 子类要调用本来构造方法, 用 this(), 而且也必须出现在第一行, 考虑c, 即复写时只能出现this()/super()其中一个

//构造函数的关系class First{public First(){System.out.println("First run");}public First(String str){System.out.println("Frist("+str+") run");}}class Second extends First{ public Second(){    // --> 5.a System.out.println("Second run"); } public Second(String str){    // --> 5.a System.out.println("Second("+str+") run"); } public Second(int num){ super("second(num)");   // --> 5.b,c // 上一行替换为this();    // --> 5.d  System.out.println("Second("+num+") run"); }}public class ExtendsDemo{    public static void main(String[] args){    new Second();                   // --> First run Second run    new Second("a");                // --> First run Second("a") run     new Second(1);                  // --> First(second(num)) run Second(1) run    }}

6. 为什么子类一定要加载父类的构造函数?

a. 构造函数可能接受一些成员初始化的值, 子类的成员可能需要依赖这些成员的初始化值


7. final关键字在类, 变量, 方法上分别是怎么用的, 定义成final的用处是什么?

a. 被final修饰的类不可以被继承, 可以避免用户通过一个子类继承的方式来改变这个类的所有属性

b. 被final修饰的方法不可以被子类复写, 给用户继承的权利,但是不可以改变某些方法的输出属性

c. 被final修饰的变量是一个常量,只能被赋值一次, 既可以修饰成员变量又可以修饰局部变量, 为了增强不可变数据的安全性

d. 内部类定义在类中的局部位置上时,只能访问局部被final修饰的局部变量


8. 抽象方法/类是什么, 有什么特点, 为什么要定义抽象?

a. 抽象方法是一种同类型(具体实现不同或不确定的)方法的抽取, 没有代码体, 不可以用new创建对象, 调用它也没有意义

b. 有抽象方法要被实用,必须由子类复写起所有的抽象方法后, 建立子类的对象调用

c. 抽象类是包含有抽象方法的类, 这其实是一种表示, 表明此类有需要复写内部的抽象方法

d. 如果一个抽象类的子类没有复写父类抽象类中所有的抽象方法, 那么这个子类还是一个抽象类

e. 抽象类可以没有一个抽象方法, 这样做的唯一一个目的就是不让这个类实例化


9. 接口是什么, 接口有什么特点?

a. 接口是将一些类所共有的方法抽取成一个功能描述的类, 所有子类可以实现这个接口中的方法以表征这个接口定义的功能, 

b. 接口定义了一类事物一种规则, 实现是一种规则的遵循; 

c. 接口在定义上可以理解为一个只包含常量(public static final)和/或抽象方法(public abstract)的抽象类

d. 接口中所有的成员都是public的

e. 接口中默认包含 public static final 和 public abstract关键字

f. 类与接口的关系叫implements, 一个类/接口可以implements多个接口

g. 接口于接口的关系还叫extends, 一个接口可以extends多个接口(注意,多个父接口中不可以有只有返回值不同的方法)

h. 接口不可以创建对象, 如果要实例化, 必须有一个可以实现此接口中所有方法的子实现类


// 接口示例interface A{void methodA();}       // --> 9.einterface B{void methodB();}       // --> 9.einterface C extends A,B{void methodC();} // --> 9.ginterface D{public abstract void methodD();      // --> 9.c,dpublic static final double PI=3.14;  // --> 9.c,d}public class ImplementsDemo implements C1,D1 { // --> 9.fpublic void methodA(){};public void methodB(){};public void methodC(){};public void methodD(){};public static void main(String[] args) {System.out.println(new ImplementsDemo().PI); // --> 9.h}}


10. 什么是多态, 多态的好处是? 

a. 多态可以是一类事物在不同分类,场合,的不同角色的体现, 这些角色的体现包含再该事物的继承和实现体系之中

b. 一个子类事物,可以作为一个父类或父接口的的角色被识别和接受, 即父类的引用接受了自己的子类对象

c. 多态的出现大大的提高了程序的可扩展性, 特别是体现在对方法参数的引用类型的向上装换上面

d. c的方法会牺牲子类的本类特殊功能的调用, 如果希望调用子类特殊功能, 需要进行向下类型转换(需要判断instanceof)

e. 虽然c在引用调用方法时收的引用类(父类)可见方法的限制, 调用的方法的仍然是对象中的方法(即子类中复写的方法体)

f. e的另一种说法是: 多态非静态方法编译时期看引用, 运行时期看对象; 

g. 静态方法/静态成员/非静态成员多态时无论编译和运行都只看引用;

//多态示例abstract class Animal{abstract public void eat();public void sleep(){System.out.println("Zzz");}; }class Cat extends Animal{public void eat(){System.out.println("Fish");}public void catchMouse(){System.out.println("Catch Mouse");}}class Dog extends Animal{public void eat(){System.out.println("Bone");}public void guardHouse(){System.out.println("Guard House");}}public class PolymorphismDemo {public static void main(String[] args) {doSomething(new Cat());doSomething(new Dog());}public static void doSomething(Animal a){a.eat();if(a instanceof Cat)         // --> 10.d,e((Cat) a).catchMouse();if(a instanceof Dog)         // --> 10.d,e((Dog) a).guardHouse();a.sleep();}}

11. instanceof关键字如何理解?

a. instanceof 用来判断一个引用名称的对象是否是一个类的对象,父类的子类对象或者接口的子类实现

b. 无论引用是父类还是接口, 只看这个引用对用的对象

interface Man{}    class Father{}class Son extends Father implements Man{}public class InstanceofTest {public static void main(String[] args) {Son son=new Son();      // --> 11.aFather son1=new Son();  // --> 11.bMan son2=new Son();     // --> 11.bSystem.out.println((son instanceof Son)+","    // --> true,true,true  +(son instanceof Father)+","+(son instanceof Man)); System.out.println((son1 instanceof Son)+","   // --> true,true,true          +(son1 instanceof Father)+","+(son1 instanceof Man));System.out.println((son2 instanceof Son)+","   // --> true,true,true  +(son2 instanceof Father)+","+(son2 instanceof Man));}}

12. 内部类是什么, 有什么特点, 如何在内部类中调用外部类的成员, 如何在内部类调用外部类的成员?

a. 内部类是一个定义在一个类中的类, 内部类可以访问外部类中的成员包括私有

b. 外部类如果要访问内部类, 需要建立内部类对象

c. 内部类是一个类内部的成员,所以可以被多种修饰符修饰, 如 private, static


13. 如何在其他类中直接访问一个类的内部类中的成员, 如何区分内部类和外部类的同名成员?

a.  同样也需要建立一个内部类对象:  OuterName.InnerName  oi= new OuterName().new InnerName();

b. 一个有内部类的类有这样几个引用: 局部成员 x; 内部类成员: this.x 外部类成员: OuterName.this.x

c. 本类中访问会省略this或OuterName.this, 查找顺序是: 先检查局部, 在检查内部类引用, 再检查外部类引用, 先找到哪个就返回哪个值

//内部类示例class Outer{int x=1;               // --> 13.b Outer.this.class Inner{int x=2;       // --> 13.b this.void show(){int x=3;System.out.println(x+" "+this.x+" "+Outer.this.x);}             // --> 13.c}}public class InnerTest {public static void main(String[] args) {Outer.Inner oi=new Outer().new Inner(); // --> 13.aoi.show();}}

14. 内部类定义成static的时候有哪些要注意的?

a. static:内部类具有static特性;当内部类被static修饰后,只能访问外部类中static成员,出现访问局限。

b. 在外部其他类中,访问static内部类成员:new Outer.Inner().function(); //外部类名调用静态成员=>新建对象=>调用方法

c. 在外部其他类中,访问static内部static成员:new Outer.Inner.function();

d. 当内部类定义了static成员,内部类必须是static的(static部分先于外部类对象存在)

e. 当外部类中的static方法访问内部类时,内部类也必须是static; (static的外部类方法调用不需要对象,只有调用static的内部类才能被调用)


15. 局部内部类有哪些要注意的?

a. 不可以被成员修饰符修饰;

b. 可以直接访问外部类的成员,因为还持有外部类的引用;

c. 不可以访问它所在的局部中的变量,除非这个局部变量被final修饰

// 静态和局部内部类示例class Outer{static int x=1;         // --> 14.a static class Inner{     // --> 14.d,evoid show(){    // --> 14.bSystem.out.println(x);}static void staticShow(){}; }       // --> 14.cvoid fee(){//int x=0;   // --> 15.c 无法通过编译 需要finalclass InnerLocal{   // --> 15.avoid foo(){System.out.println(x);}          // --> 15.b}}}public class InnerTest {public static void main(String[] args) {Outer.Inner oi=new Outer.Inner(); // --> 15.boi.show();               Outer.Inner.staticShow();         // --> 15.c}}

参考资料: 传智博客毕老师Java基础视频


原创粉丝点击