多态
:同一方法根据发送对象的不同而采用多种不同的行为方式
Person test = new Student(); [引用类型] [实际类型]
对象能执行那些方法,主要看对现象申明时左边的引用类型,与对象右边的实际类型关系不大
Class A(){ public void run(){ System.out.println("Good!"); } } Class B extends A(){ @Override public void run(){ System.out.println("Bad!"); } public void eat(){ System.out.println("Sweet!"); } } Class C(){ //一个对象的实际类型是确定的 // new B(); //引用类型不确定,父类引用指向子类 // 引用类型为父类,可指向子类,但无法调用子类独有的方法 A s1 = new B(); // 引用类型为子类,可使用自己的方法或继承的父类的方法 B s2 = new B(); Object s3 = new B(); **对象能执行那些方法,主要看对现象申明时左边的引用类型,与对象右边的实际类型关系不大** s1.run(); ----正确 s1.eat(); ----错误 ((B)s2).eat(); ----正确 }
-
注意事项
1)多态是方法的多态,属相没有多态
2)多态需要在继承----即父类和子类中才有,类型转换异常----ClassCastException!
3)存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new Son();
①static ---- 方法,属于类,它不属于实例
②final ---- 常量:值不可改变
③private ---- 私有
instanceof
Class A(){} Class B extends A(){} Class C extends A(){} Object test = new B(); test instanceof Object == true; test instanceof B == true; test instanceOf A == true; test instanceof C == false; test instanceof String == false;
-
***注意
1)父类引用指向子类的对象
2)把子类转换为父类,向上穿行,可能丢失自己的一些方法
3)把父类转化为子类,向下转型,强制转换
4)方便方法的调用,减少重复的代码
static解析
Class Student(){ private static int age; private int ageNext; public void methodOne(){ // 非静态方法可以直接调用静态方法 methodTwo(); methodThree(); } public static void methodTwo(){ // 静态方法可以指直接调用静态方法 methodThree(); // 但是不能直接调用非静态方法 错误 -------methodOne(); 正确方式:new Student().methodOne(); } public static void methodThree(){ // 静态属性可直接调用 System.out.println(Student.age); // 非静态不行,得实例化 Student student = new Student(); System.out.println(student.ageNext); // 实例化后也可调用静态属性 System.out.println(student.age); } }
静态代码块会第一个执行
public class Application { public static void main(String[] args) { Application application = new Application(); } public Application(){ System.out.println("构造方法(结构体)!"); } { System.out.println("匿名代码块!"); } static { System.out.println("静态代码块!"); } } // 由下图可见,静态代码块无论如何会第一个执行
且static静态代码块只会在程序初始化时执行一次
Application application = new Application(); System.out.println("================================"); Application application2 = new Application();
而匿名代码块与对象同事产生,一般用于赋初始值,且先于构造方法执行
静态导入包
import static java.lang.Math.random; System.out.println(random()); //直接调用方法
被final修饰的类无法被继承,其没有子类
抽象类
abstract修饰符修饰得方法/类被称为抽象方法/抽象类
-
抽象类中可以有也可以没有抽象方法,也可以有普通方法,关键字为abstract
-
但是有抽象方法的类一定要申明为抽象类,一定是抽象类
-
抽象类,不能使用new关键字来创建对象,抽象类是用于子类继承的
-
抽象方法,只有方法的声明,没有方法的具体实现代码,其用于子类实现
-
子类继承抽象类之后,要么实现抽象类中未实现的抽象方法,要么继续申明为抽象类
-
且类是单继承,Java中接口是多继承
接口
-
只有规范(抽象方法),自己无法写方法,关键字为Implements
-
面向接口编程,且接口都需要有实现类
-
接口的本质就是锲约、规则,指定一个接口,就必须指定其相关功能
-
接口中所有都是抽象的,默认使用 public abstract,所以接口中的方法不用写修饰符,直接 void run();这样就可以了
-
注重抽象的思维,接口可以实现多继承,凭借此优点在企业开发中使用量明显多于抽象类
-
接口中,常量都是public static final 的
-
接口不能被实例化,其中没有构造方法
-
implements可以实现多个接口,但是实现接口时必须重写接口中的方法
内部类
-
成员内部类:在一份类的内部再写一个类就是内部类
Class Outer(){ Class Inner(){}; } // 外部类实例化即可使用 Outer outer = new Outer(); // 内部类则需要先实例化外部类,再通过外部类实例化内部类 outer.Inner inner = outer.new inner();
内部类可以访问该外部类的所有私有属性和私有方法
-
静态内部类
静态内部类无法访问外部类的非静态属性和方法
-
匿名内部类
一个Java类中可以有多个Class类,但是只能有一个public类
匿名内部类多用于内部测试
Class Apple{ public void eat(){} } public Class Test(){ new Apple().eat(); //这也算是匿名内部类 new UserService(){ // 也是匿名内部类,这些都是一些高级玩法 @Override public void hello(){} }; } interface UserService{ void hello(){}; }
-
局部内部类
即在方法中定义的类
异常机制
-
检查行异常:用户错误或者问题引起,例如打开一个不存在的文件,这种异常不能被简单的忽略,必须处理
-
运行时异常:是可能被避免的异常,可以在编译时被忽略
-
ERROR:错误不是异常,时脱离了程序员控制的问题。错误在代码中通常被忽略,例如:栈溢出,一个错误就发生了,它们在编译时也检查不到
1)Throwable作为所有异常的超类
2)Java中所有的异常类分为Error和Exception两大类
3)RuntimeException(运行时异常)
-
ArrayIndexOutOfBoundsException----数组下标越界
-
NullPointException----空指针异常
-
ArithmeticException----算数异常
-
MissingResourceException----丢失资源
-
ClassNotFoundException----找不到类等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理
4)Error和Exception的区别,Error通常时=是灾难性的致命的错误,是程序无法处理和控制的,当出现这些异常时,JVM会终止线程,程序就崩掉了;而Exception通常可以被程序处理掉,并且应该养成在程序中尽可能处理这些异常的习惯
异常处理
-
关键字:try catch finally throw throws
1)finally 用于善后工作,多用与IO流处理时,关闭资源
2)假设需要捕获多个异常,需要从小到大的去捕获
3)快捷键创建try、if、where等语句,选中需要被操作的语句,Ctrl+Alt+t
-
主动抛出异常:throw----多用于方法中
public void test( int a){ if(a == 0){ throw new ArithmeticExceptin(); //主动抛出异常 } }
-
向上抛出异常:throws----不想在某个方法中抛出异常,或者这个方法中处理不了这个异常,就向上抛出
public void test(int a) throws ArithmeticExceptin{ //向上抛出异常 if(a == 0){ throw new ArithmeticExceptin(); //主动抛出异常 } } public Class A{ public static void main(String[] args){ try{ test(0); }catch(ArithmeticExceptin e){ e.printStackTrace(); } } }
自定义异常
-
创建自定义异常类
-
在方法中通过throw关键字抛出异常对象
-
如果在当前处理异常,则try-catch捕获异常处理即可;否则在方法的声明出通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
-
在出现异常方法的调用者中捕获并处理异常