内部类分为四种:
1.成员内部类
2.局部内部类
3.静态内部类
4.匿名内部类
(一)实现方式:
1.成员内部类
//成员内部类......相当于非静态方法
class MemberInner {
private int a = 2;
public class Inner2 {
private int a =3 ;
public void doSomething(int a) {
// 调用外部类的属性
System.out.println(MemberInner.this.a);// 这块要注意......很重要!!!输出结果为:2
System.out.println(this.a);//输出结果为:3
// 调用局部属性
System.out.println(a);//输出结果为:5
}
}
}
public class Test3 {
public static void main(String[] args) {
MemberInner.Inner2 inner2 = new MemberInner().new Inner2();// 非静态内部类要new实例
inner2.doSomething(5);
}
}
2.静态内部类
//静态内部类......相当于静态方法
class StaticInner{
private static int a=3;
public static class Inner{
public void test(){
System.out.println(a);
}
}
}
public class Test2 {
public static void main(String[] args) {
StaticInner.Inner inner=new StaticInner.Inner();//静态内部类直接调用
inner.test();
}
}
3.局部内部类
//局部内部类......相当于局部变量
class LocalInner {
public void doSomething(int b) {
final int a = 3;// 只能访问final的变量
class Inner3 {
public void test(int b) {
System.out.println(b);//输出结果:4
System.out.println(a);//输出结果:3
}
}
new Inner3().test(b);
}
}
public class Test4 {
public static void main(String[] args) {
LocalInner inner = new LocalInner();
inner.doSomething(4);
}
}
4.匿名内部类
public class NiMing {
private int size=5;
public Object makeInner(int localVar){
final int finalLocalVar=localVar;
return new Object(){
//使用匿名内部类
public String toString()
{
return "OuterSize="+size+"\nfinalLocalVar="+finalLocalVar;
}
};
}
public static void main(String args[])
{
Object obj=new NiMing().makeInner(47);
System.out.println(obj.toString());
}
}
//输出结果为:
OuterSize=5
finalLocalVar=47
(二)四种内部类介绍:
什么时候需要使用内部类?
当描述事物时,事物的内部还有事物,在内部的事物就用内部类来描述,因为内部事物需要使用外部事物的内容。
内部类的访问规则:
1. 内部类可以直接访问外部类的成员,包括私有。之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this
2.外部类要访问内部类,必须建立内部类对象。
四种内部类介绍:
1.成员内部类:当内部类定义在外部类的成员位置上就称为成员内部类。
可以在外部其他类中,直接建立内部类的对象。
格式:外部类名.内部类名 变量名=外部类对象.内部类对象;如:Outer.Inner in=new Outer().new Inner();
2.静态内部类:当内部类在成员位置上,就可以被成员修饰符所修饰。比如private:将内部类在外部类中进行封装。static:内部类就具备了static的特性。当内部类被static修饰后,就成为了静态内部类。
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();(Inner 是静态的,可以直接通过外部类名Outer来访问;function也是静态的,可以直接通过其所在类的类名Inner访问。)
注意:
1)静态内部类只能访问外部类的静态成员。
2)如果在内部类中定义了静态成员,则该内部类必须也是静态的。
3)当外部类中的静态方法中需要访问内部类时,内部类必须也是static的。
总的来说就是那个比较常见的提示:“不能在静态上下文中引用非静态变量”。
3.局部内部类:因为内部类可以定义在外部类中任意的位置,当内部类被定义在局部时(比如在方法中)就称为局部内部类。
注意:
1)不可以被成员修饰符修饰。
2)可以直接访问外部类中的成员,因为还持有外部类的引用。
但不可以访问它所在的局部区域中的变量,除非该变量被final修饰。
4.匿名内部类:匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
实例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();
}
}
运行结果:eat something
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用
但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?
这个时候就引入了匿名内部类
实例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();
}
}
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了
这样便可以省略一个类的书写
并且,匿名内部类还能用于接口上
实例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();
}
}
运行结果:eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承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();
}
}
运行结果:1 2 3 4 5
实例5:Runnable接口的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + ” “);
}
}
};
Thread t = new Thread(r);
t.start();
}
}
运行结果:1 2 3 4 5