Day07_面向对象三:内部类、枚举、泛型

内部类

  1. 如果一个类定义在另一个类的内部,这个类就是内部类

成员内部类

package demo0321;

public class Outer {
    private int age = 99;
    public static String a;
    public class Inner{
        private int age = 88;
        private String name;
        public static String User; // JDK16才开始支持定义静态成员的
        // 成员内部类可以正常访问外部类的变量
        public void test(){
            System.out.println(age);
            System.out.println(a);
            int age = 66;
            // 直接age访问的是最近的变量
            System.out.println(age);
            // this.age访问内部类的相关变量
            // this.age在内部类中不存在age的时候,会出现异常
            System.out.println(this.age);
            // 通过外部类.this可以获取最外部类的变量
            System.out.println(Outer.this.age);

        }
        public String getName(){
            return name;
        }
        public void setName(String name){
            this.name = name;
        }
    }
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        // 成员内部类创建对象
        // 需要先new出外部类,在.new成员内部类
        Outer.Inner in = new Outer().new Inner();
        in.setName("Hello");
        System.out.println(in.getName());
        in.test();

    }
}

静态内部类

package demo0321;

public class Outer {
    private int age;
    public static String className;
    public static class Inner{
        private String name;
        public static int a;

        public Inner() {
        }

        public void test(){
            System.out.println(className);
            // 静态内部类和静态方法一样,可以直接访问类的类变量,不能访问外部类的实例变量
            // System.out.println(age);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        // 静态内部类创建对象
        Outer.Inner in = new Outer.Inner();
        in.setName("hello");
        System.out.println(in.getName());
        in.test();
    }
}

匿名内部类

  1. 就是一种特殊的局部内部类,所谓匿名: 指的是程序员不需要为这个类声明名字
// 匿名内部类的格式
new 类或接口(参数值){
	类体(一般是方法重写)
}

2.特点: 匿名内部类本身就是一个子类,并会立即创建出一个子类对象

3.优势和应用场景

​ 1.可以更方便创建出一个子类对象

​ 2.匿名内部类通常作为一个参数传递给方法

package demo0321;


abstract class Animal{
    public abstract void cry();
}
class Cat extends Animal{
    @Override
    public void cry(){
        System.out.println("小猫在叫~~");
    }
}

public class Test {
    public static void main(String[] args) {
        // 正常使用该方法
        Animal a = new Cat();
        a.cry();
        // 通过匿名内部类实现
        // 把这个匿名内部类编译成一个子类,然后会立即创建一个子类对象出来
        Animal dog =new Animal(){
            @Override
            public void cry(){
                System.out.println("小狗在叫");
            }
        };
        dog.cry();
    }
}
通过案例进一步理解内部类
package demo0321;


import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test {
    public static void main(String[] args) {
        // 扩展,搞清楚内部类在开发中的真实应用场景
        // GUI编程
        // 1.创建窗口
        JFrame win = new JFrame("登录界面");
        JPanel panel = new JPanel();
        win.add(panel);
        JButton btn = new JButton("登录");
        panel.add(btn);

        // 给按钮绑定单击时间监听器
        // 通过匿名内部类可以做到简化代码的作用
        // 比如这里我们可以不需要在单独创建出一个ActionListener实现类,而是直接传递
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win, "登录一下");
            }
        });


        win.setSize(400, 400);
        win.setLocationRelativeTo(null);
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        win.setVisible(true);
    }
}

枚举

1. 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象
2. 枚举类的构造器都是私有的(写不写都只能是私有的),因此,枚举类对外不能创建对象
3. 枚举类都是最终类,不可以被继承
4. 枚举类中,从第二行开始,可以定义类的其他各种成员
5. 编译器为枚举类新增了几个方法,并且枚举类都是继承: java.long.Enum类的,从enum类也会继承到一些方法
package demo0321;

public enum A {
    // 枚举类的第一行必须罗列的是枚举对象的名字
    X, Y, Z;
    // 后面内容可以编写类的其他内容
    private String Classname;

    public String getName() {
        return Classname;
    }

