多态
多态的概述:多态是继封装,继承之后,面向对象的第三大特性。是指同一行为,具有多个不同表现形式,为多态。
举个生活栗子:生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
java实现多态条件:
- 继承:在多态中必须存在有继承关系的子类和父类
- 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法
- 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法
代码简略实现:
public class Dome01 { public static void main(String[] args) { Fu fu = new Fu(); //创建父类对象 fu.print(); //我们可以调用父类的公共方法print不能访问name私有方法 Zi zi = new Zi(); //创建子类对象 zi.print(); //子类自动继承父类的print()方法,但是子类里也写了一个print方法,所以属于重写父类方法 zi.run(); //子类继承父类可继承的方法或变量,所以可以通过子类调用run //多态---------------- Fu zi2 = new Zi(); //创建子类对象,使用父类来承接 zi2.print(); //和上面的子类对象调用一样,上面子类能调用发下面也能调用 zi.run(); } } class Fu {// 定义父类方法 public void print() { System.out.println("我是父类的输出方法"); } private void name() { System.out.println("我是父类的私有方法"); } public void run() { System.out.println("我是父类的run方法"); } } class Zi extends Fu { // 定义子类 // 子类方法一 @Override public void print() { System.out.println("我是子类的输出方法"); } private void name() { System.out.println("我是子类的私有方法"); } }
虽然使用下面多态调用效果一样,但是调用的过程是有区别的
-
成员变量:编译看左边(父类),运行看左边(父类) 所有的成员变量取决于编译时类型
-
成员方法:编译看左边(父类),运行看右边(子类) 所有的成员方法取决于运行时类型
-
静态方法:编译看左边(父类),运行看左边(父类) 所有的静态方法取决于编译时类型
代码解释:
public class Dome02 { public static void main(String[] args) { Fu1 zi1 = new Zi1(); System.out.println(zi1.a); //输出的值为0,调用成员方法是编译时看父类的成员变量,运行时也运行父类的成员变量 zi1.name(); //调用成员方法时,编译时,先看父类有没有该成员方法,如果有,就去看子类有没有,如果也有就执行子类的 zi1.name2(); // 由于name02是静态方法,所以,调用时编译是看的是父类,所以运行时也会运行父类的, //调用静态方法和成员变量,静态的是属于各自类的不能继承也不能被重写 Fu1.name2(); System.out.println(Fu1.b); Zi1.name2(); System.out.println(Zi1.b); } } class Fu1 { int a = 0; static int b = 1; public void name() { System.out.println("我是父类普通成员方法"); } public static void name2() { System.out.println("我是父类静态成员方法"); } } class Zi1 extends Fu1 { int a = 22; static int b = 11; @Override public void name() { System.out.println("我是子类普通成员方法"); } public static void name2() { // 静态方法不能重写 System.out.println("我是子类的静态成员方法"); } }
在调用成员方法时,子类如果没有重写,会默认继承父类的,所以运行依旧子类中的name()方法,但本质上这个name()方法依旧是父类的,但子类重写后,它的本质就变量,相当于子类从父类继承来了一块宝石,然后子类经过一系列的打磨,雕刻,它变成了一个工艺品,这个时候,这个工艺品就是子类独有的而并非还是原来的那个宝石。注:父类的方法在子类重写后仍可以通过父类对象调用
多态的好处: 可以使程序编写的更简单,并有良好的扩展。
引用类型的转型:
转型分为向上转型和向下转型两种。
向上转型 :多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。
父类类型 变量名 = new 子类类型(); 如:Animal a = new Cat();
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c =(Cat) a;
instanceof关键字:
有时候,在转换类型的时候,程序员会看不到源码,所以我们需要强转时,不知道该往哪一个子类去转换,就会引发ClassCastException异常,为了处理这一个问题java提供了instanceof关键字。(类似于判断的意思) 演示如下:
public class MyTest3 { public static void main(String[] args) { // 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat // 向下转型 if (a instanceof Cat){ Cat c = (Cat)a; c.catchMouse(); // 调用的是 Cat 的 catchMouse } else if (a instanceof Dog){ Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse } } }
内部类
内部类:顾名思义就是内部的类,在一个类A中定义一个类B这个时候 类A就会被称作外部类, 而类B就被称作内部类了。 内部类,有根据所处位置不同,修饰符不同来区分为四大内部类分别是:成员内部类 静态内部类 局部内部类 匿名内部类。
成员内部类:
public class Outer { class Inner { // 成员内部类 } }
成员内部类的注意点:
-
-
外部类要访问内部类的成员,必须要建立内部类的对象。
静态内部类:静态内部类是指使用 static 修饰的内部类。----代码如下:
public class Outer { static class Inner { // 静态内部类 } }
静态内部类注意点:
-
-
静态内部类可以直接访问外部类的静态成员,如果要访问外部类的实例成员,则需要通过外部类的实例去访问。
局部内部类:局部内部类是指在一个方法中局部位置定义的内部类。 ----代码如下:
public class Outer { public void method() { class Inner { // 局部内部类 } } }
局部内部类注意点:
-
-
局部内部类只在当前方法中有效;
-
局部内部类中不能定义 static 成员。
public class Dome03 { public static void main(String[] args) { // 匿名内部类实现重写普通类的方法 new test01() { @Override public void name() { // TODO Auto-generated method stub } }; // 匿名内部类实现重写抽象类的抽象方法 new test02() { @Override public void name() { // TODO Auto-generated method stub } }; // 匿名内部类实现重写接口的抽象方法 new test03() { @Override public void name() { // TODO Auto-generated method stub } }; } } class test01 { public void name() { System.out.println(""); } } abstract class test02 { public abstract void name(); } interface test03 { void name(); }
匿名内部类的作用:
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,
- 定义子类
- 重写接口方法
- 创建子类的对象
- 调用重写后的方法
我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快捷方式。
模板设计模式
如何理解,模板设计模式是将功能的细节封装起来,给外界一个公共的调用模板,我们调用这个模板就能达到想要的需求。比如:我们想在控制台打印三句话:我爱你java,我将好好学习java,我一定会成为一个好的工程师。使用模板设计模式如下:
public class Dome04 { public static void main(String[] args) { Test test = new Test(); test.template(); //调用时我们不需要知道代码实现的细节,直接调用模板方法就能完成需求 } } class Test { // 细节是什么??? 细节就是三句话 public void template() { // 定义公共模板 // 公共模板调用三个细节 print1(); print2(); print3(); } // 使用private封装三个细节 private void print1() { System.out.println("我爱你java"); } private void print2() { System.out.println("我将好好学习java"); } private void print3() { System.out.println("我一定会成为一个好的工程师"); } }
设计模式,属于一种写代码的思想,这里写很是简略,与个人学习有出入,是自己所理解的比较容易懂一些。了解更多细节:https://www.runoob.com/design-pattern/template-pattern.html
个人学习,内容简略