内部类和枚举型

java基础

内部类

基本介绍

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类,嵌套其他类的类称为外部类。是我们类的第五大成员[属性,方法,构造器,代码块,内部类],内部类最大特点是可以直接访问私有属性,可以体现类与类之间的包含关系。

基本语法

class Outer{//外部类
    class Inner{//内部类
        
    }
}
class Other{//外部其他类
        
    }
例子
package org.example.controler;

public class InnerClass01 {//外部其他类
    public static void main(String[] args) {

    }
}
class Outer{//外部类
    private int n1 = 100;//属性

    public Outer(int n1) {//构造器
        this.n1 = n1;
    }

    public void m1(){
        System.out.println("m1()");
    }
    {//代码块
        System.out.println("代码块");
    }
    class Inner{//内部类

    }
}

局部内部类的使用

说明:

局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
  3. 作用域:仅仅在定义它的方法或代码块中。
  4. 局部内部类–访问---->外部类的成员[访问方式:直接访问]
  5. 外部类–访问—>局部内部类的成员
  6. 外部其他类–不能访问---->局部内部类(因为 局部内部类地位是一个局部变量)
  7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
package org.example.controler;

public class LocalInnerClass {
    public static void main(String[] args) {
    //演示
        Outer02 outer02 = new Outer02();
        outer02.m1();
    }
}
class Outer02{//外部类
    private int n1 = 100;
    private void m2(){
        System.out.println("Ourter02 m2()");
    }//私有方法
    public void m1(){//方法
        //1.局部内部类是定义在外部类的局部位置,通常在方法
        //3.不能添加访问修饰符,但是可以使用final修饰,加上final就不可以继承这个类了,否则可以继承
        //4.作用域:仅仅在定义它的方法或代码块中
       final class Inner02{//局部内部类(本质仍然是一个类)
            //2.可以直接访问外部类的所有成员,包含私有的
           private int n1=800;
            public void f1(){
                //5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1和m2()
                //7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
                //Outer02.this本质就是外部类的对象,即哪个对象调用了m1,Outer02.this就是哪个对象
                System.out.println("n1="+n1+"外部类的n1="+Outer02.this.n1);
                
                m2();
            }
        }
        //6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
       Inner02 inner02= new Inner02();
       inner02.f1();
    }



}

在这里插入图片描述

记住:1.局部内部类定义再方法中/代码块

2.作用域在方法体或者代码块中

3.本质仍然是一个类

匿名内部类的使用

大致概括:
  1. 本质是类
  2. 内部类
  3. 该类没有名字
  4. 同时还是一个对象
说明:

匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

基本语法:
new 类或接口(参数列表){
    类体
};
案例:
package org.example.controler;

/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}
class Outer04{//外部类
    private int n1 = 10;//属性
    public void method(){//方法
        //基于接口的匿名内部类
        //1.需求:想使用A接口,并创建对象
        //2.传统方式,是写一个类,实现该接口
        //3.老韩需求是 Tiger 类只是使用一次,后面再不使用
        //4.可以使用匿名内部类来简化开发
        //5.tiger1的编译类型是 A
        //6.tiger1的运行类型是 就是匿名内部类 XXX=> Outer04$1
        /*
        我们看底层 会分配 类名 Outer04$1
        class XXX implements A{
             @Override
            public void cry() {
                System.out.println("老虎叫换、、、、、");
            }
        }
        * */
        //7.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并且把地址
        //返回给tiger1
        //8.匿名内部类使用一次就不能再使用了
        A tiger1 = new A(){

            @Override
            public void cry() {
                System.out.println("老虎叫换、、、、、");
            }
        };
        System.out.println("tiger1的运行类型:"+tiger1.getClass());
        tiger1.cry();



        A tiger = new Tiger();
        tiger.cry();
    }
}
interface A{//接口
    public void cry();
}
class Tiger implements A{

    @Override
    public void cry() {
        System.out.println("老虎叫唤....");
    }
}
class Dog implements A{

    @Override
    public void cry() {
        System.out.println("小狗汪汪叫");
    }
}
class Father{//类
    public Father(String name){//构造器
        super();
    }
    public void test(){//方法

    }
}

