首页 > 编程语言 >【java基础】内部类

【java基础】内部类

时间:2022-11-19 22:24:28浏览次数:36  
标签:部类 java 内部 静态 成员 基础 static public

什么是内部类?

内部类就是定义在类的内部的类,称之为内部类
Java中内部类分为以下4种:

  1. 成员内部类, 内部类在定义时没有使用static修饰(知晓)
  2. 静态内部类,内部类在定义时使用static修饰【Java中唯一可以使用static修饰类的方法】
    (知晓)
  3. 局部内部类,内部类在定义时定义在方法体内部(了解)
  4. 匿名内部类,它属于局部类类的特殊形态(必须会用)

内部类也是类,所以也会被JVM进行编译生成字节码文件【.class文件】

  1. 成员内部类生成字节码文件: 外部类类名$成员内部类类名.class
  2. 静态内部类生成字节码文件: 外部类类名$静态内部类类名.class
  3. 局部内部类生成字节码文件: 外部类类名$数字局部内部类类名.class
  4. 匿名内部类生成字节码文件: 外部类类名$数字.class
    PS: 数字是从1开始逐渐递增【随着类的增加而增加】成员内部类(知晓)

成员内部类(知晓)

外部类可以使用权限修饰符为 public 和 默认的和abstract,成员内部类可以使用【4种权限修饰
符和abstract修饰】,可以将成员内部类看做就是在类中声明成员变量或成员方法,所以成员内
部类是属于对象的

//外部类
public class Outter {
    //外部类中提供成员变量和方法、静态变量和方法
    String name = "小白";
    double PI = 3.14;
    static int age = 10;
    public static void showInfos(){
        System.out.println("外部类静态方法");
    }
    public void display(){
        System.out.println("外部类的成员方法");
    //需要提供内部类对象创建,才可以使用成员内部类中所提供成员变量和成员方法
        InnerClass innerClass = new InnerClass();
        innerClass.name ="z";
        innerClass.show();
    }
    //提供成员内部类 ---》 成员内部类就是定义在类中类,可以使用任何修饰符除static外
    public class InnerClass{ //成员内部类
        //可以在成员内部类中提供类的基础定义,但是不可以提供static修饰的属性和方法
        //static double PI = 3.14;
        String name = "小黑";
        public void show(){
            System.out.println("成员内部类中成员方法");
            //如果说在成员内部类中调用与外部类同名属性
            //this代表的是InnerClass对象,所以使用this.name
            System.out.println(this.name);
            //这种方式访问外部类的成员变量
            System.out.println(Outter.this.name);
            //调用外部类的成员方法【如果没有重名的效果,就不需要使用,外部类类名.this.方式调用】
            display();
            System.out.println(PI);
            //成员内部类中是可以调用外部类静态属性和方法
            System.out.println(age);
            showInfos();
        }
    }
}
class Test{
    public static void main(String[] args) {
        //如何在外部创建成员内部类的对象
        //成员内部类是属于外部类所有的,所以提供方式就是
        // 外部类类名.内部类类名 内部类对象名 = new 外部类().new 成员内部类();
        Outter.InnerClass innerClass = new Outter().new InnerClass();
        innerClass.show();
    }
}

总结: 成员内部类是定义在类中,不使用static修饰,可以使用4种权限修饰符,可以使用
abstract和final修饰,允许继承类与实现接口,成员内部类中不可以定义static修饰变量与方
法,成员内部类是可以直接访问外部类定义属性和方法,如果成员内部类出现了与外部类属性重
名,可以使用【this 和 外部类.this】进行区分,外部类要访问成员内部类的属性和行为时,提供
成员内类的对象
---》 外部类类名.内部类类名 内部类对象名 = new 外部类().new 内部类();

静态内部类(知晓)

静态内部类和成员内部类几乎与是一样的,唯一不点在于静态内部类使用static进行了修饰
PS:这是Java中类唯一可以使用static修饰的形式

