Java面向对象高级(内部类、枚举、泛型)

一、内部类

什么是内部类:

内部类是类中的五大成分之一(成员变量、方法、构造器、内部类、代码块),如果一个类定义在另一个类的内部,这个类就是内部类。

格式:

public class Car{
	//内部类
    public class Engine{
        
    }
}

内部类有四种形式分别是:成员内部类、静态内部类、局部内部类、匿名内部类。

1.1 成员内部类

成员内部类:就是类中的一个普通成员,类似于成员变量、成员方法。

案例:

public class Outer {
    private int age = 99;
    public static String a="黑马";

    // 成员内部类
    public class Inner{
        private String name;
        private  int age = 88;

        //在内部类中既可以访问自己类的成员,也可以访问外部类的成员
        public void test(){
            System.out.println(age); //88
            System.out.println(a);   //黑马

            int age = 77;
            System.out.println(age); //77
            System.out.println(this.age); //88
            System.out.println(Outer.this.age); //99
        }

        public String getName() {
            return name;
        }

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

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }
    }
}

成员内部类如何创建对象,格式如下

//外部类.内部类 变量名 = new 外部类().new 内部类();
Outer.Inner in = new Outer().new Inner();
//调用内部类的方法
in.test();

总结一下内部类访问成员的特点

  • 既可以访问内部类成员、也可以访问外部类成员

  • 如果内部类成员和外部类成员同名,可以使用类名.this.成员区分

1.2 静态内部类

静态内部类,其实就是在成员内部类的前面加了一个static关键字。静态内部类属于外部类自己持有。

public class Outer {
    private int age = 99;
    public static String schoolName="黑马";

    // 静态内部类
    public static class Inner{
        //静态内部类访问外部类的静态变量,是可以的;
        //静态内部类访问外部类的实例变量,是不行的
        public void test(){
            System.out.println(schoolName); //99
            //System.out.println(age);   //报错
        }
    }
}

静态内部类创建对象时,需要使用外部类的类名调用。

//格式:外部类.内部类 变量名 = new 外部类.内部类();
Outer.Inner in = new Outer.Inner();
in.test();

1.3 局部内部类

局部内部类是定义在方法中的类,和局部变量一样,只能在方法中有效。所以局部内部类的局限性很强,一般在开发中是不会使用的。

public class Outer{
    public void test(){
        //局部内部类
        class Inner{
            public void show(){
                System.out.println("Inner...show");
            }
        }
        
        //局部内部类只能在方法中创建对象,并使用
        Inner in = new Inner();
        in.show();
    }
}

1.4 匿名内部类

匿名内部类是一种特殊的局部内部类;所谓匿名,指的是程序员不需要为这个类声明名字。

匿名内部类的格式:

new 父类/接口(参数值){
    @Override
    重写父类/接口的方法;
}

匿名内部类本质上是一个没有名字的子类对象、或者接口的实现类对象。

匿名内部类在编写代码时没有名字,编译后系统会为自动为匿名内部类生产字节码,字节码的名称会以外部类$自然数.class的方法命名

匿名内部类的作用:简化了创建子类对象、实现类对象的书写格式。

匿名内部类的应用场景

只有在调用方法时,当方法的形参是一个接口或者抽象类,为了简化代码书写,而直接传递匿名内部类对象给方法。

二、枚举

2.1 认识枚举

枚举是一种特殊的类,它的格式是:

public enum 枚举类名{
    枚举项1,枚举项2,枚举项3;
}

2.1.2 枚举深入

枚举是一个类的话 ,也能在枚举类中定义构造器、成员变量、成员方法

2.2 枚举的应用场景

枚举的应用场景:

枚举一般表示一组信息,然后作为参数进行传输。

枚举应用场景案例:

现在有这么一个应用,用户进入应用时,需要让用户选择是女生、还是男生,然后系统会根据用户选择的是男生,还是女生推荐不同的信息给用户观看。

public enum Constant{
    BOY,GRIL
}
public class Test{
    public static void main(String[] args){
        //调用方法,传递男生
        provideInfo(Constant.BOY);
    }
    
    public static void provideInfo(Constant c){
        switch(c){
            case BOY:
                System.out.println("展示一些信息给男生看");
                break;
            case GRIL:
                System.out.println("展示一些信息给女生看");
                break;
        }
    }
}

枚举的应用场景:枚举一般表示几个固定的值,然后作为参数进行传输

三、泛型

3.1 认识泛型

