面向对象高级语法

127 阅读6分钟

面向对象高级语法

1 内部类

1.1 成员内部类
1.1.1 作用

​ 在描述一个类的时候, 如果需要同时描述这个类的某一部分, 而且只用一次的情况下, 没必要另外创建一个类时, 可以使内部类来实现

1.1.2 格式
public class Outer{
	public class Inner{
	}
}
//如, 这里有一个在Animal 内部的 Cat类
class Animals{
xxxxx
    class Cat{
xxxxx
    }
}
1.1.3 特点

​ 内部类中可以定义普通的所有的数据

1.1.4 创建对象

​ Outer.Inner 对象名 = new Outer().new Inner();

​ 还拿上文中Animal的例子

Animals.Cat cat = new Animals("Tiger"). new Cat(21);

​ 可以理解为先拿取Animals的所在位置, 然后通过Animals内部的地址指向存在堆中另一块Cat类

1.1.5 使用

​ 可以使用外部类中所有的数据, 静态成员和实例成员.

​ 内部类的实例方法中,可以通过外部类.this访问外部类对象.

​ 成员内部类 ==> 调用内部类 -> this.xx ​ 外部类->外部类.this.xx

如:

public void  eat(){
    System.out.println("猫吃狗!");
    System.out.println(getAge()+" "+Animals.this.getName());
}
//我的内部类Cat中的方法调用了Outer类的Animals.this.getName, 结果调出为Tiger.
1.2 静态内部类
1.2.1 作用

​ 在描述一个类的时候, 如果需要同时描述这个类的某一部分, 可以使内部类来实现

1.2.2 格式
public class Outer{
     public static class Inner{
      }
}
1.2.3 特点

​ 内部类中可以定义普通的所有的数据

1.2.4 创建对象

​ Outer.Inner 对象名 = new Outer.Inner();

1.2.5 使用

​ 可以使用外部类的静态成员. 不能访问实例成员, 这点和静态变量/方法很相似

1.3 局部内部类

​ 很少用, 没咋关注.... 有用到再补充吧

1.4 匿名内部类(开发中常用)
1.4.1 作用

​ 便于创建子类对象

1.4.2 格式

​ 包括一个接口或者抽象类 和 构造匿名内部类指令

​ 1) 构造一个接口或抽象类

// 接口1
public interface SteeringWheel {
    void steer();
}

​ 2) 构造匿名内部类指令

格式:

new  抽象类()/接口(){
        重写抽象方法
}

一号例子, 构建匿名内部类:

public class Car {
    public static void main(String[] args) {
        // 构建匿名内部类
        // 构建道奇
        SteeringWheel dodge = new SteeringWheel() {
            @Override
            public void steer() {
                System.out.println("道奇开始转动");
            }
        };
        // 构建法拉利
        SteeringWheel Ferrari = new SteeringWheel() {
           @Override
            public void steer() {
                System.out.println("法拉利开始转动");
            }
        };

        // 调用rt函数
        raceTest(dodge);
        raceTest(Ferrari);
    }

    // rt函数, 测试
    public static void raceTest(SteeringWheel s){
        s.steer();
    }
}

还有一种类型,直接把匿名内部类当做方法的参数:

public interface USB {
    void plugin();
    void out();
}
public class Computer {
    public void use(USB usb){
        usb.plugin();
        usb.out();
    }
}
public class test {
    public static void main(String[] args) {
        Computer c = new Computer();
        c.use(new USB() {
            @Override
            public void plugin() {
                System.out.println("keyboard in ");
            }

            @Override
            public void out() {
                System.out.println("keyboard out");
            }
        });
    }
}
1.4.3 特点

​ 匿名内部类本质就是一个子类,并会立即创建出一个子类对象。

1.4.4 优点

​ 简化了类的创建,通过匿名内部类可以直接获取到一个子类对象, 也弥补了接口, 抽象类不能构造一个对象的缺点. 将会和接口配合在实际运用中多次出现.

1.4.5 使用场景

​ 一般用于作为参数传递给方法, 如果某一个子类只需要使用一次, 我们就可以使用匿名内部类简化类的创建.

2 枚举

2.1 概念

​ 枚举是一种特殊类, 第一行只能定义变量名称 (实际上是一个用final修饰的常量, 所以不能修改)

2.2 格式
public enum 枚举类名{
     变量A,变量B,变量C;
}

例子:

// 枚举
public enum Team {
    // 枚举了几只队伍
    TeamA, TeamK, TeamB, Team4, Team8;
}
2.3 特点

