内部类的分类
匿名内部类---通常碰到
局部内部类---很少遇到
成员内部类--通常遇到---有多少个内部类就生成多少个$类名.class文件
非静态内部类
静态内部类
成员内部类
非静态内部类
特点:
-
外部类里使用非静态内部类和平时使用其他类没什么不同
-
非静态内部类必须寄存在一个外部类对象里
-
如果有一个非静态内部类对象,那么一定存在对应的外部类对象
-
非静态内部类对象单独属于外部类的某个对象
-
-
有内部类对象必然也有外部类对象
好处:
-
非静态内部类可以直接访问外部类的成员,外部类不能直接访问非静态内部类成员---内部类就是为了外部类提供服务的,内部类可以提供一个非常良好的封装环境,我能用你、你不能用我
-
非静态内部类不能有静态方法、静态属性、静态初始化块---要有的话内部类也要定义成静态的
-
外部类的静态方法、静态代码块不能访问非静态内部类,不能使用非静态内部类定义的变量、创建实例
成员变量访问要点:
-
内部类里方法的局部变量:变量名
-
内部类属性:this.变量名
-
外部类属性:外部类名.this.变量名---类似于Java中类似C语言的goto的标签
实例:
package com.cxl;
import sun.util.resources.cldr.ne.TimeZoneNames_ne;
/**
* 测试非静态内部类
* @author Lucifer
*/
public class TestInnerClass {
/*写一个主线程,创建一个内部类对象(Inner)和外部类对象(Outer)*/
public static void main(String[] args) {
/*创建外部类Outer对象*/
Outer oth = new Outer();
/*创建Outer中的内部类Inner的对象*/
/*
因为我们的Inner是普通的非静态内部类
要创建对象要依托外部类的对象
*/
Outer.Inner inn = new Outer().new Inner();
//外部类以外的地方使用非静态内部类
//这就是为什么能在内部类直接调用外部类的属性和方法的原因,以为创建内部类对象必须要有外部类对象
/*调用内部类的方法*/
inn .show();
}
}
/*定义一个外部类*/
class Outer{
/*
这是一个普通的类
可以随便定义属性、方法
*/
private int age = 22;
public void testOuter(){
System.out.println("Outer.testOuter()");
}
/*
定义一个非静态内部类---不用static修饰
类似一个成员一样放到外部类里面,所以称之为成员内部类
成员内部类又分为:
1.非静态内部类
2.静态内部类
(关键点在于是否用static修饰类名)
*/
class Inner{
/*也可以定义内部类具体的属性,要访问直接this.属性名*/
int age = 21;
/*在这内部类里面可以定义属性和方法*/
/*内部类可以直接访问外部类的属性和方法*/
public void show(){
/*也可以定义局部变量*/
int age = 20; //访问的时候直接是变量名
/*访问外部类的成员变量和方法*/
System.out.println("外部类的成员变量age:" + Outer.this.age);
System.out.println("内部类的成员变量age:" + this.age); //可以重复相同的变量名,指定的类空间不同
System.out.println("内部类方法的局部变量:" + age);
}
}
}
静态内部类
一个static成员
定义方式:
static class ClassName{
//类体
}
使用要点:
-
静态内部类对象存在,并不一定存在对象的外部类对象所以静态内部类的实例方法不能直接访问外部类的实例方法
-
静态内部类看做外部类的一个静态成员。外部类的方法可以通过:"静态内部类.名字"的方式访问静态内部类的静态成员,通过new静态内部类()访问静态内部类的实例
实例:
package com.cxl;
/**
* 测试静态内部类
* @author Lucifer
*/
public class TestStaticInnerClass {
/*建静态内部类实例*/
Outer2.Inner2 inn = new Outer2.Inner2();
/*
从语法可以看出来:
静态内部类对象不需要依托于外部类对象
*/
}
/*创建一个外部类*/
class Outer2{
/*在里面定义一个staticclassinner*/
//它就像一个静态成员一样---声明周期
static class Inner2{
/*
里面可以有自己的属性和方法
*/
}
}
匿名内部类---GUI或者安卓编程常用
特点:
适合只需要使用一次的类---键盘监听
定义方式:
new 父类构造器(实参类表)(或者) \实现接口(){
//匿名内部类类体!
}
注意:
-
匿名内部类没有访问修饰符
-
匿名内部类没有构造方法,因为匿名内部类没有名字
实例:
package com.cxl;
/**
* 测试匿名内部类
* @author Lucifer
*/
public class TestAnonymousInnerClass {
/*写一个形参为接口对象的方法*/
public static void test01(AA a){
System.out.println("########");
a.aa(); //需要传一个接口对象来调用接口的方法
}
/*main方法*/
public static void main(String[] args) {
TestAnonymousInnerClass.test01(new AA(){
/*重写接口的方法用于实现接口*/
局部内部类---用得很少
特点:
-
定义在方法内部,作用域只限于本方法
-
局部内部类和成员内部类一样被编译,但是作用域发送了变化。只能在该方法中被使用。出了该方法就会失效
应用场景:
-
创建一个类,又不希望类是公共可用的,产生了局部内部类。
-
在方法内部提供封装,仅供内部使用
实例:
package com.cxl;
/**
* 测试局部内部类
* @author Lucifer
*/
public class TestPartInnerClass {
/*定义一个方法,里面使用局部内部类定义一个具体的实现*/
public void show(){
//仅限于该方法内使用的内部类
class Inner{
/*局部内部类的方法*/
public void fun(){
System.out.println("HelloWorld!");
}
}
/*实例化内部类调用里面的方法*/
new Inner().fun();
}
//实例化TestPartInnerClass类,调用方法
public static void main(String[] args) {
new TestPartInnerClass().show();
}
}