綠 青 色

内部类总结

内部类

   内部类就是在一个类的内部定义的类。
内部类

成员内部类:

  内部类对象依赖外部类对象而存在,即在创建一个普通内部类对象时首先需要创建其外部类对象。
  内部类对象可以访问外部类对象中所有访问权限的字段,同时,外部类对象也可以通过内部类的对象引用来访问内部类中定义的所有访问权限的字段。

成员内部类格式如下

class 外部类 {
	修饰符 class 内部类 {
		// 其它代码
	}
}

编译上述代码会产生两个文件:
  外部类.class 和 外部类\(内部类.class   例:Outer.class 和 Outer\)Inner.class

在外部创建内部类对象
   内部类除了可以在外部类中产生实例化对象,也可以在外部类的外部来实例化。
   那么,根据内部类生成的 *.class 文件:Outer\(Inner.class    “\)” 符号在程序运行时将替换成 “.
   所以内部类的访问:通过 “外部类.内部类” 的形式表示。

Outer out = new Outer();	// 产生外部类实例
Outer.Inner in = out.new Inner();	// 产生内部类实例

成员内部类访问方式:

   外部类名.内部类名 变量名 = new 外部类名(实参列表).new 内部类名(实参列表);

局部内部类:

局部内部类的特点:

  • 局部内部类局部变量一样,不能使用访问控制修饰符(publicprivateprotected)和 static 修饰符修饰。

  • 局部内部类只在当前方法中有效。

  • 局部内部类中不能定义 static 成员。

  • 局部内部类中还可以包含内部类,但是这些内部类也不能使用访问控制修饰符(public、 private 和 protected)和 static 修饰符修饰。

  • 在局部内部类中可以访问外部类的所有成员。
       访问外部类成员变量:外部类.this.成员变量,访问外部类成员方法:外部类.this.成员方法

  • 在局部内部类中只可以访问当前方法中 final 类型的参数与变量。

注意
   a、局部内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
   b、局部内部类对象不能使用该内部类所在方法的非final局部变量。

局部内部类格式如下

class 外部类 {
	修饰符 返回值类型 方法名(参数列表) {
		class 内部类 {
			// 其他代码
		}
	}
}
// 例:
class Outer {
	public void doSomething(){
		class Inner{
			public void seeOuter(){}
        }
  }
}

注意:局部内部类访问的外部局部变量都必须用 final修饰,以防止更改外部局部变量的值。jdk1.8之后不必添加final

静态内部类:

  使用static修饰的内部类我们称之为静态内部类
    关键字static可以修饰成员变量、方法、代码块,static还可以修饰内部类。

在一个类内部定义一个静态内部类:
  静态的含义是该内部类可以像其它静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
  静态内部类中也无法访问外部类的非静态成员。

静态内部类格式如下

class Outer{
  static class Inner{}
}
class Test {
  public static void main(String[] args){
  	Outer.Inner n = new Outer.Inner();
		}
}

静态内部类访问的方式:

  外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名(形参列表);

注意:

  1、静态内部类的创建不需要依赖外部类。
  2、 静态内部类不能使用外部类的非static成员变量和方法。
  3、 如果内部类中定义了静态成员,那么该内部类也必须是静态的。

匿名内部类:

  匿名内部类就是没有名字的内部类。

匿名类有两种实现方式:

  • 继承一个类,重写其方法。

  • 实现一个接口(可以是多个),实现其方法。

匿名内部类格式如下

class 外部类 {
	public 返回值类型 方法名(参数列表) {
		new 接口() | 父类构造器(参数列表) {
			// 其他代码
		}
	}
}

匿名内部类的特点
  (1) 匿名类和局部内部类一样,可以访问外部类的所有成员。如果匿名类位于一个方法中,则匿名类只能访问方法中 final 类型的局部变量和参数。
  (2)匿名类中允许使用非静态代码块进行成员初始化操作。
  (3)匿名类的非静态代码块会在父类的构造方法之后被执行。

在使用匿名内部类时,要记住以下几个原则
  (1)不能有构造方法,只能有一个实例。
  (2)不能定义任何静态成员、静态方法。
  (3)不能是public,protected,private,static
  (4)一定是在new的后面,用其隐含实现一个接口或继承一个类。
  (5)匿名内部类为局部的,所以局部内部类的所有限制都对其生效

局部内部类访问局部变量必须用final修饰,为什么?
   当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法被调用时会入栈,
方法结束后即弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,显然已无法使用了,
如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也就可以继续使用了。

注意:在jdk1.8中取消了在局部内部类中使用的变量必须显示的使用final修饰,编译器默认会为这个变量加上final

内部类的作用
   每个内部类都能独立地继承自一个(接口的)实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,
内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。

   依赖外部类对象的:成员内部类,方法内部类,匿名内部类
  静态内部类不依赖外部类的对象。所以,我们在项目中优先考虑选择静态内部类(不会产生内存泄露)

posted @ 2019-09-04 23:19  LYANG-A  阅读(166)  评论(0编辑  收藏  举报