​ 1) 枚举类中的第一行, 只能写一些合法的标识符(名称), 多个名称用逗号隔开。

​ 2) 普通类能定义的数据,在枚举中都能定义 (类的五大成员)

2.4 使用格式

​ 枚举类名.变量名 (尝试修改会显示枚举中变量被final修饰符修饰, 所以这玩意实际上就是一个常量), 如上文的Team.Team8 就可以读取Team8.

ENUM // value of 字符串转换对象 // values 所有内部转换成对象

​ 运用到例子如下.

public class FindWinner {

    //用switch进行调用枚举结果
    public static void main(String[] args) {
        System.out.println(Team.Team8);
        place(Team.Team8);
        place(Team.TeamB);
    }

    private static void place(Team team) {
        switch (team){
            case Team8 ->
            System.out.println("T8 no.1");
            case TeamB -> System.out.println("Tb no.2");
        }
    }
}
2.5 优点

​ 1) 可以限制别人输入的数据

​ 2) 可阅性好

2.6 使用场景

​ 可以结合switch使用, 同时可以用来做一些信息的标记

3 泛型

3.1 作用

​ 泛型提供了在编译阶段约束所能操作的数据类型, 并自动进行检查的能力. 比如 只能接受Animal不接受Animal的子类

3.2 好处

​ 这样可以避免强制类型转换, 及其可能出现的异常。

3.3 泛型的本质

​ 把具体的数据类型作为参数传给类型变量。

3.4 通配符

​ 就是 “?” ,可以在“使用泛型”的时候代表一切类型

​ 除通配符之外, 还能用字母表示泛型 (默认规则, 可以不遵循)

​ T:代表任意类 ​ E:表示Element的意思,或是异常 ​ K:与V搭配使用 ​ V:与K搭配使用

3.5 泛型上限

​ 泛型上限: ? extends 父类: ? 能接收的必须是自己或者其子类 , 上限get. 用在频繁获取数据的场景

​ 所获取到的只能是本类或子类. 比如<? extends Car> , 只能获取比Car类还小的, 所以称之为上限

3.6 泛型下限

​ 泛型下限: ? super 子类 : ? 能接收的必须是本身或者其父类, 下限add, 用在频繁添加数据的场景

​ 所获取到的只能是本类或父类. 比如<? super Car> , 只能获取比Car类还大的, 所以称之为下限

3.7 注意事项

​ 1) 泛型只停留在编辑器, 编写class文件中的泛型会消失, 变成指代类型, 这一个现象叫做泛型擦除

​ 2) 泛型只能是引用数据类型 (基本数据类型需要设置包装类, 例如int=>integer)

4 API

4.1 Object
4.1.1 toString()

​ 作用是返回对象的地址

​ 可以被重写, 重写后, 可以用于返回对象的具体内容

​ 重写范例:

import java.util.Objects;
//定义一个学生类,里面定义姓名和年龄两个属性。重写toString()方法,改变输出对象时的内容
public class Student {
    private String name;
    private int age;

    public String toString(){
        if(Objects.nonNull(getName())&&Objects.nonNull(getAge())){
            String b= "姓名是:"+getName()+"\n年龄是:"+getAge();

            return b;
        }
        return "不能输入空";
    }
public class test {
    public static void main(String[] args) {
        Student stu = new Student("Yui", 21);
        String str = stu.toString();
        System.out.println(str);
    }
}
4.1.2 equals()

​ 用于比较两个对象的地址

​ 重写后可以用来比较两个对象的具体内容

4.1.3 clone()

​ 注意clone的修饰符是protected (本类, 同包, 子孙类) , 并不能用于Object子类对象中, 只能用于Object子类. 但是可以通过重写更改修饰符, 并实现一个Cloneable的接口, 用来作为标记. (抛出异常CloneExce...., 添加一个 implements Cloneable (作为标识))

​ 浅克隆: 复制一个一模一样的对象; 即, 基本类型=>具体值, 引用数据类型=>地址值;

​ 深克隆:基本数据类型=>具体值, 字符串=>地址值, 其他引用类型(对象)=>先创建新的对象,在赋值到新的对象中 (创建了新对象).

4.2 Objects

​ 主要用来做一些检查.

笔者PS: 类加s通常为工具类, 即里面用静态方法和匿名构造器的类

​ 常用API有以下

​ 1) equals(Object o1, Object o2) -- 先判断空,再对内容进行判断

​ 2) isNull(Object obj) -- 判断对象是否为空

​ 3) nonNull(Object obj) -- 判断对象是否不为空