Java——内部类(inner class)

mac2022-06-30  78

为什么要使用内部类?

主要因为以下三点:

1、内部类方法可以访问该类定义所在的作用域的数据,包括私有数据。 2、内部类可以对同一个包中的其他类隐藏起来。 3、想要定义一个回调函数却不想编写大量代码,使用匿名内部类比较便捷。  

一个类的定义放在另一个类的内部,这个类就叫做内部类。 (类名不需要和文件夹相同)

public class Inner { //像这样的,Contents就叫做内部类 public class Contents { public void f() { System.out.println("hello"); } } }

内部类可以是静态static的,也可用public,default,protected和private修饰。而外部类(类名和文件名相同的类)只能使用public和default来修饰。

内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类编译成用$分隔外部类名与内部类名的常规类文件,而虚拟机对此一无所知。 例如:对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。

 

内部类分为以下四种:      

静态内部类static inner class (also called nested class)

成员内部类member inner class

局部内部类local inner class

匿名内部类anonymous inner class

 

静态内部类Static Inner Class

1、最简单的内部类形式。

2、类定义时加上static关键字。

3、不能和外部类有相同的名字。

4、只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。

5、生成静态内部类对象的方式为:

  OuterClass.InnerClass inner = new OuterClass.InnerClass();

  package cy.内部类.静态内部类; public class StaticOuter { private static String name = "Outer"; private int age = 10; public static class StaticInner { @SuppressWarnings("unused") private static String name = "Inner"; public void sayOuterName() { System.out.println("inner:" + StaticOuter.name); } /* * 错误,静态内部类不能访问外部类的非静态成员。 public void sayOuterAge() { System.out.println(age); } */ } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } } package cy.内部类.静态内部类; public class TestMain { public static void main(String[] args) { StaticOuter staticOuter = new StaticOuter(); staticOuter.sayAge(); staticOuter.sayName(); StaticOuter.StaticInner staticInner = new StaticOuter.StaticInner(); staticInner.sayOuterName(); } }

运行结果:

10Outerinner:Outer

由此可以看出,静态内部类的对象处了没有对外围类对象的应用特权外,与其他所有内部类完全一样。

 

成员内部类member inner class

package cy.内部类.成员内部类; public class Outer { private static String name = "Outer"; private int age = 10; public class Inner { private final static String name = "Inner"; private int age = 11; public void sayOuterName() { // 内部类中引用外部类对象的静态成员 System.out.println("inner:" + Outer.name); } public void sayInnerName() { System.out.println("inner:" + Inner.name); } public void sayInnerAge() { System.out.println("inner:" + this.age); } public void sayOuterAge() { // 内部类中引用外部类对象的非静态成员 System.out.println(Outer.this.age); } public Outer createOuter() { // 内部类中创建外部类。 return new Outer(); } } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } public Inner createInner() { // 外部类中创建内部类对象。 return this.new Inner(); } } public class TestMain { public static void main(String[] args) { Outer outer = new Outer(); outer.sayAge(); outer.sayName(); // 区别于静态内部类的创建方法 Inner inner = outer.new Inner(); inner.sayOuterName(); } }

运行结果:

10Outerinner:Outer

 

局部内部类local inner class

局部类不能用public,protected或者private访问说明符进行声明。它的作用域是被限定在这个局部类的块中。

局部类有一个优势,即对外世界可以完全隐藏起来,其他类中的代码不能访问它。

package cy.内部类.局部内部类; public class Outer { private static String name = "Outer"; private int age = 10; public void doSomeThing() { // 局部内部类,局部内部类,不允许带有 public,protected,private // public class Inner { // protected class Inner { // private class Inner { class Inner { // private static String name; // private final static String name; public void sayInnerName() { System.out.println(name); } public void sayOuterName() { System.out.println(Outer.name); } } Inner inner = new Inner(); inner.sayInnerName(); inner.sayOuterName(); } public void doSomeThingA() { if (this.age > 0) { // 这个Inner与上一个Inner没有任何关系 class Inner { public void sayInnerName() { System.out.println(name); } public void sayOuterName() { System.out.println(Outer.name); } } Inner inner = new Inner(); inner.sayInnerName(); inner.sayOuterName(); } } public void sayName() { System.out.println(name); } public void sayAge() { System.out.println(age); } }

 

匿名内部类anonymous inner class

假设这创建某个类的一个对象,就不必命名了,这种类成为“匿名内部类”。

package cy.内部类.匿名内部类; public class Outer { public static void main(String[] args) { // 内部类引用外部类对象,使用final。 final String name = "name"; // 接口直接创建对象。类名称并没有直接定义。Java编译器会自动给一个类名称。 // 注意匿名内部类的重要使用场景。“线程” Say s = new Say() { @Override public void say() { System.out.println("hello world " + name); } }; s.say(); } } interface Say { void say(); }

这种语法有点难理解,它的含义是:创建一个实现Say接口的类的新对象,需要实现的方法say定义在{}中。

由于构造器的名字必须跟类名相同,而匿名类没有名称,所以匿名类不能有构造器。取而代之的是,构造器参数传递给超类(superclass)构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。

转载于:https://www.cnblogs.com/iCcccy/p/4692227.html

最新回复(0)