1-面向对象-高级
1.继承
java是单继承和多重继承,不能多继承
子类继承父类在内存中的创建过程:
首先将在堆中开辟空间创建父类,然后创建子类,可以看作子类中通过super引用创建的父类。调用方法时首先在子类本身中寻找方法,如果没有找到就去父类中找。
例如,Student类继承Person类,内存模型如下所示:
2.super
- super访问构造方法
- super访问属性
- super访问方法
前面说到,创建子类时会首先创建父类,默认情况下,创建父类是通过无参构造创建的。如果需要指定参数需在子类无参构造方法中通过super()调用父类有参构造方法,代码如下
class Student extends Person4{
//默认无参构造是调用父类的无参构造
//public Student() {
// super();
//}
public Student() {
//调用父类有参构造,设置初始值
super("默认姓名",100);
//假设父类中sex属性是public或者protected,可以这样直接调用
super.sex = "男";
}
public Student(String name, int age) {
super(name, age);
}
}
super就像一个变量引用了父类的实例,通过这个变量可以操作父类。
3.重写
子类对父类中的方法进行重新定义,重新需满足以下条件:
- 参数列表与被重写的方法完全一致(参数长度、类型、顺序)
- 返回值与被重写的方法完全一致
- 访问权限不能低于被重写的方法
- static和private方法不能被重写
- 必须发生在子父类之间
重写和重载区别:
重写(override) | 重载(overload) | |
---|---|---|
范围 | 子类和父类 | 一个类中 |
返回值 | 返回值相同 | 无限制 |
参数列表 | 必须相同 | 必须不同 |
访问权限 | 子类不得低于父类 | 无限制 |
异常 | 异常范围可以更小,但不能抛出新的异常 | 无限制 |
4.final
-
用于修饰变量,就成了常量,无法再次赋值(只能赋值一次)。
修饰的局部变量成为常量,可以先声明再赋值。
修饰的成员变量,必须声明的同时赋值。
-
用于修饰类:表示该类不能被继承
-
用于修饰方法:表示方法不能被重写
5.抽象类
-
抽象类不能被实例化,必须被其他类所继承,否则是没有意义的。
-
抽象类中不一定有抽象方法,但抽象方法一定在抽象类(或接口)中。
-
继承抽象类的子类(如果不是抽象类)必须重写(覆写)父类中的抽象方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WAIwDQhf-1630292139348)(C:\Users\12416\AppData\Roaming\Typora\typora-user-images\image-20210824163630871.png)]
6.接口
7.多态
多态分为编译时多态(方法重载)和运行时多态(方法重写),要实现多态有两个条件:
1.子类继承父类并重写父类方法
2.通过父类引用子类对象
这样通过父类引用调用同一个方法时就会根据子类对象的不同而表现出不同的行为。
重载和重写区别:
- 重载在一个方法中,重写在子类和父类中
- 重载不受返回值的影响,重写返回值必须相同
- 重写访问权限只能更高,子类访问权限不能低于父类
8.Object
-
toString()
建议所有类都重写toString方法
-
equals
object中默认equals是比较两个对象的地址。String类中重写了该方法
9.内部类(了解,用的不多)
- 成员内部类
- 局部内部类
- 匿名内部类
- 静态内部类
10.包装类
11.可变长参数
-
方法名(String… args){} 可把args看作数组来使用
-
当同时有普通参数和可变长参数时可变参数要放最后。
12.递归
- 自己调用自己
13.异常
异常分为受检异常(非运行时异常)和非受检异常(运行时异常RuntimeException),前者在未运行程序时就会检查(在编译的时候就会检查到错误),而后者只有在运行时才能发现异常。
finally代码块中必然会被执行,除非关闭程序。在代码中只有一种情况不会执行finally,即执行了System.exit()方法,此方法会直接退出程序,导致不能执行finally
finally两点重点:1.必然执行2.返回时机
public class Demo2 {
public static void main(String[] args) {
//输出28
System.out.println(haha().age);
}
public static Person haha(){
Person p = new Person();
try{
p.age = 18;
//准备返回前 对p进行备份,注意备份的是对象的地址
return p;
}catch (Exception e){
return null;
}finally {
//改变对象的值,对象只有一个,p和备份都指向这个对象,所以最终对象的age值是28
p.age = 28;
}
}
}
class Person{
int age;
}
public class Demo {
public static void main(String[] args) {
//输出10
System.out.println(haha());
}
public static int haha(){
int a;
try{
a = 10;
//在返回前对a的值10进行备份,准备返回
return a;
}catch (Exception e){
return -1;
}finally {
//准备返回时执行finally 这时改变的是a的值,
//但最终返回的是改变a之前的备份值,所以最终返回10而不是20
a = 20;
}
}
}
-
throws
和try catch
如何选择:throws代表:我告诉你我这个类可能会出现什么异常,记得去处理哈。
异常是否应该抛出去?
如果是因为传递参数导致异常就选择throws抛出去,代表不处理异常,返回给调用者去处理。
throw
//自己throw一个异常
throw new RuntimeException("123");
-
自定义异常
2-常用类库
1.泛型
编译时会去泛型化,即编译成真正的类型而非泛型。
泛型最广的用法是:泛型类
泛型的主要作用:
- 提高代码的复用率
- 泛型中的类型在使用时指定 不需要强制转换类型,更加安全
2.Objects类
equals方法
即使a为空也不会报空指针异常,原因在于首先判断了a!=null
其余方法待整理
3.Math类
一些常用方法:
abs()求绝对值
min(a,b)求最小值
max(a,b)求最大值
round(-100.5) = -100 四舍五入 负数直接舍去,round(100.5) = 101 正数直接进一
floor(-3.5)小于等于-3.5的最大整数 即 -4.0
floor(3.5)小于等于3.5的最大整数 即 3.0
ceil(-3.5)大于等于-3.5的最大整数 即 -3.0
ceil(3.5)大于等于3.5的最大整数 即 4.0
数学类首先考虑查看 Math类api
4.Arrays类
-
二分查找的方法binarySearch
-
比较字典序compare
-
排序方法sort
-
输出数组的字符串形式toString
-
数组扩容copyOf(原数组,新数组的长度):内部调用了System.arraycopy()方法
//Arrays.copyOf演示 public static void main(String[] args) { int[] a = {1,5,23,5,2,2,5,6,7,3}; a=Arrays.copyOf(a,15); System.out.println(a.length); System.out.println(Arrays.toString(a)); } 输出结果: 15 [1, 5, 23, 5, 2, 2, 5, 6, 7, 3, 0, 0, 0, 0, 0]
5.BigDecimal
最常用的就是以下一些方法:
可以解决double类运算的误差问题,如输出0.1+0.2结果是:0.30000000000000004,存在误差。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l9DLOdvI-1630292139364)(C:\Users\12416\AppData\Roaming\Typora\typora-user-images\image-20210828231238081.png)]
构造方法传递一个String类型
通过一个bigdecimal对象的add方法会产生一个bigdecimal的对象,这样运算的结果是精准的:
public static void main(String[] args) {
BigDecimal b = new BigDecimal("0.1");
BigDecimal b2 = b.add(new BigDecimal("0.2"));
System.out.println(b2);
}
结果是:0.3
//还可以将结果转换成想要的数据类型如
//b2.intValue()转换成int类型
//b2.doubleValue()转换成double类型
5.Date类
已过时:某些方法在使用中可能出行bug,官方可能就会提示用户该方法已过时,不推荐使用。
如果想获取年月日小时分钟秒,要通过
Calendar
类,该类可以根据不同地区生成该地区的时间,适合国际化操作,而==DateFormat
类用于格式化和解析日期字符串==,Date类中方法大部分均已过时(不包括两个未过时构造方法),只有几个方法没有过时如getTime()获取毫秒数,返回一个long类型的自1970年1月1日的00:00:00毫秒数,等几个方法
一些未过时方法:
- boolean after()
- boolean before()
- long getTime()
- 等等两三个方法,具体查看api文档
6.DateFormat类
该类是抽象类,其实现子类只有SimpleDateFormat类。
常用方法:
public static void main(String[] args) throws ParseException {
/*
* y: 年
* M: 月
* d: 日
* H: 时
* m: 分
* s:秒
* */
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//format()方法将date类型对象转换成字符串
String text = format.format(new Date());
System.out.println(text);
//parse()方法将指定的格式字符串转换成date对象
Date date = format.parse("2021/8/29 9:11:00");
System.out.println(date);
System.out.println(date.getTime());
}
7.Calendar类(日历类)
常用方法:get()、set()、add()、getTime() 其余:getActualMaxmum
该类是抽象类,不能实例化,需要通过getInstance()方法获取实例,自动根据时区获取当前日历
8.System类
9.String类绝对重点
- trim():去除首尾空格
- split():分割
- charAt()、indexOf()、endWith()、startWith()、substring()、replace()等等
String类大部分方法都十分有用
10.StringBuilder(非线程安全)/StringBuffer(线程安全)
操作字符串性能:StringBuilder>StringBuffer>String
- reverse()反转
- append()、delete()、deleteCharAt()、insert()、toString()等等