内部类是在其他类中的类
匿名类是一种特殊的内部类,它没有类名
内部类
内部类的定义
将类的定义class xxxx{…}置入一个类的内部即可
编译器生成xxxx$xxxx这样的class文件
内部类不能与外部类同名
内部类的使用
在封装它的类的内部使用内部类,与普通类的使用方式相同
在其他地方使用,类名前要冠以外部类的名字。在用new创建内部类时,也要在new前面冠以对象变量:外部对象名.new内部类名(参数)
示例:TestInnerClass.java
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.字段及方法
示例:TestInnerThis.java
public class TestInnerThis
{
public static void main(String args[]){
A a = new A();
A.B b = a.new B();
b.mb(333);
}
}
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
}
}
}
结果:
333
222
111
内部类的修饰符
内部类与类中的字段、方法一样是外部类的成员,它前面也可以有访问控制符和其他修饰符
访问控制符:public protected 默认及private
注:外部类只能够用public修饰或者默认
final abstract
static修饰符
用static修饰内部类,表明该内部类实际是一种外部类,因为它与外部类实例无关。有人认为static是嵌套类,不是内部类。
static类在使用时:
1.实例化static类时,在new前面不需要用对象实例变量
2.static类中不能访问其外部类的非static的字段及方法,即只能访问static成员
3.static方法中不能访问非static的域及方法,也不能不带前缀地new一个非static内部类
示例:TetsInnerStatic.java
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 = 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
{
}
}
局部类
在一个方法中也可以定义类,这种类称为“方法中的内部类”或局部类
使用局部类
1.同局部变量一样,方法中的内部类
不能够用public、private、protected、static修饰,但可以用final或abstract修饰
2.可以访问其外部类的成员
3.不能够访问该方法的局部变量,除非是final局部变量
匿名类
匿名类是一种特殊的内部类。它没有类名,在定义类的同时就生成该对象的一个实例。一次性使用的类
class TestInnerAnonymous
{
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;
return new Object() {
public String toString() {
return ( " InnerSize: " + size +
" finalLocalVar: " + finalLocalVar
);
}
};
}
}
匿名类的使用
1.不取名字,直接用其父类或接口的名字
也就是说,该类是父类的子类,或者实现了一个接口
编译器生成xxxx$1之类的名字
2.类的定义同时就创建实例,即类的定义前面有一个new
new类名或接口名(){…}
不使用关键字class,也不使用extends及implements
3.在构造对象时使用父类的构造方法
不能够定义构造方法,因为它没有名字
如果new对象时,要带参数,则使用父类的构造方法
匿名类的应用
作为方法的参数
排序,给一个比较大小的接口
如:SortTest.java
import java.util.Arrays;
import java.util.Comparator;
class SortTest {
public static void main(String[] args){
Book[] books = new Book[10];
for (int i=0; i<books.length; i++ ){
books[i] = new Book((int)(Math.random()*100));
}
dump(books);
Arrays.<Book>sort( books, new Comparator<Book>(){
public int compare(Book b1, Book b2){
return b1.getPrice()-b2.getPrice();
}
});
dump(books);
}
static void dump( Book [] books ){
for (int i=0; i<books.length; i++ ){
System.out.print(books[i]+" ");
}
System.out.println();
}
}
class Book
{
private int price;
Book(int price){ this.price=price; }
int getPrice(){ return price;}
public String toString(){ return ""+price; }
}