内部类

内部类包含:实例内部类(成员内部类)、静态内部类、本地内部类匿名内部类 阅读详情

定义在其他类的内部称为内部类;包含内部类的类也被称为外部类
作用:
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包的其他类访问该类;
- 内部类可以直接访问外部类的私有数据,因为内部类被当成其外部类的成员。但外部类不能访问内部类的细节,如成员变量
- 匿名内部类适合用于创建那些仅需要一次使用的类,

区别:
- 内部类比外部类可以多使用三个修饰符,private,protected,static ,外部类不可以使用这三个修饰符
- 非静态内部类不能拥有静态成员

成员内部类分为静态内部类非静态内部类
大部分时候,内部类都被作为成员内部类定义,而不是作为局部内部类。
成员内部类是一种与成员变量,方法,构造器和初始化块相似的类成员,局部内部类和匿名内部类则不是类成员。

5.7.1 非静态内部类

内部类的上一级程序单元是外部类,它具有4个作用域:同一个类,同一个包,父子类,和任何位置。

package code;
public class Cow{
    private double weight;
    public Cow(){}
    public Cow(double weight){
        this.weight = weight;
    }
    private class CowLeg{
        private double length;
        private String color;
        public CowLeg(){}
        public CowLeg(double length,String color){
            this.length = length;
            this.color = color;
        }
        public void setLength(double length){
            this.length = length;
        }
        public double getLength(){
            return length;
        }
        public void setColor(String color){
            this.color = color;
        }
        public String getColor(){
            return color;
        }
        public void info(){
            System.out.println("当前牛腿的颜色是:" + color + ",高:" + length);
            System.out.println("当前这只牛的重量是" + weight);
        }
    }
    public void test(){
        CowLeg c1 = new CowLeg(11.2,"绿色");
        c1.info();
    }
    public static void main(String [] args){
        Cow cow = new Cow(44.3);
        cow.test();
    }

}

当前牛腿的颜色是:绿色,高:11.2
当前这只牛的重量是44.3

文件路径:生成两个class文件,一个是Cow.class,一个是Cow$CowLeg.class

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,接着到该方法所在的内部类中查找,再接着到该内部类所在的外部类中查找,依次查找,存在则使用该变量。

DiscernVariable.java

package code;
public class DiscernVariable{
    private String prop = "外部类实例变量";
    private class Inner{
        private String prop = "内部类实例变量";
        public void info(){
            String prop = "局部变量";
            System.out.println(DiscernVariable.this.prop);
            System.out.println(this.prop);
            System.out.println(prop);
        }
    }
    public void test(){
        Inner in = new Inner();
        in.info();
    }
    public static void main(String []args){
        DiscernVariable dv = new DiscernVariable();
        dv.test();
    }
}

外部类实例变量
内部类实例变量
局部变量

非静态内部类的成员可以访问外部类的private成员,但反过来不成立
在外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。

Outer.java

package code;
public class Outer{
    private int outProp = 9;
    class Inner{
        private int inProp = 8;
        public void acessOuterProp(){
            System.out.println("外部类的outProp值" + outProp);
        }
    }
    public void accessInnerProp(){
        //外部类不能直接访问非静态内部类的实例变量
        //System.out.println("内部类的inProp值" + inProp);
        System.out.println("内部类的inProp值" + new Inner().inProp);
    }
    public static void main(String [] args){
        //执行下面代码,只创建了外部类对象,没有创建内部类
        Outer o = new Outer();
        o.accessInnerProp();
    }
}

内部类的inProp值8

根据静态成员不能访问非静态成员的规则,外部类的静态方法、代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量,创建实例。

StaticTest.java

package code;
public class StaticTest{
    private class In{}
    public static void main(String[]args){
        //静态成员(main()方法)无法访问非静态成员(In类)
        //new In();
    }
}

Java不允许在非静态内部类里定义静态成员。

InnerNoStatic.java

package code;
public class InnerNoStatic{
    private class InnerClass{
        //非静态内部类不能有静态声明
        /*static{
            System.out.println("========");
        }
        private static int intProp;
        private static void test();*/
    }
}

非静态内部类里不可以有静态初始化块,但可以包含普通初始化块

5.7.2 静态内部类

如果使用static来修饰一个内部类,则这个内部类就属于外部类本身

static关键字不可修饰外部类,但可以修饰内部类
因为外部类的上一级程序单元是包,所以不可使用static修饰,而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关。

静态内部类可以包含静态成员,也可以包含非静态成员。
而静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。
StaticInnerClassTest.java

package code;
public class StaticInnerClassTest{
    private int prop1 =5;
    private static int prop2 = 9;
    static class StaticInnerClass{
        //
        private static int age;
        public void accessOuterProp(){
            System.out.println(prop1);
            System.out.println(prop2);
        }
    }
}

StaticInnerClassTest.java:9: 错误: 无法从静态上下文中引用非静态 变量 prop1
System.out.println(prop1);
^
1 个错误

外部类不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象(new)作为调用者来访问静态内部类的实例成员。

AccessStaticInnerClass.java

package code;
public class AccessStaticInnerClass{
    static class StaticInnerClass{
        private static int prop1 = 5;
        private int prop2 = 9;
    }
    public void accessInnerProp(){
        //System.out.println(prop1);
        //通过类名访问静态内部类的类成员
        System.out.println(StaticInnerClass.prop1);
        //System.out.println(prop2);
        //通过实例访问静态内部类的实例成员
        System.out.println(new StaticInnerClass().prop2);
    }
}

AccessStaticInnerClass.java:8: 错误: 找不到符号
System.out.println(prop1);
^
符号: 变量 prop1
位置: 类 AccessStaticInnerClass
AccessStaticInnerClass.java:10: 错误: 找不到符号
System.out.println(prop2);
^
符号: 变量 prop2
位置: 类 AccessStaticInnerClass
2 个错误

Java还允许在接口里定义内部类,接口里定义内部类,接口里的内部类默认使用public static 修饰,所以只能是静态内部类。

接口里可以定义内部接口,但是实际开发中很少见到

5.7.3 使用内部类

定义类的作用:

  • 定义变量
  • 创建实例
  • 作为父类被继承

定义内部类的主要作用也是一样的

下面三种情况讨论内部类的用法:

  1. 在外部类内部使用内部类
    -在外部类内部使用内部类的时候与平常使用普通类没有太大区别。唯一存在的区别是:不要在外部类的静态成员(包括静态方法和静态初始化块)中使用非静态内部类,因为静态成员不能访问非静态成员

  2. 在外部类以外使用非静态内部类
    -不能使用private访问控制权限
    在外部类以外的地方使用内部类,内部类完整的类名应该是OuterClass.InnerClass。有包名还要加包名前缀。
    在创建非静态内部类对象之前,必须先创建其外部类对象

CreateInnerInstance.java

package code;
class Out{
    class In{
        public In(String msg){
            System.out.println(msg);
        }
    }
}
public class CreateInnerInstance{
    public static void main(String [] args){
        Out.In in = new Out().new In("测试信息");
        /*
            上面代码可改为如下三行代码:
                使用OutterClass.InnerClass的形式定义内部类变量
            Out.In in;
                创建外部类实例,非静态内部类实例将寄生在该实例中
            Out out = new Out();
                通过外部类实例和nei来调用内部类构造器创建非静态内部类实例
            in = out.new In("测试信息");

        */
    }
}

测试信息

非静态内部类的构造器必须使用外部类对象来调用。
需要在外部类以外的地方创建非静态内部类的子类,则尤其要注意:非静态内部类的构造器必须通过其外部类对象来调用。
当创建一个子类时,子类构造器总会调用父类的构造器,因此在创建非静态内部类的子类时,必须保证让子类构造器可以调用非静态内部类的构造器,调用非静态内部类的构造器时,必须存在一个外部类对象。

SubClass.java

package code;
public class SubClass extends Out.In{
    public SubClass(Out out){
        out.super("hello");
    }
}

非静态内部类的子类不一定是内部类,它可以是一个外部类。但非静态内部类的子类实例一样需要保留一个引用,该引用指向其父类所在外部类的对象,也就是说,如果有一个内部类子类的对象存在,则一定存在与之对应的外部类对象。

3.在外部类以外使用静态内部类
因为静态内部类是外部类类相关,因此创建静态内部类对象时无需创建外部类对象,

CreateStaticInnerInstance.java

