Java内部类及使用方法

  • 内部类定义
  • 内部类和外部类的中的成员变量相互访问
  • 匿名内部类
  • 静态内部类
  • 方法内部类


内部类定义

把一个类定义在另外一个类的内部称为内部类
可以把内部类看为外部类的一个引用类型的成员变量
而引用类型的成员变量在使用时必须先用new分配空间
所以内部类只是在外部类下的一个声明和定义,而未分配空间
无论在外部类的内部使用内部类还是外部类之外使用内部类都必须先new
内部类可以方便的访问外部类的私有属性

class Outer
{
	private String info = "Hello World" //声明私有属性
	class Inner //内部类声明类
	{
		private int age;
		public void print() //打印输出方法
		{
			System.out.println(info);//可见内部类可以方便的访问外部类的私有属性
		}
	}
	public void func(){ //定义方法
		//在任何情况下,访问内部类的成员或方法时,必须先new!!!
		//在包含内部类的类下调用内部类的方法不需要先new Outer
		Inner inner = new Inner();
		System.out.println(inner.age);
		inner.print(); //通过内部类调用方法
	}
}
//----------另外一个类文件--------------
public class TestOuterAndInner //测试类
{
	public static void main(String [] args)
	{
		//不在Outer内,需要先new Outer再new Inner,才可以调用Inner下的方法
		new Outer().new Inner().print();
	}
}

在Outer内部可以不用new Outer再new Inner
而在Outer外部必须先new Outer再new Inner
才可以访问Inner的成员变量及函数

内部类和外部类的中的成员变量相互访问

内部类可以直接用变量名轻易访问到外部类的成员变量
如果在内部类中有与外部类同名的成员变量
则内部类访问外部类的成员变量时
需要使用 外部类类名.this.外部类属性名 的方式进行访问
而内部类中不允许有静态属性

public class Outer
{
	String name = "zhangsan";
	public class Inner
	{
		private String name = "lisi";
		static int age = 10; //错误,内部类中不允许定义静态属性
		public void print(){
			System.out.println("Outer name "+Outer.this.name);
			System.out.println("Inner name "+name);//这里其实用this.name效果相同,this指Inner对象
		}
	}
	public static void main(String [] args)
	{
		Outer o = new Outer();
		o.new Inner().print();//调用内部类的print()结果为分别打印zhangsan和lisi
		Outer o2 = new Outer();
		//name为private属性,在非Outer类下将变成无法访问
		//这里为Outer类下的main范围下,因此可以访问到Inner的name
		System.out.println(o2.new Inner().name);//打印lisi
	}
}

匿名内部类

适合只需要使用一次的类,安卓中使用比较多

public class NoNameInnerClassDemo{
	public static void main(String[] args)
	{
		new Thread(new Runnable(){
			public void run(){
				@Override
				System.out.println("run")
			}
		});
	}
}

上面代码中Thread构造函数中需要传入一个实现了Runnable接口的类
而上面的写法可以看为声明了一个无名类,这个无名类implement了Runnable接口后实现了Runnable接口的方法后,用new实例化了这个无名类并作为Thead方法的参数传入
这种写法也适合于无名类作为抽象类的子类进行继承的方式
匿名内部类的写法多是为了代码简洁

静态内部类

class Outerr{//外部类
	private static String info = “HelloWorld”;
	static class Inner{//静态内部类
		public void print()
		{
			System.out.println(info);
		}
	}

	public static void main(Sting [] args){
		//此处不用再new Outer()
		//直接Outer.Inner即可
		Inner inner = new Outer.Inner();
		
	}
}

使用static声明的内部类不能访问非static的外部属性
声明static内部类后这个内部类的归属变为整个Outer类
注意Inner的访问权限为default,因为main方法在Outer中,且main和Inner皆为static所以可以直接以Inner inner的方式声明对象
而在Outer相同包下的其他类则需要以Outer.Inner innerde方式声明对象,再用new进行实例化
在不同的包下Inner将变得无法访问(因为权限为default)

方法内部类

public class MethodInnerClassDemo{
	public void show(int num)//不同jdk可能需要加上final关键字
	{
		System.out.println("show")
		class InnerClass{
			private String name;
			public void test(int a){
				System.out.println("test");
				System.out.println(a);
				System.out.println(num);
			}
			new InnerClass().test(11);
		}
	}

	public static void main(String []args){
		new MethodInnerClassDemo().show(12);//打印show后打印test 11 12
	}
}

这种写法的类只能在声明的方法内有效,了解即可

最后补充一点知识:关于成员内部类的继承问题。一般来说,内部类是很少用来作为继承用的。但是当用来继承的话,要注意两点:

1)成员内部类的引用方式必须为 Outter.Inner.

2)构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。这段代码摘自《Java编程思想》

class WithInner {
    class Inner{
         
    }
}
class InheritInner extends WithInner.Inner {
      
    // InheritInner() 是不能通过编译的,一定要加上形参
    InheritInner(WithInner wi) {
        wi.super(); //必须有这句调用
    }
  
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner obj = new InheritInner(wi);
    }
}