java内部类定义:在一个类的内部定义另一个类
实现原理:当我们在一个类outter(这里称作外部类)中定义另外一个类inner(这里称作内部类)时,这个内部类实际上捕获了一个指向外部类成员的引用,换句话讲,内部类中的方法成员可以自由访问外部类中的属性成员,但是注意,只能访问其中的构造器方法,而不能访问其余方法。
下面将以具体的代码讲述其中的知识点,在每条语句的后面都会附上这么写的原因或者实现机制
下面还有匿名内部类的用法,将在后来更新
实现原理:当我们在一个类outter(这里称作外部类)中定义另外一个类inner(这里称作内部类)时,这个内部类实际上捕获了一个指向外部类成员的引用,换句话讲,内部类中的方法成员可以自由访问外部类中的属性成员,但是注意,只能访问其中的构造器方法,而不能访问其余方法。
下面将以具体的代码讲述其中的知识点,在每条语句的后面都会附上这么写的原因或者实现机制
第一部分:普通内部类
实例一:使用外部类名.内部类名的格式声明一个内部类
public class Demo1 {
/**
* 这里定义一个内部类,这个内部类可以访问包含他的外部类的所有的变量和方法
* 但是外部类却不能访问内部类中被定义为private的成员
*/
class Contents{ //这里定义第一个内部类
private int i=11;
public int value(){
return i;
}
}
/**
*
* 如果你不特意指定内部类的成员的访问权限,那么他默认为public的,换句话讲,只要可以找到一个外部类的引用
* 他就可以被同一个包中的所有成员访问
*/
class Destination{ //这里定义第二个内部类
private String label;
Destination(String whereTo){
label=whereTo;
}
String readLabel(){
return label;
}
}
public void ship(String dest){
/*Contents 是一个内部类,但是这里可以直接使用Contents进行声明,是因为内部类同这个
* 方法是同级的,换句话讲,因为内部类在这个方法之前编译,所以当我们的虚拟机在编译这个方法之时,可以“知道”这个类是什么,从而
*成功编译。
*/
Contents c=new Contents();
Destination d=new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String args[]){
/**
* 当我们新建一个指向外部类的引用时,其中包含的成员(包括内部类)就已经被编译了
*/
Demo1 demo1=new Demo1();
demo1.ship("hello world");
/**
*这个方法是static的。所以编译器先编译它,但这时,编译器还没有编译内部类,所以需要手动地“告诉”编译器这是一个内部类,
*故采用outterclassname.innerclassname的形式进行声明,等号右边要新建一个内部类,此时需要一个外部类的引用
*/
Demo1.Contents t=demo1.new Contents();
}
}
实例二:使用接口名声明一个内部类
//这里声明一个接口
public interface Selector {
boolean end();
Object current();
void next();
}
//当我们的内部类继承自外部的一些接口时,在static方法中声明这些内部类时,可以直接使用使用"接口名"的形式
//而不需要使用“外部类名.内部类名”的形式
public class Sequence {
private Object[] items;
private int next=0;
public Sequence(int size){
items=new Object[size];
}
public void add(Object x){
if(next<items.length){
items[next++]=x;
}
}
private class SequenceSelector implements Selector{
private int i=0;
/**如果没有到达数组的末尾,就返回true,如果没有到达数组的末尾,就返回false
* @Override
*/
public boolean end() {
// TODO Auto-generated method stub
return i==items.length;
}
@Override
public Object current() {
// TODO Auto-generated method stub
return items[i];
}
@Override
public void next() {
// TODO Auto-generated method stub
if(i<items.length){
i++;
}
}
}
public Selector selector(){
return new SequenceSelector();
}
public static void main(String args[]){
Sequence sequence=new Sequence(10);
for(int i=0;i<10;i++){
sequence.add(Integer.toString(i));
}
/**
* 这里的Selector既是一个内部类,又是一个接口,所以当编译器编译到这条语句时,已经“知道”Selector接口是什么了。
*换句话讲,可以直接用接口名进行声明,而不用
* outername.innername的形式
*/
Selector selector=sequence.selector();
}
}
下面还有匿名内部类的用法,将在后来更新