一、继承
1.认识什么是继承、继承解决的问题
概述:继承可以让两个类产生父子关系,提高代码的复用性
解决的问题:共性抽取
2.继承的格式
public class 父类{
//成员变量
//构造器
//成员方法
}
public class 子类 extends 父类{
//成员变量
//构造器
//成员方法
}
3.继承后,各个成员的访问特点
1)成员变量、成员方法的访问特点:
遵循就近原则:子类有就用子类的,子类没有就用父类的
this.本类成员变量:访问本类的成员变量
super.本类成员方法:访问父类的成员方法
this.父类成员变量:访问本类的成员变量
super.父类成员方法:访问父类的成员方法
2)构造器的访问特点:
a:子类中所有的构造器,都会默认访问父类中空参数的构造器
原因:因为子类构造器的第一行默认有一句super()
b:如果子类不想访问父类空参数构造,可以手动通过super(参数)访问父类有参数构造器
注意:如果自己写了有参数构造器,空参数构造器就没了
4.方法重写
1)什么是方法重写?
答:子类和父类有一模一样的方法声明,但是方法体不一样,这种现象叫做方法重写.
2)方法重写的语法要求
a:子类重写父类方法方法名、形参列表、返回值类型必须和父类一样
b:子类重写父类方法,建议加上一个@Overide注解,起到语法检查的作用
c:子类不能重复父类的私有方法
d:子类重写父类方法时,权限必须>=父类权限
private < 缺省(不写权限修饰符) < protected < public
3)方法重写的应用
打印对象地址值的原理?
答:因为在Object类中有一个toString()方法,返回对象的地址值,
打印语句底层会自动调用对象的toString(),默认执行的就是Object类的toString()方法,
所以会打印对象的地址
如果我们自己写的类,不想打印对象的地址,我们可以在自己的类中重写toString()方法
public class Student /*extends Object*/{
private String name;
private int age;
//此处省略了get和set方法,自己补全
//alt+insert 选择 toString()
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
二、final关键字的特点
1.final修饰类: 不能被继承
2.final修饰方法:不能被重写
3.final修饰变量: 在第一次赋值之后,不能被修改
final修饰基本类型变量: 值不能被修改
final修饰引用类型变量: 地址值不能被修改
三、static修饰符的用法
1. static读作静态,可以修饰类的成员变量(类变量、静态变量)和成员方法(类方法、静态方法)
2. static修饰成员的调用方式:
第一种:使用类名直接调用
第二种:使用对象调用(这种写法不推荐)
3. static使用的注意事项
1)静态方法中,只能访问静态的成员
2)实例方法中,既可以访问静态成员,也可以实例成员
四、包、权限修饰符
1.包:包本质上是一个文件夹,用来对类文件进行分类管理
定义包: package 包名;
2.导包:把不同包下的类入到到其他类中来使用
import java.util.Scanner;
3.带包名的访问: 包名.类名 变量名 = new 包名.类名();
java.util.ArrayList<String> list = new java.util.ArrayList<>();
4.权限修饰符
作用:用来修饰类的成员,不同的权限修饰符能够被访问的范围不同
private访问范围: 只能在本类中被访问
缺省(默认): 可以在本类、本包中被访问
propected访问范围:可以在本类、本包、不同包下的子类中被访问
public访问范围: 可以在本类、本包、不同包下的子类、无关类中被访问
五、抽象类
1.abstract是抽象的意思,可以用来修饰类和方法
2.抽象类和抽象方法的使用规则
1)抽象类不能创建对象、抽象方法没有方法体
2)抽象类被子类继承,子类必须重写所有的抽象方法;否则这个类也必须是抽象类
3)抽象类中可以有抽象方法、也可以有非抽象方法
4)抽象方法必须放在抽象类中
六、接口
1.接口的定义
public interface 接口名{
//常量:默认被public static final修饰
public static final int num = 10;
//抽象方法: 默认被 public abstract修饰
public abstract void test();
}
2.接口的使用:必须要让类来实现、而且可以多实现
public interface 接口1{
public abstract void tes1();
}
public interface 接口2{
public abstract void tes2();
}
//重写方法的快捷键:alt+entry
public class 类名 implements 接口1, 接口2{
@Override
public void test1(){
}
@Override
public void test2(){
}
}
3.接口和抽象类的区别:
1)接口可以多少实现,类只能单继承
2)接口可以继承多个接口
4.JDK8接口新增的方法(实际工作中,自己用得很少,了解)
默认方法: 被 public default 修饰; 可选重写
静态方法: 被 public static 修饰; 被接口名调用
私有方法: 被 private 修饰; 只能在本接口中被调用
七、多态
1.多态的形式:
父类 变量 = 子类对象;
接口 变量 = 实现类对象;
2.多态的好处和弊端:
好处:体现在方法上,把一个方法的形参写成父类/接口类型,调用方法时可以传递子类/实现类的对象.
方法的兼容性更强
public class Feeder{
//形参类型是Animal类型,Animal a既能接收Dog对象,也能接收Cat对象
public void feed(Animal a){
a.eat();
}
}
弊端:多态的形式下,不能直接调用子类的特有方法。
3.多态的转型:把父类类型的变量强制转换为子类
//多态写法
Animal a = new Dog();
if(a instanceof Dog){
Dog dog = (Dog)a;
dog.特有方法();
}
八、内部类
1.成员内部类【了解】
public class Outer{
private String name = "张三"
//成员内部类
public class Inner{
private String name = "李四";
public void test(){
int String name = "王五";
System.out.println(name); //"王五"
System.out.println(this.name);//"李四"
System.out.println(Outer.this.name); //"张三"
}
}
}
创建成员内部类对象的格式
Outer.Inner in = new Outer().new Inner();
in.test();
2.静态内部类【了解】
public class Outer{
private String name = "张三"
//成员内部类
public static class Inner{
private String name = "李四";
public void test(){
int String name = "王五";
System.out.println(name); //"王五"
System.out.println(this.name);//"李四"
System.out.println(Outer.this.name); //"张三"
}
}
}
创建成员内部类对象的格式
Outer.Inner in = new Outer.Inner();
in.test();
3.局部内部类【了解】
public class Outer{
public void test(){
//局部内部类:只能在方法中被使用
class Inner{
public void show(){
}
}
//创建Inner的对象,才能调用show方法
Inner in = new Inner();
in.show();
}
}
4.匿名内部类【掌握】
格式:new 父类/接口(){
重写父类/接口的方法
}
本质:匿名内部类的本质是一个父类的子类对象、接口的实现类对象。
应用场景:一般是调用方法的时候,如果方法的形参是接口,那么把匿名内部类作为参数传递.
ArrayList<String> list = new ArrayList<>();
list.add("大雄");
list.add("静香");
list.add("胖虎");
list.add("小夫");
//遍历集合:API中提供了一个方法叫做forEach;
//调用forEach方法,方法的形参是一个Consumer接口,
//这时就可以传递Consumer接口的实现类对象.
//原理:forEach方法底层会自动帮我们遍历集合,
//然后调用accept方法,元素传递给s,就可以打印了。
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
九、常用API【掌握】
1.Object类:
Object是所有类的父类,任何一个类的对象(包括数组)都可以调用Object类的方法。
public String toString() 【推荐】
/*
把一个对象转换为字符串形式,默认为地址值的十六进制形式:
“类名@地址值”
对开发者而言更重要对象内部封装的数据
一般子类复写toString方法把对象转换为属性值
*/
public boolean equals(Object obj) 【推荐】
/*
equals用于判断两个对象是否相等,本质上比较对象的地址值。
对开发者而言更重要的是对象内部封装的数据,而不是地址值。
一般子类复写equals方法比较对象的属性值,更符合实际需求
*/
public int hashCode() 【推荐】
//返回对象的哈希值
2.数据类型包装类
2.1作用:把基本数据类型数据封装为对象,每一个基本数据类型都有一个包装类与之对应
基本类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
包装类如何创建对象
Integer a = Integer.valueOf(10);
Double b = Double.valueOf(3.14);
2.2利用包装类对字符串和基本类型数据进行转换
//需求1:把"12345"转换为12345
int i = Integer.parseInt("12345");
System.out.println(i);
//需求2:把12345转换为"12345"
String s1 = Integer.toString(12345);
2.3演示自动装箱和自动拆箱
Integer x = 10; //底层会自动调用 Integer x = Integer.valueOf(10);
int y = x; //底层会自动调用 int y = x.intValue();
System.out.println(x);
System.out.println(y);
System.out.println("---------------------");
//面试题:
//如果把基本类型的数据直接赋值给Integer类型,
//数据范围在[-128~127]内,不会重新创建对象,否则就会重新创建对象;
Integer n = 127;
Integer m = 127;
System.out.println(n == m); //true
Integer n1 = Integer.valueOf(128);
Integer m1 = 128;
System.out.println(n1 == m1); //false
3.BigDecimal类
作用:对小数进行精确运算,解决double类型或者float数据运算进度损失问题.
使用步骤:
第一步:把参数运算的数据都封装为BigDecimal对象,调用valueOf(数据)方法
第二步:调用BigDecimal类提供的方法对数据进行四则运算(加、减、乘、除)
第一步:把参数运算的数据都封装为BigDecimal对象,调用valueOf(数据)方法
BigDecimal bd1 = BigDecimal.valueOf(10);
BigDecimal bd2 = BigDecimal.valueOf(3);
第二步:调用BigDecimal类提供的方法对数据进行四则运算(加、减、乘、除)
//求和
BigDecimal sum = bd1.add(bd2);
System.out.println(sum); //13
//求差
BigDecimal sub = bd1.subtract(bd2);
System.out.println(sub); //7
//乘法
BigDecimal mul = bd1.multiply(bd2);
System.out.println(mul); //30
//除法
BigDecimal div = bd1.divide(bd2);
System.out.println(div); //10/3 除不尽,这里会报错
//注意:如果除不尽,就会出现ArithmeticException异常
//解决办法: 保留指定的小数位
/*
参数1:除数
参数2:保留小数的位数
参数3:舍入模式(保留小数的方式)
RoundingMode.HALF_UP 四舍五入
RoundingMode.UP 不管是否满五,都往前进一位
RoundingMode.DOWN 不管是否满五,都舍弃
*/
BigDecimal div = bd1.divide(bd2,2, RoundingMode.HALF_UP);
System.out.println(div); //3.33
4.System类
作用:系统类,提供了一些获取系统数据的方法(毫秒值、环境变量等),还可以复制数组.
方法的含义
//退出虚拟机,参数一般写一个0就可以了
public static void exit(int status)
//获取当前系统时间的毫秒值(从1970年1月1日0时0分0秒到现在的时间间隔)
public static long currentTimeMillis()
//复制数组
public static void arraycopy(原数组, 原数组的起始位置, 目标数组,
目标数组的起始位置, 复制的元素个数)
十、枚举【掌握】
1.枚举是什么?
枚举是一个特殊的类,也是有字节码的。 使用enum来定义。
2.格式:
public enum 枚举类名{
//枚举项一般都是用大写字母的单词表示
枚举项1, 枚举项2...;
}
3.枚举举例
public enum Direction {
//枚举项是枚举类的对象
UP,DOWN,LEFT,RIGHT;
}
4.枚举类的应用场景
枚举一般是作为信息标志符使用,针对不同的枚举项做出不同的处理。
//枚举的应用:一般在开发中作为信息标志符,针对不同的枚举项做出不同的处理
public static void movie(Direction direction){
switch (direction){
case UP:
System.out.println("玛丽向上飞了一下");
break;
case DOWN:
System.out.println("玛丽向下蹲了一下");
break;
case LEFT:
System.out.println("玛丽向左跑了一下");
break;
case RIGHT:
System.out.println("玛丽向右跳了一下");
break;
}
}