/**
* 内部类与匿名类
* @author cnRicky
* @date 2018.11.10
*/
内部类与匿名类
- 内部类(inner class)是在其他类中的类
- 匿名类(anonymous class)是一种特殊的内部类,它没有类名
内部类(Inner class)
-
内部类的定义
- 将类的定义class xxxx{...}置入一个类的内部即可
- 编译器生成xxxx$xxxx这样的class文件
- 内部类不能够与外部类同名
-
内部类的使用
- 在封装它的内的内部使用内部类,与普通的使用方式相同
- 在其他地方使用
- 类名前要冠以外部类的名字
- 在用new创建内部类时,也要在new前面冠以对象变量
- 外部对象名.new 内部类名(参数)
class TestInnerClass{
public static void main( String[] args ){
Parcel p = new Parcel();
p.testShip();
Parcel.Contents c = p.new Contents(33);
Parcel.Destination d = p.new Destination( "Hawii" );
p.setProperty( c, d );
p.ship();
}
}
class Parcel {
private Contents c;
private Destination d;
class Contents {
private int i;
Contents( int i ){ this.i = i; }
int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {label = whereTo;}
String readLabel() { return label; }
}
void setProperty( Contents c, Destination d ){
this.c =c; this.d = d;
}
void ship(){
System.out.println( "move "+ c.value() +" to "+ d.readLabel() );
}
public void testShip() {
c = new Contents(22);
d = new Destination("Beijing");
ship();
}
}
在内部类中使用外部类的成员
-
内部类中可以直接访问外部类的字段及方法
- 即使private也可以
-
如果内部类中有与外部类同名的字段或方法,则可以用
- 外部类名.this.字段及方法
-
例子:
class A
{
private int s = 111;
public class B{
private int s = 222;
public void mb(int s){
System.out.println(s);//局部变量s
System.out.println(this.s);//内部类对象的属性s
System.out.println(A.this.s);//外层类对象属性s
}
}
}
内部类的修饰符
- 内部类与类中的字段、方法一样是外部类的成员,它的前面也可以有访问控制符和其他修饰符
- 访问控制符:public、protected,默认(default)及private
- 注:外部类只能够使用public修饰或者默认
- final,abstract
- 访问控制符:public、protected,默认(default)及private
static修饰符
-
用static修饰内部类,表名该内部类实际是一种外部类
- 因为它与外部类的实例无关
- 有人认为static的类是嵌套类(nested class),不是内部类(inner class)
-
static类在使用时:
- 1、实例化static类时,在new前面不需要用对象实例变量;
- 2、static类中不能访问其外部类的非static的字段及方法,即只能够访问static成员
- 3、static方法中不能访问非static的域及方法,也不能够不带前缀地new一个非static的内部类
-
例子:
public class TestInnerStatic
{
public static void main(String[] args)
{
A.B a_b = new A().new B();//ok
A a = new A();
A.B ab = a.new B();
Outer.Inner oi = new Outer.Inner();
//Outer.Inner oi2 = new Outer.new Inner();//!!!error
//Outer.Inner oi3 = new Outer().new Inner();//!!!error
}
}
class A
{
private int x;
void m(){
new B();
}
static void sm(){
//new B();//error!!!
}
class B
{
B(){ x = 5; }
}
}
class Outer
{
static class Inner
{
}
}
局部类
- 在一个方法中也可以定义类,这种类称为“方法中的内部类”
- 或者叫局部类(local class)
- 例子:
class TestInnerInMethod
{
public static void main(String[] args)
{
Object obj = new Outer().makeTheInner(47);
System.out.println("Hello World!" + obj.toString());
}
}
class Outer
{
private int size = 5;
public Object makeTheInner(int localVar)
{
final int finalLocalVar = 99;
class Inner{
public String toString(){
return("InnerSize:" + size +
// "localVar:" + localVar + //Error!
"finalLocalVar:" + finalLocalVar
);
}
}
return new Inner();
}
}
使用局部类
-
1、同局部变量一样,方法中的内部类
- 不能够用public,private,protected,static修饰
- 但可以被final或者abstract修饰
-
2、可以访问其外部类的成员
-
3、不能够访问该方法的局部变量,除非是final局部变量
匿名类
-
匿名类(anonymous class)是一种特殊的内部类
- 它没有类名,在定义类的同时就生成该对象的一个实例
- “一次性使用”的类
-
例子:
class TestInnerAnonymous
{
public static void main(String[] args)
{
}
}
class Outer
{
private int size = 5;
public Object makeTheInner(int localVar)
{
final int finalLocalVar = 99;
return new Object(){
public String toString(){
return ("InnerSize:" + size + "finalLocalVar:" + finalLocalVar);
}
};
}
}
匿名类的使用
-
1、不取名字,直接用其父类或接口的名字
- 也就是说,该类是父类的子类,或者实现了一个接口
- 编译器生成xxxxx$之类的名字
-
2、类的定义的同时就创建实例,即类的定义前面有一个new
- new 类名或接口名(){ ...... }
- 不使用关键字class,也不使用extends及implements
-
3、在构造对象时使用父类构造方法
- 不能够定义匿名类的构造方法,因为它没有名字
- 如果new对象时,要带参数,则使用父类的构造方法
匿名类的应用
- 用到界面的事件处理
- 注册一个事件监听器
- 示例AutoScore.java中
//SymAction ISymAction = new SymAction();
//btnNew.addActionListener(ISymAction);
btnNew.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event)
{
......;
}
});
- 作为方法的参数
- 排序,给一个比较大小的接口
- 如:
Arrays.<Book>sort(books, new Comparator<Book>(){
public int compare(Book b1, Book b1){
return b1.getPrice()-b2.getPrice();
}
});