您的位置:首页 > 编程语言 > Java开发

Java内部类

2016-03-04 13:50 501 查看


内部类(inner class)是定义在另一个类中的类。为什么需要使用内部类呢?其主要原因有以下三点:

内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。

内部类可以对同一个包中的其他类隐藏起来。

当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷。

内部类可以分为:

成员内部类

局部内部类

静态内部类

匿名内部类


1.成员内部类

成员内部类:就是在外部类的内部再定义一个类

public class OuterClass1 {
private int i = 10;
private int j = 20;
private static int count = 0;
public static void func1(){}
public static void func2(){}
//成员内部类中,不能定义静态成员
//成员内部类中,可以访问外部类中的所有成员
class InnerClass {
//内部类中不允许定义静态变量
//static int inner i = 100;
int j = 100;//内部类和外部类的实例变量可以共存
int k = 1;
void innerFunc1(){
System.out.println("内部类中k值为" + k);
//在内部类中访问内部类自己的变量直接用变量名
System.out.println("内部类中j值为" + j);
//在内部类中访问自己的变量名也可以用this.变量名
System.out.println("内部类中j值为" + this.j);
//在内部类中访问外部类与内部类重名的实例变量用“外部类名.this.变量名”
System.out.println("外部类中j值为" + OuterClass1.this.j);
//如果内部类中没有与外部类同名的变量,则可以直接用变量名访问外部类变量
System.out.println("外部类中count值为:" + count);
func1();
func2();
}
}
//外部类的非晶态方法访问成员内部类
public void func3(){
InnerClass inner = new InnerClass();
inner.innerFunc1();
}
public static void main(String[] args) {
//内部类的创建原则是,首先创建外部类对象,然后通过此类创建内部类对象
//静态的内部类则不需要外部类对象的引用
OuterClass1 out = new OuterClass1();
OuterClass1.InnerClass outin1 = out.new InnerClass();
outin1.innerFunc1();
//也可以将创建代码合并在一块
OuterClass1.InnerClass outin2 = new OuterClass1().new InnerClass();
outin2.innerFunc1();
}
}


2.局部内部类

局部内部类不能用public或private访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。

局部类有一个优势,即对外部世界可以完全地隐藏起来。即使所在外部类的其他代码也不能访问它

与其他内部类相比较,局部类还有一个优点。它们不仅能够访问包含他们的外部类,还可以访问局部变量。不过,那些局部变量必须被声明为final。

public class OutClass2 {
private int s = 10;
private int k = 0;
public void func1(){
final int s= 20;
final int j= 1;
//局部内部类
class InnerClass{
int s = 30;//可以定与外部类同名的变量
//static int m = 20;//不可以定义静态变量
void innerFunc(){
//如果内部类没有与外部类同名的变量,在内部类中可以直接访问外部类的实例变量
System.out.println("外围类成员" + k);
//可以访问外部类的局部变量(即方法内的变量),但是必须声明为final
System.out.println("常量:" + j);
//如果内部类中有与外部类同名的变量,直接访问的是内部类中的变量
System.out.println("常量:" + s);
//用this.变量名访问的也是内部类的变量
System.out.println("常量:" + this.s);
//用外部类名this.内部变量名访问的是外部变量
System.out.println("外部变量成员:" + OutClass2.this.s);
}
}
new InnerClass().innerFunc();
}
public static void main(String[] args) {
//访问局部内部类必须先定义外部类对象
OutClass2 out = new OutClass2();
out.func1();
}
}


3.静态内部类

/**
* 静态内部类
* 静态内部类可以用public、protected、private修饰,
* 不能从嵌套类的对象中访问非静态类的外围对象
* 静态内部类与普通内部类的区别:
* 1.静态内部类:内部类对象可以与外部类对象没有联系,在静态内部类中不能访问外部类的非静态成员
* 2.普通内部类:对象隐含的保存了一个引用,指向创建他的外围类对象。
* */
public class OutClass3{
public static int i = 1;
public int j = 10;
public static void func1(){

}
public void func2(){

}
//静态内部类可以用static、public、private修饰
//静态内部类中可以定义静态或非静态的成员
static class InnerClass{
static int inner_i = 100;
int inner_j = 200;
static void innerFunc1(){
//静态内部类只能访问外部类的静态成员(包括静态变量和静态方法)
System.out.println("outer.i" + i);
func1();
}
void innerFunc2(){
//静态内部类不能访问外部类的非静态成员(包括非静态变量和非静态方法)
//		System.out.println("outer.j" + j);
//func2();
}
}
public static void func3(){
//外部类访问内部类的非静态成员:实例化内部类即可
InnerClass inner =new  InnerClass();
inner.innerFunc1();
}
public static void main(String[] args) {
new OutClass3().func3();
//静态内部类的对象可以直接生成
OutClass3.InnerClass inner = new OutClass3.InnerClass();
inner.innerFunc2();
}
}

有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为static,以便取消产生的引用。

注释:声明在接口中的内部类自动成为static和public类。


4.匿名内部类

假如一个类只有在当前方法中使用一次,只创建这个类的一个对象,就不必命名了。这种类被称为匿名内部类(anonymous)。

public void start(int interval , final boolean beep){
ActionListener listener = new TimerPrinter()
{
public void actionPerformed(ActionEvent e){
Date date = new Date();
SimpleDateFormat f = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
System.out.println("现在时间:" + f.format(date));
if(beep)Toolkit.getDefaultToolkit().beep();
}
};
Timer t = new Timer(interval , listener);
t.start();
}
它的含义是:创建一个实现ActionListener接口的类的新对象,需要实现的方法actionPerformed定义在括号{}内。

通常的语法格式为:
new SuperType(Constructionparameters)
{

inner class methods and data
}
其中,SuperType可以使接口,于是内部类就要实现这个接口;也可以是一个类,于是内部类就要扩展它。
由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器。取而代之的是,将构造器参数传递给超类构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。不仅如此,还要提供一对花括号。

注释:下面的技巧称为“双括号初始化”(double
braceinitialization),这里利用了内部类语法。假设想构造一个数组列表,并将它传递到一个方法:

ArrayList<String> strs = new ArrayList<String>();
strs.add("STR1");
strs.add("STR2");
strs.add("STR3");

如果不再需要这个数组列表,最好让它作为一个匿名列表。

ArrayList<String> sts = new ArrayList<String>(){{add("a");add("b");}};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: