1.作用:
1)内部类提供了更好的封装,不允许同一个包中的其他类访问该类。
2)内部类可直接访问外部类的私有数据,因为内部类被当成其外部类的成员。但外部类不能访问内部类的实现细节。
3)匿名内部类适合用于创建那些仅需要一次使用的类。
2.内部类的分类
1)成员内部类:静态内部类(static修饰,但不能修饰外部类)和非静态内部类。
内部类的属性和方法可以与外部类中的相同,访问时可通过this、外部类类名.this作为限定来区分。
外部类访问非静态内部类成员则必须显示创建非静态内部类对象来调用访问其成员。非静态内部类里不允许定义静态成员。
外部类可以使用静态内部类的类名来访问静态内部类的类成员。或者静态内部类的对象来访问。如下例:
public class A
{
static class B
{
private static int a=5;
private ing b=6;
}
public void fun()
{
System.out.println(B.a);
System.out.println(new B().b);
}
}
在外部类以外的地方访问该类的非静态内部类对象,则可使用new 外部类().new 内部类名()或者外部类对象.new 内部类名()的方式定义内部类对象。
如下:
class Cow
{
public double weight;
public Cow(double weight)
{
this.weight=weight;
}
class CowLeg
{
private double length;
public CowLeg(double length)
{
this.length=length;
}
public void info()
{
System.out.println("zhang");
}
}
}
public class TestCow
{
public static void main(String[] args)
{
Cow.CowLeg ccg= new Cow(11).new CowLeg(123);//fangfa1
ccg.info();
Cow.CowLeg ccg1;//fangfa2
Cow c=new Cow(1);
ccg1=c.new CowLeg(111);
ccg1.info();
}
}
使用静态内部类对象时可用new 外部类名.内部类名()的方式。并且静态内部类只能访问外部类中的静态属性或方法。
如下:
class StaticOut
{
static class StaticIn
{}
}
public class interStaticInnerClass
{
public static void main(String[] args)
{
StaticOut.StaticIn ssin=new StaticOut.StaticIn();//或者分开如下
StaticOut.StaticIn ssin1;
ssin1=new StaticOut.StaticIn();
}
}
注:外部类的子类不可重写外部类中的内部类。因为内部类所处的空间不同。
外部类可通过new 内部类名()访问内部类的private成员。如下
public class Outer
{
private int outProp = 9;
class Inner
{
private int inProp = 5;
public void acessOuterProp()
{
System.out.println("outProp:" + outProp);
}
}
public void accessInnerProp()
{
System.out.println("inProp:" + new Inner().inProp);//通过new内部类对象访问内部类私有成员
}
public static void main(String[] args)
{
Outer out = new Outer();
out.accessInnerProp();
}
}
2)局部内部类
定义:把内部类定义在方法里,则该局部类只在该方法里有效。且不能在外部类的以外的地方使用。也不需访问控制符和static修饰。
3)匿名内部类
适合创建那种只需要一次使用的类,创建匿名内部类时会立即创建一个该类的实例,这个类定义立即消失,且匿名内部类不能重复使用。定义如下:
interface A
{
public double fun1();
public String fun2();
}
public class B
{
public void test(A a)
{
System.out.println(a.fun2());
}
public static void main(String[] args)
{
B b=new B();
b.test(new A()
{
public double getP()
{
return 123.5;
}
});
}
}
匿名类访问外部类的属性时,必须使用final修饰外部类的属性。3.回调
定义:允许客户类通过内部类引用来调用其外部类的方法。当某一子类同时继承一父类和接口,但父类和接口中含有同名的方法,可以在该类中定义一个内部类实现接口的功能,并在该类中定义一个返回内部类对象的方法来调用内部类里的方法。具体如下:
interface Teachable
{
void work();
}
public class Programmer
{
private String name;
public Programmer(){};
public Programmer(String name)
{
this.name=name;
}
public void work()
{
System.out.println(name);
}
}
//定义子类
public class TeachableProm extends Programmer
{
public TeachableProm(){};
public TeachableProm(String name)
{
super(name);
}
private void teach()
{
System.out.println("....在演讲");
private class Closure implements Teachable
{
public void work()
{
teach();
}
}
public Teachable getrecall()
{
return new Closure();
}
}
}
使用时:
public class test
{
public static void main(String[] args)
{
TeachableProm tp=new TeachableProm("123");
tp.work();//直接调用父类的方法
tp.getrecall().work();//表面上调用Closure的work()方法,实际上回调TeachableProm中的teach()方法。
}
}