package code;
class StaticOut{
    //定义一个静态内部类,不使用访问控制符
    //即同一个包中的其他类可访问该内部类
    static class StaticIn{
        public StaticIn(){
            System.out.println("静态内部类的构造器");
        }
    }
}
public class CreateStaticInnerInstance{
    public static void main(String[]args){
        StaticOut.StaticIn in = new StaticOut.StaticIn();
        /*上面代码可改为:
        使用OuterClass.InnerClass的形式定义内部类变量
        StaticOut.StaticIn in;
        通过new来调用内部类构造器创建静态内部类的实例
        in = new StaticOut.StaticIn();


        */
    }
}

静态内部类的构造器

不管是静态内部类还是非静态内部类,他们声明变量的语法完全一样。
区别只是在创建内部类对象时,静态内部类只需使用外部类即可调用构造器,而非静态必须使用外部类对象来调用构造器
因为调用静态内部类的构造器时无须使用外部类对象,所以创建静态内部类的子类也比较简单,

public class StaticSubClass extends StaticOut.StaticIn(){}

当定义一个静态内部类时,其外部类非常像一个包空间

所以当程序需要使用内部类时,应该优先考虑使用静态内部类

不可以再子类中重写父类的内部类

5.7.4 局部内部类

如果把一个内部类放在方法中定义,则这个内部类就是一个局部内部类。
所有的局部成员都不能使用static修饰,

package code;
public class LocalInnerClass{
    public static void main(String [] args){
        class InnerBase{
            int a;
        }
        class InnerSub extends InnerBase{
            int b;
        }
        InnerSub is = new InnerSub();
        is.a = 5;
        is.b = 4;
        System.out.println("InnerSub对象的a和b实例对象是" + is.a + "," + is.b);
    }
}

InnerSub对象的a和b实例对象是5,4

局部内部类的class文件的文件名比成员内部类的class文件的文件名多了一个数字。这是为了区分同一个类里不可能有两个同名的成员内部类,而同一个类里则可能有两个以上同名的局部内部类(处于不同的方法中)。

因为局部内部类的的作用域太小了,只能在当前方法使用,所以在实际开发中很少使用局部内部类

5.7.5 java8改进的匿名内部类

匿名内部类适合创建只需要一次使用的类,不能重复使用。
两条规则:

  • 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。
  • 匿名内部类不能定义构造器。但可以定义初始化类,可以通过实例初始化块来完成构造器需要完成的事情。

AnonymousTest.java

package code;
interface Product{
    public double getPrice();
    public String getName();
}
public class AnonymousTest{
    public void test(Product p){
        System.out.println("购买了一本" + p.getName() + ",花掉了" + p.getPrice());
    }
    public static void main(String[] args){
        AnonymousTest at = new AnonymousTest();
        at.test(new Product(){
            public double getPrice(){
                    return 4.55;
            }
            public String getName(){
                return "英语书";
            }
        });
    }
}

购买了一本英语书,花掉了4.55

定义匿名内部类无须class关键字,而是在定义匿名内部类时直接生成该匿名内部类的子类
匿名内部类必须实现它的抽象父类或者接口里包含的所有抽象方法。

当通过实现接口来创建匿名内部类时,匿名内部类也不能显式创建构造器。因此只有一个隐式的无参数构造器。所以new接口名括号里不能传入参数值。
但如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,相似指的是拥有相同的形参列表。
AnonymousInner.java

package code.AnonymousInner;
abstract class Device{
    private String name;
    public abstract double getPrice();
    public Device(){};
    public Device(String name){
        this.name = name;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}
public class AnonymousInner{
    public void test(Device d){
        System.out.println("购买了一个"+ d.getName() +",花掉了" + d.getPrice());
    }
    public static void main(String[]args){
        AnonymousInner at = new AnonymousInner();
        at.test(new Device("电子示波器"){
            public double getPrice(){
                return 2.33;
            }
        });
        Device d = new Device(){
            {
                System.out.println("匿名内部类的初始化块...");
            }
            public double getPrice(){
                return 4.66;
            }
            public String getName(){
                return "键盘";
            }
        };
        at.test(d);
    }
}

购买了一个电子示波器,花掉了2.33
匿名内部类的初始化块…
购买了一个键盘,花掉了4.66

Java8新功能:如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰
ATest.java

package code;
interface A{
    void test();
}
public class ATest{
    public static void main(String [] args){
        int age = 8;
        A a = new A(){
            public void test(){
                //从Java8开始,匿名内部类,局部内部类允许访问非final的局部变量。
                //在Java8以前下面语句将提示错误:age必须使用final修饰
                System.out.println(age);
            }
        };
        a.test();
    }
}

8

Java8将这个功能称为“effectively final”.

电磁波函数复数表示法:为什么物理学家偏爱e^(ikz)而非cos(kr-wt)? 本文深入解析了电磁波函数复数表示法(如e^(ikz))相较于传统余弦形式的巨大优势。通过欧拉公式,复数形式将复杂的三角运算转化为简洁的指数运算,在微分、积分、线性叠加及处理相位时展现出极高的计算效率,是物理学家和工程师分析波动现象的核心工具。 阅读详情

相关推荐

XIAO ESP32S3 Sense摄像头与麦克风实战:从硬件连接到AI语音视觉项目

本文详细介绍了如何使用Seeed Studio XIAO ESP32S3 Sense开发板进行AI语音视觉项目开发。从硬件连接到Arduino环境搭建,再到摄像头拍照、视频流传输、麦克风录音等实战操作,最后引导读者探索基于TensorFlow Lite Micro的语音唤醒和SenseCraft AI的图像识别等AI应用,为物联网和边缘AI项目提供了完整的入门指南。

xray4的博客 988

Java内部类详解(含:成员内部类、局部内部类匿名内部类、静态内部类)

Java内部类详解(含:成员内部类、局部内部类匿名内部类、静态内部类)

leaf__yang的博客 2万+

树莓派5搭建ROS1开发环境:从系统安装到环境变量配置

本文详细指导如何在树莓派5上搭建ROS1开发环境。针对树莓派OS非标准安装路径导致的常见CMake报错问题,提供了从系统烧录、一键安装ROS到关键环境变量配置的完整解决方案,确保工作空间能成功编译,助力机器人项目开发。

weixin_29159127的博客 357

内部类(成员内部类、静态内部类、方法内部类)

一:成员内部类:最常见的内部类就是成员内部类,也称作普通内部类;1、Inner类定义在Outer类的内部,相当于Outer类的成员变量的位置,Inner类可以使用任意访问修饰符,如:public、private、protected等。2、Inner类中定义的test()方法可以访问Outer类中的数据,不受访问控制符的影响。3、定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去......

liu771626413的博客 4万+

什么是内部类内部类的种类?内部类的作用?

一、什么是内部类 将一个类定义在一个类或者一个方法里面,这样的类称着内部类 https://www.jianshu.com/p/83a50ef23279 https://blog.csdn.net/lianxu3344/article/details/79473607 https://blog.csdn.net/flyfeifei66/article/details/82686086 https:...

T-bright的博客 1万+

内部类(成员内部类、局部内部类匿名内部类、静态内部类

内部类(成员内部类、局部内部类匿名内部类、静态内部类

weixin_44216665的博客 5896

java内部类之成员内部类、局部内部类匿名内部类

内部类概念 一个类中包含另外一个类。 分类 1、成员内部类。 2、局部内部类(包含匿名内部类)。 成员内部类 定义格式: 修饰符 class 类名称 { 修饰符 class 类名称 { //... } //... } 注意: 内部类使用外部,可以随意访问,但是外部类使用内部类要借助内部类的对象。 使用成员内部类 两种方法: 1...

green703338130的博客 6709

Java基础】内部类 (成员内部类、局部内部类、静态内部类匿名内部类

Java内部类 (成员内部类、局部内部类、静态内部类匿名内部类

good good study day day up 3387

内部类(成员内部类+局部内部类+静态内部类+匿名内部类

内部类的定义:在java中,允许在一个类的内部定义类,称为内部类,这个内部类所在的类称为外部类。内部类定义在外部内的内部,通常只服务于外部类,对于其他外部是不具备可见性的。内部类应用场景:1.当某个类只为一个类提供服务时,可以将这个类定义成内部类 2.可以解决接口或者抽象类不能实例化的问题 成员内部类:在一个类中除了可以定义成员变量,成年方法,还可以定义类,这样的类称为成员内部类。在成员内部类中可以访问外部类的所有成员资源(包括私有成员),例如成员变量

qq_51768153的博客 4352

Java 四大内部类总结——局部内部类匿名内部类,成员内部类,静态内部类

Java 四大内部类总结——局部内部类匿名内部类,成员内部类,静态内部类

prince0520的博客 3100

什么是内部类内部类的作用

java语言中,可以把一个类定义到另外一个类的内部,在类里面的这个类就叫内部类,外面的类就叫外部类。 在这情况下,这个内部类可以看做外部类的一个成员。 内部类好处 1.隐藏你不想让别人知道的操作,也即封装性。 public interface Contents { int value(); } public interface Destination { String readLabel...

yy471101598的博客 9667

Java内部类这一篇就够啦,超详细,新人友好(成员内部类、静态内部类、局部内部类匿名内部类

详细的介绍成员内部类、静态内部类、局部内部类匿名内部类,超详细,值得收藏!

shiyuechunfeng的博客 2757

什么是内部类?成员内部类、静态内部类、局部内部类匿名内部类的区别及作用?

一、什么是内部类?or 内部类的概念 内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。 public class TestA{ class TestB {} } 二、 为什么需要内部类?or 内部类有什么作用? 1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。 2、内部类可以对同一个包中的其他类隐藏起来。 3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。 三、 内部类的分类 成员内部

sulixu的博客 3815

内部类与静态内部类

内部类与静态内部类 目录 前言 内部类 1.1 非静态内部类 1.1.1 定义 1.1.2 内部类的特殊语法规则 1.2 静态内部类 回到顶部 前言   如果你是一个急性子,没什么耐性的人,可以只看下句,自己去品味理解:   内部类:就是我是你的一部分,我了解你,我知道你的全部,没有你就没有我。(所以内部类对象是以外部类对象存在为前提的)   静态内部类:就是我跟你没关系,自己可以完全独立存在,但是我就借你的壳用一下,来隐藏自己。   如果还不知道静态和普通成员..

qq_40826814的博客 2979

面试 | 什么是内部类?成员内部类、静态内部类、局部内部类匿名内部类的区别及作用?

1 内部类的概念 内部类是定义在另一个类中的类;下面类B是类A的内部类。即内部类对象引用了实例化该内部对象的外围类对象。 public class A{ class B {} } 2 为什么需要内部类?(来自JAVA核心技术) 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。 内部类可以对同一个包中的其他类隐藏起来。 当想要定义一个回调函数且不想编写大量代码时,使用匿名内...

星空下的程序猿 3244

Java 内部类 ==> 成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类

一般情况,我们把类定义成独立的单元。有些情况下,我们把一个类放在另一个类的内部定义,称为内部类(innerclasses)。 内部类可以使用public、default、protected 、private以及static修饰。而外部顶级类(我们以前接触的类)只能使用public和default修饰。 注意 内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不...

郑德帅 7431

java内部类之成员内部类、静态内部类

内部类其实就是一个类中还包含着另外一个类 如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)显然,此处不能单方面用属性或者方法表示一个心脏,而需要一个类,而心脏又在人体当中,正如同是内部类在外部内当中 广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类匿名内部类和静态内部类。下面就先来了解一下这四种内部

gongpulin的博客 4363

java内部类之私有内部类、局部内部类匿名内部类

一、私有内部类: class Out { private int age = 12; private class In { public void print() { System.out.println(age); } } public void outPrint() { new

gongpulin的博客 1万+

Java-内部类:成员内部类、局部内部类匿名内部类、静态内部类

本文介绍了Java内部类:成员内部类、局部内部类匿名内部类、静态内部类,从5W2H以及它们的区别进行了描述

向诸位大佬虚心学习 1749

Java基础巩固——内部类(静态内部类,局部内部类匿名内部类)详细讲解

(也叫嵌套类)

Future_yzx的博客 1234

内部类(成员内部类、局部内部类匿名内部类

1、内部类概述和访问特点 内部类概述: 把类定义在其他类的内部,这个类就被称为内部类。 举例:在类A中定义了一个类B,类B就是内部类内部类访问特点 a:内部类可以直接访问外部类的成员,包括私有。 b:外部类要访问内部类的成员,必须创建对象。 2、内部类分类 根据内部类定义的位置不同可以分为:成员内部类和局部内部类 成员内部类:将内部类定义到外部类的成员位置 局部内部类:将内部类定义到外部类的局部位置(方法内) class ...

满眼星陈ya的博客 1302
上一篇: java8改进的接口
下一篇: Java8新增的Lambda表达式
CXD_zy
博客等级 码龄13年 2粉丝 26原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值