所谓泛型指的是,在定义类、接口、方法时,同时声明了一个或者多个类型变量(如:<E>),称为泛型类、泛型接口、泛型方法、它们统称为泛型。

泛型的作用、本质:

  • 泛型的好处:在编译阶段可以避免出现一些非法的数据。

  • 泛型的本质:把具体的数据类型传递给类型变量。

3.2 自定义泛型类

自定义泛型类的格式如下:

//这里的<T,W>其实指的就是类型变量,可以是一个,也可以是多个。
public class 类名<T,W>{
   
}

案例:

接下来,我们自己定义一个MyArrayList<E>泛型类,模拟一下自定义泛型类的使用。注意这里重点仅仅只是模拟泛型类的使用,所以方法中的一些逻辑是次要的,也不会写得太严谨。

//定义一个泛型类,用来表示一个容器
//容器中存储的数据,它的类型用<E>先代替用着,等调用者来确认<E>的具体类型。
public class MyArrayList<E>{
    private Object[] array = new Object[10];
    //定一个索引,方便对数组进行操作
    private int index;
    
    //添加元素
    public void add(E e){
        array[index]=e;
        index++;
    }
    
    //获取元素
    public E get(int index){
        return (E)array[index];
    }
}

接下来,我们写一个测试类,来测试自定义的泛型类MyArrayList是否能够正常使用

public class Test{
    public static void main(String[] args){
        //1.确定MyArrayList集合中,元素类型为String类型
        MyArrayList<String> list = new MyArrayList<>();
        //此时添加元素时,只能添加String类型
        list.add("张三");
        list.add("李四");
        
         //2.确定MyArrayList集合中,元素类型为Integer类型
        MyArrayList<Integer> list1 = new MyArrayList<>();
        //此时添加元素时,只能添加Integer整型
        list.add(100);
        list.add(200);
        
    }
}

3.3 自定义泛型接口

泛型接口其实指的是在接口中把不确定的数据类型用<类型变量>表示。定义格式如下:

//这里的类型变量,一般是一个字母,比如<E>
public interface 接口名<类型变量>{
    
}

3.4 泛型方法

泛型方法的格式:

public <泛型变量,泛型变量> 返回值类型 方法名(形参列表){
    
}

泛型方法的案例:

public class Test{
    public static void main(String[] args){
        //调用test方法,传递字符串数据,那么test方法的泛型就是String类型
        String rs = test("test");
    
        //调用test方法,传递Dog对象,那么test方法的泛型就是Dog类型
    	Dog d = test(new Dog()); 
    }
    
    //这是一个泛型方法<T>表示一个不确定的数据类型,由调用者确定
    public static <T> T test(T t){
        return t;
    }
}

3.5 泛型限定

泛型限定的意思是对泛型的数据类型进行范围的限制。有如下的三种格式

  • <?> 表示任意类型

  • <? extends 数据类型> 表示指定类型或者指定类型的子类

  • <? super 数据类型> 表示指定类型或者指定类型的父类

演示一下,假设有Car作为父类,BENZ,BWM两个类作为Car的子类,代码如下:

class Car{}
class BENZ extends Car{}
class BWN extends Car{}

public class Test{
    public static void main(String[] args){
        //1.集合中的元素不管是什么类型,test1方法都能接收
        ArrayList<BWM> list1 = new ArrayList<>();
        ArrayList<Benz> list2 = new ArrayList<>();
        ArrayList<String> list3 = new ArrayList<>();
        test1(list1);
        test1(list2);
        test1(list3);
        
        //2.集合中的元素只能是Car或者Car的子类类型,才能被test2方法接收
        ArrayList<Car> list4 = new ArrayList<>();
        ArrayList<BWM> list5 = new ArrayList<>();
        test2(list4);
        test2(list5);
        
        //2.集合中的元素只能是Car或者Car的父类类型,才能被test3方法接收
        ArrayList<Car> list6 = new ArrayList<>();
        ArrayList<Object> list7 = new ArrayList<>();
        test3(list6);
        test3(list7);
    }
    
    public static void test1(ArrayList<?> list){
        
    }
    
    public static void test2(ArrayList<? extends Car> list){
        
    }
    
   	public static void test3(ArrayList<? super Car> list){
        
    }
}

3.6 泛型擦除

什么是泛型擦除?

泛型只能编译阶段有效,一旦编译成字节码,字节码中是不包含泛型的。而且泛型只支持引用数据类型,不支持基本数据类型。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值