JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java|类的嵌套结构:内部类、静态嵌套类,匿名类

wys521 2024-11-24 22:42:58 精选教程 29 ℃ 0 评论

在Java系统中可以通过静态嵌套类与内部类的声明操作将嵌套结构导入类的设计之中,让具有相关功能的类相互配合,进而方便程序设计人员控制这些类的使用范围(作用域)。在Java类的声明中可以包含其他类声明的成员,这种概念称为嵌套类(Nested Class)。嵌套类分为两种:一种是非静态嵌套类(Non-Static Nested Class),也称为内部类。另一种是静态嵌套类(Static Nested Class),内部类被static修饰。另外,嵌套类还可以匿名。

内部类编译后的文件名为:“外部类名$内部类名.java”;

为什么内部类可以直接访问外部类中的成员呢?

那是因为内部中都持有一个外部类的引用。这个是引用是

外部类名.this

内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。

当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。

如果内部类被静态修饰,相当于外部类,会出现访问局限性,只能访问外部类中的静态成员。如果内部类中定义了静态成员,那么该内部类必须是静态的。

1 内部类(非静态嵌套类)

如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,可以直接将A类定义在B类中,A类就称为内部类,B类称为外部类。内部类可以直接访问外部类中的成员,包括私有成员。而外部类想要访问内部类,必须要建立内部类的对象。

由于内部类与其他的实例类成员一样都附属于主类对象,因此可以直接存取对象的实例变量(Instance Variable)与实例方法(Instance Method),并且在内部类之中不得包含任何静态成员(Static Member)。

class Outer{
    int num = 4;
    class  Inner {
        void show(){
            System.out.println("inner show run "+num);	// 内部类访问外部类的成员
        }
    }
    public void method(){
        Inner in = new Inner();  // 创建内部类的对象。
        in.show();               // 调用内部类的方法。
    }
}

以下demo code在有嵌套的类中没有使用static关键字,正常:

class InnerClassDemo {
    class Inner{
            void show(){System.out.println("hi");}
    }
    public void method(){
        this.new Inner().show();
    }
}

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        InnerClassDemo ic = new InnerClassDemo();
        ic.method(); // hi
        
    }
}

以下在有嵌套的类中在静态方法中不允许使用this:

class InnerClassDemo {
    class Inner{
            void show(){}
    }
    public void method(){
        this.new Inner().show();		//可以
    }
    public static void main(String[] args) {		//	static不允许this
        this.new Inner().show();												//	错误,Inner类需要定义成static
    }
}

如果有外部类在静态方法(如main()主执行区块)中创建内部类对象,就必须使用完整的类路径语句来指定该对象的引用位置,并在外部类中声明内部类的相关方法,该方法返回内部类创建对象的引用值:

class OuterClass{
    // 主类构造函数
    public OuterClass(){
        System.out.println("主类构造函数的语句");
    }
    // 声明静态嵌套类
    static class InnerClass{
        public InnerClass(){
            System.out.println("静态嵌套类构造函数的语句");
        }
        void show(){System.out.println("hi");}
    }
    // 主程序区块
    public static void main(String args[]){
        new OuterClass();
        new InnerClass().show();
    }
}

2 静态嵌套类

静态嵌套类不同于内部类,并不是依附于主类(外部类)创建的对象,而是直接附属于主类。因此,静态嵌套类无法直接存取实例变量或调用任何实例方法,只能通过对象来间接存取或调用类的实例成员。

另外,由于静态嵌套类属于主类的静态成员,因此可以不通过主类的成员方法来返回对象实现的引用值,即可以直接在主类的静态方法(例如main()主执行区块)中进行内部类对象的创建工作。

class InnerClassDemo {
    static class Inner{
        void show(){
            System.out.println("hi");
        }
    }
    public void method(){
        new Inner().show();
    }
    public static void main(String[] args) {
        new InnerClassDemo();
        new Inner().show();//hi
    }
}

3 匿名内部类

如果我们所声明的内部类或嵌套静态类必须继承某个类或实现某个接口,就可以在不定义类名称的情况下,直接通过基类或接口的构造函数引用值来创建该类的对象:

class Ideone
{
    public static void main (String[] args)
    {
        Object obj = new Object(){
            public String toString(){
                return "这是一个内部的匿名类!";
            }
        };
    }
}

这种不具有类名,但可以直接调用基类或接口的构造函数来创建派生类对象的类,我们称其为匿名类(Anonymous Class)或匿名内部类。匿名类的语法格式如下:

基类(接口)名称派生匿名类对象 = new 基类(接口)构造函数(){
      // 声明匿名类成员的程序语句
}
// 或
new 父类名或接口名(){ 定义子类成员或者覆盖父类方法 }.方法;

匿名内部类是嵌套类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:内部类必须继承一个类或者实现接口。

new Object(){
    void show(){
        System.out.println("show run");
    }
}.show();

以下是错误的示范:

Object obj = new Object(){
    void show(){
        System.out.println("show run");
    }
};
obj.show();

编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时检查Object类中是否有show方法,所以编译失败。

匿名类一般用于实现一个接口或继承一个特定的类:

interface Inter{
    void show();
}
class Outer{//通过匿名内部类补足Outer类中的代码。
    public static Inter method(){
        return new Inter(){
                public void show(){System.out.println("hi");}
        };
    }
}
class InnerClassDemo {
    public static void main(String[] args) {
        Outer.method().show(); // hi
        /*
        Outer.method():意思是:Outer中有一个名称为method的方法,而且这个方法是静态的。
        Outer.method().show():当Outer类调用静态的method方法运算结束后的结果又调用了show方法,意味着:method()方法运算完一个是对象,而且这个对象是Inter类型的。
        */
        function (new Inter(){
                public void show(){System.out.println("hello");}
            }); //匿名内部类作为方法的参数进行传递。
        }
        public static void function(Inter in){
            in.show(); // hello
        }
    }
}

demo code 2:

class OuterClass{
    //外部类构造函数
    public OuterClass(){
        System.out.println("成功实现外部类的构造函数!!!");
    }
    //声明内部类
    class MyInnerClass{
    //内部类的构造函数
        public MyInnerClass(){
            System.out.println("  成功实现内部类的构造函数!!!");
        }
        public void show(){
            System.out.println("    成功调用内部类的show()方法!!!");
        }
    }
	//声明并定义内部匿名类
    public MyInnerClass MyInnerClass(){
        //返回内部匿名类创建的方法
        return new MyInnerClass(){
            //覆盖(重新定义)内部类的成员方法
            public void show(){
                System.out.println("    成功调用内部匿名类的show()方法!!!");
            }
        };
    }
    //主程序区块
    public static void main(String args[]){
        //创建主类对象
        OuterClass myObject = new OuterClass();
        //创建内部匿名类对象
        MyInnerClass myAnonymous = myObject.MyInnerClass();
        //调用内部匿名类覆盖(重新定义)的方法
        myAnonymous.show();
    }
}
/*output:
成功实现外部类的构造函数!!!
  成功实现内部类的构造函数!!!
    成功调用内部匿名类的show()方法!!!
*/

ref

赵军 吴灿铭《编程语言 Java程序设计与计算思维》

-End-

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表