//外部类
public class Outter {
    //外部类中提供成员变量和方法、静态变量和方法
    String name = "小白";
    double PI = 3.14;
    static int age = 10;
    public static void showInfos(){
        System.out.println("外部类静态方法");
    }
    public void display(){
        System.out.println("外部类的成员方法");
        //调用静态内部类中静态属性和方法 ---》 静态内部类类名.静态属性和静态方法即可
        System.out.println(InnerClass.name);
        //调用静态内部类中成员属性和方法 ---》 需要提供静态内部类的对象
        new Outter.InnerClass().show();
    }
        //提供静态成员内部类 ---》 静态内部类就是定义在类中类,可以使用static修饰符修饰
    public static class InnerClass{ //静态内部类
        // 静态内部类可以提供普通类中所有可以提供操作【成员变量和方法、静态变脸和方法】
        double PI = 3.15;
        static String name = "小黑";
        public void show(){
        //在静态内部类中是不用担心 属性重名问题
        //不是可以使用 外部类类名.this方法访问外部的属性【static中是不允许使用this和super关键字】
        //只能在静态内部类中创建外部类对象,才可以访问外部类成员变量和成员方法
            System.out.println(new Outter().name);
        //调用外部类静态方法和静态属性 --> 外部类类名.静态属性或静态方法即可
            System.out.println(Outter.age);
            Outter.showInfos();
        //静态内部类中的属性和方法直接调用即可
            System.out.println(PI);
            System.out.println(name);
        }
    }
}
class Test{
    public static void main(String[] args) {
        //提供静态内部类对象创建
        //外部类类名.静态内部类类名 对象名 = new 外部类类名.静态内部类类名();
        Outter.InnerClass innerClass = new Outter.InnerClass();
        innerClass.show();
    }
}

总结: 静态内部就是使用static修饰类【Java中只有这个类可以使用static修饰】,可以使用所
有权限修饰符,abstract和final修饰,静态内部类和静态属性和静态方法是一样都属于类,静态
内部类中是可以定义【成员变量和方法、静态变量和方法】,静态内部类中不允许明确访问方式
获取外部类this对象即【外部类类名.this】,所以在静态内部类中访问外部类成员变量和成员方
法,需要提供外部对象才可以,外部类静态变量和静态方法直接访问即可,如果有重名【外部类
类名.静态变量/静态方法】
静态内部类如果要创建对象
外部类类名.静态内部类类名 对象名 = new 外部类类名.静态内部类类名();

局部内部类(了解)

这个内部类不允许使用任何修饰符,只能定义在方法内部与局部变量是平级关系,访问作用域仅
限在方法的内部

//外部类
public class Outter {
    //提供一个成员方法
    public void show() {
        //局部变量
        final int age = 18;
        //提供局部内部类【局部变量是平级关系】
        class InnerClass {
            //局部内部类中是不允许定义static修饰属性和方法
            //允许提供成员变量和成员方法
            String gender = "男";

            public void display() {
            //在局部内部类中访问方法中局部变量
            /*
            IDEA提供错误提示信息
            Variable 'age' is accessed from within inner class, needs to be
            final or effectively final
            如果局部内部类使用方法提供的局部变量,这个局部变量必须是final修饰
            */
                System.out.println(age);
            }
        }
        //局部内部类只能在方法体的内部创建对象和使用,外界是无法访问到这个类中
        new InnerClass().display();
        //在此在方法体的内部修改成员变量
        // age = 20;
    }
}

为什么,局部内部类访问局部变量之后需要使用final声明?
final修饰局部变量的存储空间会发生改变,存储不再是栈中,而是方法区中常用池,局部变量就会
变成“引用”常量
局部内部类是声明在方法体内部,就会存在一个问题,局部内部类是随着方法而开始创建空间,
随着方法消亡开始回收空间,如果在方法内声明局部变量存储空间是栈【随着方法开始而创建随
着方法消亡会销毁】,如果局部内部类使用了这个局部变量,那么堆中地址就会和栈中位置产生
一个联系,堆中局部内部类就会引用到栈中局部变量,如果发生方法执行完毕,栈中空间空间会
进行立即回收,但是堆中局部内部类是不会被立即回收【GC机制】,就会出现堆栈存在一个“指
向空”引用,内报错了,所以使用final修饰符将局部变量修改为局部常量,将存储从栈中移动到方
法区中常量池,这样一来就算栈中空间被回收,但是方法区种空间还在,所以可以等待堆中局部
内部正常回收之后断练习,保证不会出现引用错误。

匿名内部类