    public void setName(String name) {
        this.Classname = name;
    }
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        A a = A.X;
        System.out.println(a);
        // 枚举类一些额外的API
        A [] as = A.values();  // 得到枚举的全部对象
        System.out.println(as);
        A a1 = A.valueOf("Y");  // 获取枚举的单个对象
        System.out.println(a1);
        System.out.println(a1.name());  // 获取对象的名称
        System.out.println(a1.ordinal()); // 获取对象的索引
    }
}

抽象枚举

package demo0321;

public enum B {
    // 抽象枚举
    // 在第一行创建对象的时候,需要重写抽象方法,否则异常
    X("张三"){
        @Override
        public void go() {
            System.out.println(getName());
        }
    }, y("李四"){
        @Override
        public void go() {
            System.out.println(getName());
        }
    };

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

    B(String name) {
        this.name = name;
    }

    public abstract void go();
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        B y = B.y;
        y.go();
    }
}

枚举的应用场景

  1. 适合用来进行标志

**案例:**根据用户的输入男女,决定给用户推荐那些信息

1.使用变量进行区分

package demo0321;
// 使用变量时,如果面对大量代码的时候,会严重影响可读性
public class Test {
    public static void main(String[] args) {
        check(0);
        check(1);
        check(5);
    }
    public static void check(int sex){
        switch (sex){
            case 0:
                System.out.println("展示美女");
                break;
            case 1:
                System.out.println("展示帅哥");
                break;
            default:
                System.out.println("美女帅哥五五分展示");
                break;
        }
    }
}

2.使用常量进行区分

package demo0321;

public class A {
    public static final int Boy = 0;
    public static final int GIRL = 1;
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        check(A.Boy);
        check(A.GIRL);
    }
    public static void check(int sex){
        switch (sex){
            case 0:
                System.out.println("展示美女");
                break;
            case 1:
                System.out.println("展示帅哥");
                break;
            default:
                System.out.println("美女帅哥五五分展示");
                break;
        }
    }
}

3.使用枚举

package demo0321;

public enum A {
    Boy,GIRL;
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        check(A.Boy);
        check(A.GIRL);
    }
    public static void check(A sex){
        switch (sex){
            case Boy:
                System.out.println("展示美女");
                break;
            case GIRL:
                System.out.println("展示帅哥");
                break;
            default:
                System.out.println("美女帅哥五五分展示");
                break;
        }
    }
}

泛型

1.定义类、接口、方法时,同时声明一个或者多个类型变量(如),称为泛型类、泛型接口、泛型方法,它们统称为泛型

2.作用: 泛型提供了在编译阶段约束所能操作的数据类型,并自动检查的能力!

3.泛型的本质: 把具体的数据类型作为参数传递給类型变量

自定义泛型类

package demo0321;
// 在定义类时,携带<x>,就成为泛型类,x任意,一般使用E
public class A<E>{
    public boolean add(E a){
        return true;
    }

    public E get(int index){
        return null;
    }
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        A<String> a = new A();
        a.add("Java");
        // 不是泛型指定的数据类型,使用则异常
        //  a.add(15);
       String name = a.get(5);
       // 不是泛型执行的数据类型,会出现异常
       //  int age = a.get(3);

    }
}

自定义泛型接口

package demo0321;

public interface A <X, Y>{
    void add(X t, Y z);
}

package demo0321;

public class B implements A<String, String>{

    @Override
    public void add(String t, String z) {
        System.out.println(t);
        System.out.println(z);
    }
}
package demo0321;

public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.add("hello", "world");
    }
}

自定义泛型方法

package demo0321;

public class Test {
    public static void main(String[] args) {
       // int z = test("java");
       String u = test("Java");
    }
    public static  <T> T test(T t){
        return t;
    }
}

通配符

package demo0321;

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 可以是任意数据类型的数据
        ArrayList<?> arr = new ArrayList<>();
        // 必须是B类的子类
        ArrayList<? extends B> arr1 = new ArrayList<>();
        // 必须是B类的父类或者子类
        ArrayList<? super B> arr2 = new ArrayList<>();
    }
}

擦除

  1. 泛型是工作过在编译阶段的,一旦程序编译成class文件,class文件就不存在泛型了,这就是泛型删除
  2. 泛型不支持基础数据类型.只能支持对象类型(引用数据类型)
  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值