在这里插入图片描述

基于类的匿名内部类:

案列:

package org.example.controler;

/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}
class Outer04{//外部类
    private int n1 = 10;//属性
    public void method(){//方法
        //基于接口的匿名内部类
        //1.需求:想使用A接口,并创建对象
        //2.传统方式,是写一个类,实现该接口
        //3.老韩需求是 Tiger 类只是使用一次,后面再不使用
        //4.可以使用匿名内部类来简化开发
        //5.tiger1的编译类型是 A
        //6.tiger1的运行类型是 就是匿名内部类 XXX=> Outer04$1
        /*
        我们看底层 会分配 类名 Outer04$1
        class XXX implements A{
             @Override
            public void cry() {
                System.out.println("老虎叫换、、、、、");
            }
        }
        * */
        //7.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并且把地址
        //返回给tiger1
        //8.匿名内部类使用一次就不能再使用了
        A tiger1 = new A(){

            @Override
            public void cry() {
                System.out.println("老虎叫换、、、、、");
            }
        };
        System.out.println("tiger1的运行类型:"+tiger1.getClass());
        tiger1.cry();



//        A tiger = new Tiger();
//        tiger.cry();
        //演示基于类的匿名内部类
        //1.father编译类型 Father
        //2.father运行类型 Outer04$2
        //3.底层会创建匿名内部类
        /*
        * class Outer04$2 extends Father{
        *
        * }
        * */
        //4.同时也直接返回了 匿名内部类 Outer04$2的对象
        //5.注意("jack")参数列表会传递给构造器
        Father father = new Father("jack"){
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        father.test();
        System.out.println("father的运行类型"+father.getClass());
        //基于抽象类的匿名内部类
       Animal animal =  new Animal(){
            @Override
            void eat() {
                System.out.println("小狗吃骨头");
            }
        };
       animal.eat();
    }
}
interface A{//接口
    public void cry();
}
class Tiger implements A{

    @Override
    public void cry() {
        System.out.println("老虎叫唤....");
    }
}
class Dog implements A{

    @Override
    public void cry() {
        System.out.println("小狗汪汪叫");
    }
}
class Father{//类
    public Father(String name){//构造器

        System.out.println("name的值为"+name);
    }
    public void test(){//方法

    }
}

abstract class  Animal{//抽象类
    abstract void eat();
}

在这里插入图片描述

使用方法:

案列:

package org.example.controler;

public class AnonymousInnerClassDetail {
    public static void main(String[] args) {

        Outer05 outer05 = new Outer05();
        outer05.f1();
    }
}

class Outer05{
    private  int n1 = 99;
    public  void f1(){
        //创建一个基于类的匿名内部类
        Person p = new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了hi方法");
            }
        };
        p.hi();//动态绑定,运行类型是Outter05$1

        //也可以直接调用,匿名内部类本身也是返回了一个对象的
        new Person(){
            @Override
            public void hi() {
                System.out.println("匿名内部类重写了hi方法,哈哈哈、、、");
            }

            @Override
            public void ok(String str) {
                super.ok(str);
            }
        }.ok("jack");
    }
}

class Person{
    public void hi(){
        System.out.println("Person 里面的hi()");
    }
    public void ok(String str){
        System.out.println("Person 里面的ok()传的值为:"+str);
    }
}

在这里插入图片描述

匿名内部类的最佳实践

当做实参直接传递,简洁高效

案例1
package org.example.controler;

public class InnerClassExercise01 {
    public static void main(String[] args) {
        //当作实参直接传递,简洁高效
        f1(new IL() {
            @Override
            public void show() {
                System.out.println("这是一幅名画");
            }
        });
        //传统方法
        f1(new Picture());
    }
    //静态方法,形参是接口类型
    public static void f1(IL il){
        il.show();
    }

}

//接口
interface IL{
    public void show();
}

//类->实现IL=>硬编码
class Picture implements IL{

    @Override
    public void show() {
        System.out.println("这是一幅名画。。。。。");
    }
}

