多态
多态按照我的理解就是一个继承了父类的子类可以看作是它的父类。
- 多态的条件
- 要有子父类关系
- 要有方法重写
- 要有父类引用指向子类对象
优缺点
- 优点:提高了代码的扩展性和复用性,可以当作形参接收任意类型的子类对象
- 缺点:不能使用子类的特有属性和方法
多态成员访问的特点
成员变量
- 编译看左边(父类),运行看左边(父类)(静态绑定),使用的仍然是父类的成员变量,没有多态,这种静态绑定在一般情况下使用极少,成员变量一般都是私有化的。
成员方法
- 编译看左边,运行看右边,这是动态绑定。子类中如果堆父类中的方法进行了重写,父类中的方法无论如何都无法被访问,这是动态绑定的结果。
静态方法
编译看左边,运行看左边。子类其实并不能重写父类的静态方法,所以当然不能访问子类的方法。
多态转型
向上转型
将子类对象看作是父类类型,这种情况下,无法调用子类的特有的功能。
向下转型
将父类引用指向的子类对象再转回子类类型,这种转换是有风险的,再转换之前一定要使用instanceof关键字判断以下。
final关键字
final修饰的特点
- 修饰类,类不能被继承
- 修饰变量,变量就成了常量,只能被赋值一次(初始化的时候赋值)
修饰方法,方法不能被重写
修饰基本数据类型,是值不能被改变
修饰引用数据类型,是地址值不能被改变,对象中的属性可以被改变,意思是这个引用只能引用这个对象,不能引用其他对象。
final修饰成员变量的初始化时机
- 对于非静态成员变量而言,是在对象初始化完成之前,有三个地方,成员变量定义时,构造代码块,构造方法。
- 对于静态成员变量而言,是在类初始化完成前。有两个地方,静态成员变量定义时,静态代码块。
抽象类
抽象类的主要作用是为了定义规则,抽象类及其中的抽象方法必须用abstract关键字进行修饰。
抽象类的特点
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类。
抽象类不能被直接实例化,必须由子类继承并重写抽象方法来实例化。
抽象类的子类要么是抽象类,这种情况不必重写所有的抽象方法,要么是普通类,必须重写抽象类的所有抽象方法。
抽象类中的非抽象方法子类可以直接继承,提高了重用性,抽象方法规定了子类必须重写的方法,形成了一套规范,这样所有继承了这个抽象类的子类都必须具有相同的接口。
Java值传递的三种方式
八种基本数据类型传递的是值,引用数据类型传递的是址,也就说把地址复制一份,String 比较特殊, 它虽然是一个引用变量, 但是它传递的是具体的数值
String 首先是在对内存中创建一个对象,对象里面封装的是常量值, 然后将数值放入到常量池中, 再指向String。
接口
接口是更加抽象的“抽象类”,接口中必须都是抽象方法,不能有具体的实现,Java中的接口用interface来标识。
接口的特点
接口时用来实现(implements)的,而抽象类是用来继承的。
接口不能被直接实例化,但可以通过多态的方式实例化。
如果一个类要实现一个接口就必须重写这个接口中所有的抽象方法。
接口中的方法默认都是public abstract,接口中的成员变量默认都是public static final。
接口可以继承接口。
一个类可以实现多个接口,但是只能继承一个抽象类。
接口与类之间的关系
根据我的理解,接口其实也是一种类,只不过它是一种比较特殊的类,普通的类只能单继承,但是接口可以多实现。
设计模型之模板模型
模板模型是指使用接口制定规则,然后子类根据实现不同的方法内部代码。实现类和接口中的内容保持一致,有利于提高代码的扩展性。
内部类
内部类是指在类中的类,根据内部类出现的位置以及特点,可以将内部类分为四类:成员内部类、静态内部类、局部内部类与匿名内部类。
成员内部类
成员内部类我觉得有点类似成员变量,只有在外部类的对象 创建之后才能创建成员内部类的对象,当然,内部类可以直接访问外部类的成员,包括私有,因为外部类的对象已经创建了,但是外部类调用内部类的方法,必须先创建对象,因为外部类的对象有了但是内部类的对象不一定有。要创建一个内部类的对象,应该这样写:外部类.内部类 对象名 = new 外部类().new 内部类()。
内部类的权限
内部类的权限和成员方法一样,可以有private 默认 protected public,但是外部类只能是public和默认的。
静态内部类
静态内部类有点像静态的成员变量,在类加载的时候就创建了,所以静态内部类和外部类之间没有那么强的关系。创建静态内部类不需要先创建外部类。所以,外部类要想调用内部类的方法,必须先创建内部类的对象,同时,内部类要想使用外部类的方法,也必须调用创建外部类的对象。内部类中如果有静态方法,那么内部类也必须时静态的
局部内部类
定义在类中的方法中的内部类叫做局部内部类,和匿名内部类的区别就是在方法中需要使用多次,所以不能使用匿名内部类。局部内部类的作用范围仅限于本方法中;局部内部类在访问它所在方法中的局部变量必须用final修饰,因为普通的局部变量的生命周期是跟着方法走的,方法弹栈了局部变量也就消失了,使用final修饰后局部变量就变成了常量,方法弹栈后常量依然存在。
匿名内部类
匿名内部类是局部内部类的简写形式,一般用于定义接口的或者类的子类,匿名内部类就是没有名字的内部类。
使用
必须存在一个类,可以是具体的类,也可以是抽象类,或者接口。
匿名内部类适用于仅使用一次的情况。
异常
分类
- Error 错误,比如数据库崩溃,服务器宕机
- Exception 异常
- 编译时异常:编译无法通过的异常
- 运行时异常:导致程序停止运行的异常
异常的处理
- JVM处理异常:打印异常信息并停止运行
手动处理异常:
捕获异常并处理:try{} catch(){} finally{} 程序仍然能继续运行
抛出异常:在方法声明后加上throws关键字 程序会将异常抛出,如果没有捕获的话程序会中止运行
注意事项
- 多个catch处理异常时,遵循从上往下的原则。所以应当将小的异常放在上面,大的异常放在下面。
finally中的代码一定会执行,除非虚拟机退出,主要用于释放资源,比如关闭数据库连接。
自定义异常
继承Exception必须抛出,需要在编译前处理;继承RuntimeException不需要抛出,编译前不需要处理。
二维数组
二维数组就是在数组中存放数组,外层数组中存放的是数组的引用,和一维数组一样,初始化方式也可以分为静态初始化与动态初始化。静态初始化就是程序员自己指定数组中的内容,长度由JVM自行判断;动态初始化用户指定数组的长度,由JVM自行提供默认值。
权限修饰符
权限修饰符是为了确定类或者类成员的使用范围,按照权限从大到小:public、protected、默认、private。
- public:本项目下都可以使用
protected:同一包下、不同包中子父类调用。子父类调用指的是super关键字,不能new一个父类对象然后调用。
默认:同一包下
private:同一类中
注意:Java中的包其实就是文件夹的意思,是为了解决相同类名的问题。在我们写程序的时候默认是使用当前包下的类,如果我们想使用其他包下的类需要使用import关键字导入其他包或者在类的前面写上包名。
Object类
Object是Java中所有类的祖先,所有的类都是直接或者间接继承Object类。
常用方法
hashCode() 返回该对象的哈希码值,默认情况下根据对象的地址来计算。
toString() 默认返回的是对象的地址,JavaBean 中一定要重写,System.out.println()方法会调用toString方法。
equals()比较两个对象的内容是否相等,默认比较的是地址值,所以永远返回的是false。== 和 equals()的区别:
== 是一个比较运算符,既可以比较基本数据类型,也可以比较引用数据类型,比较基本数据类型时比较的是值,比较引用数据类型时比较的是地址。
equals()只能比较引用数据类型,默认比较的是地址,但是可以重写,重写之后比较的就是重写的内容。一般equals与hashCode同步重写,hashCode不同,equals一定不同,但是equals不等,hashCode有可能相等,因为hash算法的问题。
String类
String是引用数据类型,字符串类,不可变字符串。
常用方法
- public String(String original) 将字符串常量值转换为字符串
- boolean equals(Object obj) 比较字符串的内容是否相等,一般将字符串常量放在外面,因为对象有可能为空。
- int length() 获取字符串的长度
- char charAt(int index) 获取指定索引位置的字符
- int indexOf(int ch) 返回指定字符在此字符串中第一次出现的位置
- int lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现的位置
- String substring(int start) 从指定位置开始复制字符串,默认到末尾
- static String valueOf() 可以将任意类型的数据转换为字符串,这是String类的静态方法
- String concat(String str) 字符串拼接,不会创建新的字符串,比+效率高
- String[] split(String regex) 按照指定规则来切割字符串