/抽烟接口
public interface ISmoking {
    /**
     * 抽烟方法
     * @param name 抽烟的名字
     */
    void smoke(String name);
}
//按照以往的方法实现接口
public class Outter implements ISmoking {
    @Override
    public void smoke(String name) {
        System.out.println("正在抽的烟是:"+name);
    }
}
public class Test {
    public static void main(String[] args) {
        //调用抽烟方法展示抽象操作
        //1.提供实现ISmoking接口对象
        Outter outter = new Outter();
        //2.通过outter对象调用smoke方法就可以执行抽烟操作
        outter.smoke("华子");
        //这个方法可以接收的对象必须是实现ISmoking接口的对象【利用就是面向兑现中多态】
        showInfosSmokeName(outter);
        //但是,如果当前实现接口类只使用一次,不在重复使用了,这样创建方式就比较繁琐也不利于管理
        //所以Java就提供了一个更加便捷处理方式,提供匿名内部类作为接口的实现操作
        /*
        第一种 主要是针对与方法参数为接口类型进行赋值操作 --》完全匿名内部类
        new 接口名(){
        提供接口中抽象方法的实现;
        }
        *//*
        第二种方式,针对匿名内部类所创建对象进行存储操作
        接口名 对象名 = new 接口名(){
        接口抽象方法的实现
        }
        */
        //smoking 存储的就是匿名内部类的引用【使用 new ISmoking的形式将后面的匿名内部类进行对象向上转型】
        new ISmoking(){
            @Override
            public void smoke(String name) {
                System.out.println("完全匿名内部类实现接口:"+name);
            }
        }.smoke("芙蓉王"); //这种形式主要是针对方法参数赋值使用的
        //第二种 主要是针对于接口对象的赋值操作 --》局部匿名内部类
        ISmoking smoking = new ISmoking() {
            @Override
            public void smoke(String name) {
                System.out.println("使用匿名内部类创建了接口对象:"+name);
            }
        };
        smoking.smoke("煊赫门");
        //可以使用匿名内部类的这种语法便捷的对方法中参数进行赋值操作
        showInfosSmokeName(new ISmoking() {
            @Override
            public void smoke(String name) {
                System.out.println("匿名内部类对接口参数赋值:"+name);
            }
        });// 使用匿名内部类形式对接口参数进行赋值操作
    }
    //提供一个方法这个方法的参数类型是接口类型
    public static void showInfosSmokeName(ISmoking smoking){
        smoking.smoke("小熊猫");
    }
}

标签:部类,java,内部,静态,成员,基础,static,public
From: https://www.cnblogs.com/blanset/p/16907344.html

相关文章

  • java中float、int等数值转为二进制方法或者十六进制的方法记录
    //将int解析成二进制,再根据二进制转换成floatFloatf=Float.intBitsToFloat(i.intValue());//格式化float,固定显示的小数点位数。DecimalFormatdf=newDecimal......
  • JavaScript基础知识——对象
    定义无序数据的集合,键值对的集合。写法构造函数letuser=newObject({name:'yang',age:100})字面量letuser={name:'yang',age:200}匿名对象console.l......
  • java常用查询
     生成文档javadoc-ddoc hello.java                   ......
  • java暂存
    publicclassMain{publicstaticvoidmain(String[]args){Stringm=Integer.toBinaryString(120);System.out.println(m);intss=Intege......
  • Java异常跟踪栈
    Java异常跟踪栈异常对象的printStackTrace()方法用于打印异常的跟踪栈信息,根据printStackTrace()方法的输出结果,我们可以找到异常的源头,并跟踪到异常一路触发的过程。看......
  • Java异常处理规则
    Java异常处理规则前面介绍了使用异常处理的优势、便捷之处,本节将进一步从程序性能优化、结构优化的角度给出异常处理的一般规则。成功的异常处理应该实现如下4个目标:使......
  • Java使用throw抛出异常
    Java使用throw抛出异常当程序出现错误时,系统会自动抛出异常;除此之外,Java也允许程序自行抛出异常,自行抛出异常使用throw语句来完成(注意此处的throw没有后面的s,与前面声明抛......
  • 多数据源配置时validationQuery的问题(errorCode 923, state 42000 java.sql.SQLSynta
    起初,数据库配置为:datasource:master:url:jdbc:postgresql://ip:5432/databaseNameusername:**password:**......
  • java html串转换成文本串
    采用htmlparser来解决将html串中抽取出文本串。Stringstr="<!DOCTYPEHTMLPUBLIC\"-//W3C//DTDHTML4.0Transitional//EN\">"+"<HTML><HE......
  • java 序列化 浅克隆 深克隆
    序列化Java序列化技术可以使你将一个对象的状态写入一个Byte流里,并且可以从其它地方把该Byte流里的数据读出来,重新构造一个相同的对象。当两......