案例2
package org.example.controler;

public class InnerClassExercise02 {
    public static void main(String[] args) {
    /*
    * 1.有一个铃声接口Bell,里面有个ring 方法。
    * 2.有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型
    * 3.测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:拦住起床了
    * 4.再传入另一个匿名内部类(对象),打印:小伙伴上课了
    * */
        Cellphone cellphone = new Cellphone();
        cellphone.alarmClock(new Bell() {
            @Override
            public void ring() {
                System.out.println("懒猪起床了");
            }
        });

        cellphone.alarmClock(new Bell() {
            @Override
            public void ring() {
                System.out.println("小伙伴们上课了");
            }
        });
    }

}

interface Bell{
    void ring();
}

class Cellphone{
   public void alarmClock(Bell bell){
        bell.ring();
    }
}

成员内部类:

说明:

成员内部类是定义在外部类的成员位置,并且没有static修饰。

1.可以访问外部类的所有成员,包含私有的

2.可以添加任意访问修饰符(public,protected,默认,private)因为它的地位就是一个成员

案例:
package org.example.controler;

public class MemberInnerClass01 {
    public static void main(String[] args) {
        Outer08 outer08 = new Outer08();
        outer08.t1();
    }
}
class Outer08{//外部类
    private int n1 = 10;
    public String name= "张三";
    //注意:成员内部类,是定义在外部类的成员位置上
    class Innter08{//成员内部类
        public void say(){
            //可以直接访问外部类的所有成员,包含私有的
            System.out.println("Outer08的n1="+n1+"Outer08的name="+name);
        }
    }

    //写方法
    public void  t1(){
        //使用了成员内部类
        Innter08 innter08 = new Innter08();
        innter08.say();

    }
}

3.作用域和外部类的其它成员一样,为整个类体比如前面案列,在外部类的成员内部类对象,再调用方法

4.成员内部类–访问—>外部类(比如:属性)[访问方式:直接访问]

5.外部类–>访问------>内部类访问方式:创建对象,再访问

6.外部其他类—访问—>成员内部类

静态内部类:

说明:

静态内部类是定义在外部的成员位置,并且有static修饰

1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

2.可以添加任意访问修饰符,因为它的地位就是一个成员

3.作用域:同其它的成员,为整个类体

4.静态内部类–访问---->外部类(比如:静态属性)[访问方式:直接访问所有静态成员]

5.外部类—访问----->静态内部类 访问方式:创建对象,再访问

6.外部其它类–访问----->静态内部类

7.如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问

枚举

什么是枚举

1.枚举是一组常量的集合。

2.枚举属于一种特殊的类,里面只包含有限的特定的对象

实现枚举的方式

自定义枚举:
说明:

1.不需要提供setXxx方法,因为枚举对象值通常为只读。

2.对枚举对象/属性使用final+static共同修饰,实现底层优化。

3.枚举对象名通常使用全部大写,常量的命名规范。

4.枚举对象根据需要,也可以有多个属性。

案例:
package org.example.enums;

public class Enumeration02 {
    public static void main(String[] args) {
        System.out.println(Season.SPRING.getName()+" "+Season.SPRING.getDesc());
    }
}

class Season{//类
    private String name;
    private String desc;

    //定义了四个对象
    public static final Season SPRING = new Season("春天", "温暖");
    public static final Season SUMMER = new Season("夏天", "炎热");
    public static final Season WINTER = new Season("冬天", "寒冷");
    public static final Season AUTUMN = new Season("秋天", "凉爽");


    //1.将构造器私有化,目的 防止直接new
    //2.去掉set方法,防止属性被修改
    //3.在Season内部,直接创建固定的对象
    //4.优化,可以加入 final 修饰
    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }



    public String getDesc() {
        return desc;
    }


}

在这里插入图片描述

enum关键字实现枚举

案例
package org.example.enums;

public class Enumeration03 {
    public static void main(String[] args) {
        System.out.println(Season.SPRING);
    }
}

