一、多态
1.多态概述
同类型对象,执行同一行为,表现出不同的行为特征;
1.1多态常见形式
父类类型 对象名称 = new 子类构造器;接口 对象名称 = new 实现类构造器;
1.2 多态中成员访问特点
- 方法调用:编译看左边,运行看右边(多态侧重行为多态)
- 编译,查看父类中是否有对应方法
- 运行,执行子类方法结果
- 变量调用:编译看左边,运行看左边;
1.3 多态前提
- 有继承/实现关系;
- 有父类引用指向子类对象;
- 有方法重写
public abstract class Animal {
public String name = "动物原型";
public abstract void run();
}
public class Dog extends Animal{
public String name = "Dog原型";
@Override
public void run() {
System.out.println("Dog is run");
}
}
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
//编译看左,运行看右
//Dog is run
dog.run();
System.out.println(dog.name);
Animal cat = new Cat();
cat.run();
//动物原型,变量采用父类
System.out.println(cat.name);
}
}
2.多态定义方法、优势和问题
| 定义方法 | 定义方法,采用父类对象,兼容性强,接收一切子类对象,体现多态扩展性; |
|---|---|
| 优势 | 多态形态下,右边对象实现解耦合,便于扩展维护; 右侧的子类对象可以调换,不影响其他代码 |
| 问题 | 以父类为主,使用子类独有方法,报错 |
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
go(dog);
Cat cat = new Cat();
go(cat);
//dog and cat 在go()中效果一致
}
/**
* 要求所有动物都可用
* @param animal
*/
public static void go(Animal animal){
System.out.println("Start Up");
animal.run();
System.out.println("Time Out");
}
}
3.多态下引用数据类型的数据转换
| 类型转换 | 范围 | 作用 | |
|---|---|---|---|
| 自动类型转换 | 从子到父,范围小到大 | 子类对象赋值给父类类型的变量转换; | |
| 强制类型转换 | 父到子 | 子类 对象变量 = (子类)父类类型变量; | 解决多态下劣势,实现调用子类多有功能 |
3.1 数据转换实例
//自动类型转换
Animal a = new Dog();
a.run();
//强制类型转换
Animal b = new Cat();
b.run();
//b由父类型强制转换为子类型
Cat cat = (Cat) b;
//转为子类型,可以使用独有方法
cat.eatFish();
3.2 转型后类型和对象真实类型不是同一种,类型异常ClassCastException
//强制类型转换,编译阶段不报错(有继承或者实现关系可以强转),运行时可能出错;类型异常ClassCastException
//Dog dog = (Dog) b;
3.3 Java建议强制转换前 使用instanceof判断
/**
* 要求所有动物都可用
* 不清楚传进来的动物类型
* @param animal
*/
public static void go(Animal animal){
if (animal instanceof Dog){
Dog dog = (Dog) animal;
dog.lookDoor();
}else if (animal instanceof Cat){
Cat cat = (Cat) animal;
cat.eatFish();
}
}
4.多态综合实例
public interface USB {
void connect();
void unConnect();
}
public class KeyBoard implements USB{
private String name;
public KeyBoard(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name+"成功连接");
}
/**
* 独有功能
*/
public void keyDown(){
System.out.println(name+"键入字符");
}
@Override
public void unConnect() {
System.out.println(name+"成功拔出");
}
}
public class Mouse implements USB{
其他同上
/**
* 独有功能
*/
public void dbClick(){
System.out.println(name+"单击图标");
}
}
public class Computer {
其他同上
/**
* 提供USB设备安装接口
*/
public void installUSB(USB usb){
usb.connect();
//判断子类类型,强转实现功能
if (usb instanceof KeyBoard){
KeyBoard keyBoard = (KeyBoard) usb;
keyBoard.keyDown();
}else if (usb instanceof Mouse){
Mouse mouse = (Mouse) usb;
mouse.dbClick();
}
usb.unConnect();
}
}
public class Test {
public static void main(String[] args) {
Computer computer = new Computer("机械师T58");
computer.start();
KeyBoard keyBoard = new KeyBoard("PHILIPS");
//插入键盘
computer.installUSB(keyBoard);
Mouse mouse = new Mouse("罗技");
computer.installUSB(mouse);
}
}
二、内部类
1.概述
定义在一个类内的类,里面类可以理解为寄生,外面是宿主;
public class People {
public class Heart {
}
}
2.使用场景
- 一个事务内部,还有一个部分需要完整的结构描述,并且这个内部结构只为外部事务服务,可以用内部类设计
- (人和各人体器官)(汽车和发动机)与现实对接
- 内部类通常可以方便访问外部类成员,包括私有
- 内部类提供更好的封装性,内部类本身可以用private protected修饰,封装做更多控制
- 外部类只能用public修饰
3.内部类分类
3.1静态内部类
-
和内部类无区别
-
Outer.inner inner = new Outer.inner(); -
静态内部类可以直接访问外部类静态成员;共享
-
静态内部类不可以直接访问外部类实例成员;需要外部类对象
3.2成员内部类(非静态)
-
JDK16后运行成员内部静态
-
Outer.inner inner = new Outer().new inner(); -
成员内部类可以直接访问外部类静态成员;共享
-
成员内部类的实例方法可以直接访问外部类实例成员;先有外部,才有内部;
-
/** * 面试试题: * 输出对应值 */ public class People { private int heartbeat = 158; public class Heart{ private int heartbeat = 110; public void show(){ int heartbeat = 78; System.out.println(heartbeat);//78 System.out.println(this.heartbeat);//110 System.out.println(People.this.heartbeat);//158 } } }
3.3 局部内部类
-
放在方法,代码块,构造器等执行体中;
-
局部 内部类产生class文件:外部类$内部类
3.4匿名内部类(重点)
- 本质:没有名字的局部内部类,放在方法,代码块等执行体中;
- 作用:方便创建子类对象,为了简化代码编写
- 特点总结:
- 匿名内部类写出来就会产生一个匿名对象
- 匿名对象类型是当前new的类的子类
public class Test {
public static void main(String[] args) {
Animal tiger = new Tiger();
tiger.run();
//匿名内部类
Animal rabbit = new Animal() {
@Override
public void run() {
System.out.println("兔子跑");
}
};
rabbit.run();
}
}
class Tiger extends Animal{
@Override
public void run() {
System.out.println("老虎跑");
}
}
abstract class Animal{
public abstract void run();
}
3.4.1匿名内部类常见使用形式
匿名内部类可以作为方法的实际参数进行传输;
public class Swim {
public static void main(String[] args) {
Swimming student = new Swimming() {
@Override
public void swim() {
System.out.println("学生游泳");
}
};
goSwim(student);
goSwim(new Swimming() {
@Override
public void swim() {
System.out.println("teacher游泳");
}
});
}
public static void goSwim(Swimming swimming){
System.out.println("开始");
swimming.swim();
System.out.println("结束");
}
}
interface Swimming{
void swim();
}
3.4.2 常用使用场景
- 开发中不是主动去定义匿名内部类代码,别人需要我们写才会用
- 匿名内部类代码实现代码进一步简化
public class Test3 {
public static void main(String[] args) {
//窗口
JFrame win = new JFrame("清理垃圾界面");
//画布创建
JPanel jPanel = new JPanel();
win.add(jPanel);
JButton btn1 = new JButton("清理");
JButton btn2 = new JButton("二次清理");
//匿名内部类
btn1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(win,"垃圾清理开始!");
}
});
//匿名内部类:最终目的简化代码
btn2.addActionListener(e -> JOptionPane.showMessageDialog(win,"二次垃圾清理开始!") );
jPanel.add(btn1);
jPanel.add(btn2);
//窗口宽高,居中,显示
win.setSize(400,300);
win.setLocationRelativeTo(null);
win.setVisible(true);
}
}
三、包装类
1.包装类:8种基本数据类型的引用类
| 基本数据类型 | 引用数据类型 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| char | Character |
| float | Float |
| double | Double |
| boolean | Boolean |
2.为什么提供包装类
- java为了实现一切皆对象;
- 集合和泛型只能支持包装类型;
3.自动装箱拆箱
| 自动装箱 | 基本数据类型变量可以直接赋值给包装类型变量 |
|---|---|
| 自动拆箱 | 包装类型变量可以直接赋值给基本数据类型变量 |
4.包装类特有功能
- 包装类变量默认值null,容错率高;
- 可以把基本类型数据转为字符串类型;
toString()方法Integer.toString(基本类型数据)- 可以直接得到字符串类型
String rs = i +"";
- 可以把字符串类型数值转为真实数据类型(重点):
Integer.parseInt("字符串类型整数")Double.parsedouble("字符串类型小数")- 要去转换的String内容必须符合转换后要求;
RecordDate:2021/08/12