创建内部类
内部类的创建:把内部类的定义放置在外部类的定义之中,在非静态方法中创建内部类时,内部类的使用就和组合类一样。但是在非静态方法之外的部分创建内部类,必须要对内部类的对象变量声明为:OuterClassName.InnerClassName
public class TestJava {
class inner{
public void print() {
System.out.println("inner");
};
}
public inner test() {
return new inner();//返回内部类的引用
}
public static void main(String[] args) {
TestJava t = new TestJava();
TestJava.inner i = t.test();//OuterClassName.InnerClassName
i.print();
}
}
链接到外部类
在外部类对象创建一个内部类对象时,内部类对象会捕捉到外部类对象的引用,从而使得内部类能通过这个引用来使用外部类中的任意成员(域和方法),从而使得内部类与创造它的外部类之间有一种联系(1.内部类对象有外部类对象的引用 2.内部类的创建依赖于外部类(比如外部类中有方法返回内部类,如上述))。内部类只有在与其外部类对象相关联的情况下才能被创建(即内部类不为static)。
内部类对象为何能直接访问外部类成员?
1 编译器自动为内部类添加一个成员变量, 这个成员变量的类型和外部类的类型相同, 这个成员变量就是指向外部类对象的引用;
2 编译器自动为内部类的构造方法添加一个参数, 参数的类型是外部类的类型, 在构造方法内部使用这个参数为1中添加的成员变量赋值;
3 在调用内部类的构造函数初始化内部类对象时, 会默认传入外部类的引用。
使用.this/.new
1.如果要生成外部类的引用,可以使用OuterClassName.this
public class TestJava {
class inner{
public TestJava r() {
return TestJava.this;//返回外部类的引用
}
}
public void print() {
System.out.println("OuterClass");
}
public inner test() {
return new inner();//返回内部类的引用
}
public static void main(String[] args) {
TestJava t = new TestJava();
TestJava.inner i = t.test();//OuterClassName.InnerClassName
i.r().print();//return TestJava的引用,再调用外部类的print()方法
}
}
2.如果想直接创建内部类的对象(而不是通过调用外部类的函数),则需要使用外部类的对象来创建内部类的对象,用外部类对象的引用调用.new语法,内部类对象的创建一定要基于外部类之上
public class TestJava {
class inner{
public inner() {
System.out.println("Inner");
}
}
public static void main(String[] args) {
TestJava t = new TestJava();
TestJava.inner i = t.new inner();//告知外部类对象创建内部类对象,则需要提供外部类的引用来调用.new
}
}
内部类可以直接访问外部类的成员:
public class TestJava {
private String s;
class inner{
public void str() {
s = "123";//外部类的成员可以直接访问,甚至是Private
print();
System.out.println(s);
}
}
private void print() {
System.out.println("outer");
}
public static void main(String[] args) {
TestJava t = new TestJava();
t.new inner().str();
}
}
而外部类需要建立内部类的实例后才能访问内部类的成员:
public class TestJava {
class inner{
private String s;
private void print() {
this.s = "Hello"+s;
System.out.println(s);
}
}
public void outer() {
inner i = new inner();
i.s = " World!";//需要构建内部类实例
i.print();
}
public static void main(String[] args) {
TestJava t = new TestJava();
t.outer();
}
}
内部类与向上转型
用内部类实现了某接口,可以方便的向上转型,从而很好的隐藏实现细节。
在方法和作用域内的内部类
局部内部类:在一个方法中插入内部类
interface itf{
void print();
void out();
}
public class Test{
public itf inner(){
class in implements itf{
public void print(){
System.out.print("Inner");
}
public void out(){
System.out.print("out");
}
}
return new in();
}
public static void main(String[] args){
Test t = new Test;
t.inner().print();
}
这个内部类的作用域就是在此方法内,外部无法看见。这种方式可以方便的实现itf接口,从而让Test类通过只调用函数自身的函数来得到不同实现的接口。
匿名内部类
匿名内部类,没有名字,所以它没有构造器(因为构造器要求和类同名),可以实现一个接口或者扩展于一个类:
1.实现于接口时,一定不能传递参数给它,因为接口没有构造器。
格式:
new InterfaceType(){
methods and data;
}
public class TestJava {
ActionListener listener = new ActionListener() {
public void actionPerform() {
System.out.println("1");
}
};
}
2.扩展于某类时,如果其基类的构造函数需要传递参数,则需要将参数加入new Class(…)中,如果此参数只用于基类的构造器,则不用设定为final,如果内部类中需要使用此参数,则需要设定为final
new SuperType(constructor parameters)
{
methods and data;
}
class Sup{
private int i;
public Sup(int x) {this.i = x;}
public int value() {return i;}
}
public class TestJava {
public Sup test(int x) {
return new Sup(x) {//自动调用基类的构造器
public int value() {
return super.value() * 47;
}
};
}
public static void main(String[] args) {
TestJava t = new TestJava();
System.out.println(t.test(5).value());
}
}