enum Season{//类


//    //定义了四个对象
//    public static final Season SPRING = new Season("春天", "温暖");
//    public static final Season SUMMER = new Season("夏天", "炎热");
//    public static final Season WINTER = new Season("冬天", "寒冷");
//    public static final Season AUTUMN = new Season("秋天", "凉爽");
    //1.使用关键字enum来实现枚举类
    //2.使用SPRING("春天","温暖") 解读 常量名(实参列表)
    //3.如果有多个常量(对象),使用 , 号间隔即可
    //4.如果使用enum来实现枚举,要求将定义常量对象,写在前面
    //5.如果使用的时无参构造器,可以省略小括号如WATH
    SPRING("春天","温暖"),
    WINTER("冬天", "寒冷"),
    WATH;
    private String name;
    private String desc;
    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
	
    private Season(){
        
    }
    public String getName() {
        return name;
    }



    public String getDesc() {
        return desc;
    }

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}
注意事项:

1.当我们使用enum关键字开发一个枚举类时,默认会继承Enum类

2.传统的public static final Season SPRING = new Season(“春天”,“温暖”);简化成SPRING(“春天”,“温暖”),这里必须知道,它调用是哪个构造器。

3.如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略

4.当有多个枚举对象时,使用,间隔,最后有一个分号结尾

5.枚举对象必须放在枚举类的行首

enum常用方法应用实列

1.toString:Enum类已经重写过了,返回的是当前对象名,子类可以重写该方法,用于返回对象的属性信息

2.name:返回当前对象名(常量名),子类中不能重写

3.ordinal:返回当前对象的位置号,默认从0开始

4.values:返回当前枚举类中所有的常量

5.valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常

6.compareTo:比较两个枚举常量,比较的就是编号

案列
package org.example.enums;

public class EnumMethod {
    public static void main(String[] args) {
        Season autumn = Season.AUTUMN;
        //输入枚举对象的名字
        System.out.println(autumn.name());
        //ordinal()输出的是该枚举对象的次序/编号,从0开始编号
        System.out.println(autumn.ordinal());
        //values返回的是Season的数组,含有所有的枚举对象
        Season[] values = Season.values();
        for (Season season:values) {
            System.out.println(season);
        }
        //valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常
        //执行流程
        //1.根据你输入的"AUTUMN"到Season的枚举对象去查找
        //2.如果找到了,就返回,如果没有找到,就报错
        Season season = Season.valueOf("AUTUMN");
        System.out.println(season);
        //compareTo:比较两个枚举常量,比较的就是编号
        //输出结果为Season.SPPRING-Season.WINTER
        System.out.println(Season.SPRING.compareTo(Season.WINTER));
    }
}

enum实现接口

1.使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。

2.枚举类和普通类一样,可以实现接口,如下形式。

enum 类名 implements 接口1,接口2{}

注解

理解

1.注解也被称为元数据,用于修饰解释 包,类,方法,属性,构造器,局部变量等数据信息

2.和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入再代码中的补充信息

3.在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等

三个基本注解

1.@Override:限定某个方法,是重写父类方法,该注解只能用于方法

2.@Deprecated:用于表示某个程序元素(类,方法等)已过时

到Season的枚举对象去查找
//2.如果找到了,就返回,如果没有找到,就报错
Season season = Season.valueOf(“AUTUMN”);
System.out.println(season);
//compareTo:比较两个枚举常量,比较的就是编号
//输出结果为Season.SPPRING-Season.WINTER
System.out.println(Season.SPRING.compareTo(Season.WINTER));
}
}


##### enum实现接口

1.使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而Java是单继承机制。

2.枚举类和普通类一样,可以实现接口,如下形式。

enum 类名 implements 接口1,接口2{}

## 注解

### 理解

1.注解也被称为元数据,用于修饰解释 包,类,方法,属性,构造器,局部变量等数据信息

2.和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入再代码中的补充信息

3.在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替java EE旧版中所遗留的繁冗代码和XML配置等

### 三个基本注解

1.@Override:限定某个方法,是重写父类方法,该注解只能用于方法

2.@Deprecated:用于表示某个程序元素(类,方法等)已过时

3.@SupperssWarnings:抑制编译器警告
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值