一.创建内部类
(1)内部类了解外围类,并能与之通信
(2)创建内部类方式:把类的定义置于外围类的里面
public class Parcel1 {
//内部类1
class Contents{
private int i = 11 ;
public int value(){
return i ;
}
}
//内部类2
class Destination{
private String label ;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){
return label ;
}
}
public void ship(String dest){
//创建内部类
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tasmaia");
}
}
二.链接到外部类
1.当生成一个内部类的对象时,此对象与制造它的外围对象之间就有了一种联系,所以能访问其外围对象的所有成员,而不需要任何条件。内部类还拥有其外围类所有元素的访问权。
2.内部类自动拥有对其外围所有成员的访问权。
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 ;
public boolean end() {
//调用外部类的方法 items为private
return i == items.length;
}
public Object current() {
return items[i];
}
public void next() {
if(i < items.length)
i ++ ;
}
}
public Selector selector(){
//生成内部类对象
return new SequenceSelector();
}
public static void main(String[] args) {
//...
}
}
三.使用.this与.new
public class MainJava {
void f(){
System.out.println("DotThis.f()");
}
public class Inner{
public MainJava outer(){
//内部类生成对外部类对象的引用
return MainJava.this; //MainJava 为外部类
}
}
public Inner inner(){
return new Inner();
}
public static void main(String[] args) {
MainJava dt = new MainJava();
MainJava.Inner dti = dt.inner();
dti.outer().f();
}
}
//创建内部类对象
public class DotNew{
public class Inner{};
public static void main(String[] args){
DotNew dn = new DotNew(); //生成外部类对象
DotNew.Inner dni = dn.new Inner(); //生成内部类对象
}
}
要想直接创建内部类的对象,你不能按照你想象的方式,去引用外部类的名字DotNew,而是必须使用外部类的对象来创建改内部类对象。
拥有外部类对象之前是不可能创建内部类对象的。
4.内部类与向上转型
(1)当将内部类向上转型为基类,尤其是转型为一个接口的时候,内部类就有了用武之地。
5.在方法和作用域内的内部类
可以在一个方法里面或者在任意的作用域内定义内部类。
6.匿名内部类
(1)不使用匿名内部类
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
(2)使用匿名内部类
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
(3)在接口上使用匿名内部类
interface Person {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
(4)Thread类的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
(5).匿名内部类只能使用一次,它通常用来简化代码编写
(6).但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
9.为什么需要内部类
(1)使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
(2)内部类使得多重继承的解决方案变得完整
//即必须在一个类中以某种方式实现两个接口。由于接口的灵活性,可以使用单一类或内部类
interface A{}
interface B{}
class X implements A,B{}
class Y implements A {
B makeB(){
return new B(){};
}
}
public class MultiInterfaces{
static void takesA(A a){}
static void takesB(B b){}
public static void main(String[] args){
X x = new X();
Y y = new Y();
takesA(x);
takesA(y);
takesB(x);
}
}
//如果拥有的是抽象的类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承
class D {}
abstract class E {
abstract void A();
}
class Z extends D {
E makeE(){
//匿名内部类
return new E() {
void A() {
}};
};
}
}
public class MultiImplementation{
static void takesD(D d){}
static void takesE(E e){}
public static void main(String[] args){
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
}