在Java中内部类主要分为成员内部类(非静态内部类、静态内部类)、匿名内部类、局部内部类。
局部内部类基本用不着,很少情况碰到,一般碰到的是匿名内部类和成员内部类。
成员内部类里面又包含了非静态内部类和静态内部类。
目录
成员内部类可以直接访问外部类的成员,非常方便,为外部类提供服务
成员内部类
非静态内部类
非静态内部类定义方式
public class Test{
public static void main(String[] args) {
}
}
class Outer{
private int age = 10;
public void testOuter() {
}
class Inner{//静态内部类
}
}
像成员一样,定义在外部的类里面,所以叫它成员内部类。如果加了static,就是静态内部类;如果不加static修饰,就是非静态内部类。
虽然Inner类在Outer类里面,但也会生成2个不同的class文件,可以去bin目录下查看一下,有一个Outer.class文件和Outer$Inner.class文件,分别对应2个类。
成员内部类可以直接访问外部类的成员,非常方便,为外部类提供服务
public class Test{
public static void main(String[] args) {
}
}
class Outer{
private int age = 10;
public void testOuter() {
}
class Inner{
public void show() {
System.out.println("外部类的成员变量age:" + Outer.this.age);
}
}
}
类名.this(访问到外部类对象)
创建内部类对象
因为这是普通的非静态内部类,所以创建的时候要依托于外部类,要先创建外部类的对象。
也就是有内部类对象的时候,必然也有外部类对象,这也是为什么内部类可以直接调用外部类属性的原因。
public class Test{
public static void main(String[] args) {
//创建内部类对象
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
class Outer{
private int age = 10;
public void testOuter() {
}
class Inner{
public void show() {
System.out.println("外部类的成员变量age:" + Outer.this.age);
}
}
}
输出结果:
外部类的成员变量age:10
定义内部类自己的属性
public class Test{
public static void main(String[] args) {
//创建内部类对象
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
class Outer{
private int age = 10;
public void testOuter() {
}
class Inner{
int age = 20;
public void show() {
int age = 30;//定义局部变量
System.out.println("外部类的成员变量age:" + Outer.this.age);
System.out.println("内部类的成员变量age:" + this.age);//直接this
System.out.println("局部成员变量age:" + age);//局部变量
}
}
}
输出结果:
外部类的成员变量age:10
内部类的成员变量age:20
局部成员变量age:30
外部类不能直接访问非静态内部类成员,所以内部类可以提供一个良好的封装,内部类可以用外部类,但外部类不能反过来用内部类。
非静态内部类不能有静态方法、静态属性和静态初始化块,要加static的话得把它定义成静态内部类。
静态内部类
静态内部类定义方式
static class ClassName {
//类体
}
创建静态内部类对象
静态内部类看做外部类的一个静态成员,它不需要依托外部类创建好之后才创建内部类:
public class Test{
public static void main(String[] args) {
//创建静态内部类对象
Outer.Inner inner = new Outer.Inner();
}
}
class Outer{
static class Inner{
}
}
注意是new Outer.Inner(),不是new Outer().Inner()
匿名内部类
匿名内部类在工作中写GUI编程或则写安卓的时候会经常使用。
匿名内部类适合那种只需要使用一次的类,连名字都没有的内部类。
匿名内部类定义方式
new 父类构造器(实参类表)\实现接口 () {
//匿名内部类类体!
}
匿名内部类的使用
WindowAdapter是个抽象类,new完之后在方法里面直接写实现,这就定义了一个匿名内部类
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
this.addKeyListener(new KeyAdapter(){
@Override
public void keyPressed(KeyEvent e) {
myTank.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
myTank.keyReleased(e);
}
}
);
匿名内部类例子
public class Test{
public static void test01(A a) {
System.out.println("###########");
a.aa();
}
public static void main(String[] args) {
// Test.test01(new AA());//不能这样new一个接口
/**
* 可以有一个类去实现这个接口A,然后new这个类。
* 也可以通过匿名内部类来做。
* 直接定义一个没有名字的内部类,
* 这个内部类默认实现了接口A
*/
/**
* new AA()后面跟类体,增加没有实现的方法
*/
Test.test01(new A() {
@Override
public void aa() {
System.out.println("调用aa方法");
}
});
/**
* 因为只用于这个地方,只被使用一次,
* 所以也没有必要定义成一个有名字的类了,
* 所以把它定义成匿名内部类。
*/
}
}
interface A{
void aa();
}
输出结果:
###########
调用aa方法
局部内部类
这个用得很少。
在方法内部定义一个内部类。
public class Test2 {
public void show() {
//作用域仅限于该方法
class Inner {
public void fun() {
System.out.println("helloworld");
}
}
new Inner().fun();
}
public static void main(String[] args) {
new Test2().show();
}
}
可以在这个方法里面直接new,出了这个方法就不能用了,只服务于这个方法,在这个方法内部提供一个良好的封装。