内部类就是在一个外部类的内部在定义一个类。
java中的内部类共分为四种:
成员内部类(member inner class)
局部内部类(local inner class)
静态内部类(static inner class/nested class)
匿名内部类(anonymous inner class)
为什么需要内部类?
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。
【1】成员内部类(作为外部类的一个成员存在,与外部类的属性方法并列)
/*
* 成员内部类
*
*/
public class Outer1 {
private static int i = 1 ;
private int j = 10 ;
private int k = 20 ;
public static void method1(){
System.out.println("-----数据1-----");
}
public void method2(){
System.out.println("-----数据2-----");
}
public class Inner{
public int j = 100;
public int o = 1;
//public static int num = 100;//编译错误,成员内部类不允许定义静态变量
void inner_method(){
System.out.println(o);
System.out.println(j);
System.out.println(this.j); //内部类访问内部类自己的变量可以直接调用也可以使用this,同时可以与外部类定义相同名称的变量
System.out.println(Outer1.this.j);//内部类中访问与内部类相同名称的外部类变量是“外部类类名.this.变量名”
System.out.println(k); //内部类直接可以访问与外部类不同名的变量
method1(); //可以直接访问外部类静态方法
method2();
}
}
//外部类非静态方法访问成员内部类
public void method3(){
Inner inner = new Inner();
inner.inner_method();
}
//外部类静态方法访问成员内部类
public static void method4(){
Outer1 outer = new Outer1();
Inner inner = outer.new Inner();
inner.inner_method();
}
public static void main(String[] args) {
//method4();
//要想通过Inner的对象调用方法如下
Outer1 outer = new Outer1();
Inner inner = outer.new Inner();
inner.inner_method();
/*Inner inner = new Inner();
inner.inner_method()*/ //内部内为静态方法
}
}
【2】局部内部类
在方法中定义的内部类称为局部内部类。与局部变量类似,局部内部类不能有访问说明符,因为它不是外围类的一部分,但是它可以访问当前代码块内的常量,和此外围类所有的成员
/**
*
*局部内部类
*/
public class Outer2 {
private int s = 100 ;
private int out_i = 1;
public void method(final int k){
final int s = 200;
int i = 1 ;
final int j = 10 ;
class Inner{ //局部内部类不能有修饰符
int s = 300 ;
//static int m = 20; //不可以定义静态变量
Inner(int k){
inner_f(k);
}
int inner_i =100;
void inner_f(int k){
System.out.println(out_i);
System.out.println(j);//可以访问外部类的局部变量,但必须是finnal修饰
System.out.println(this.s);//访问的是内部类的变量
System.out.println(Outer2.this.s);//访问的是外部类的变量
}
}
new Inner(k);
}
public static void main(String[] args) {>
//访问局部内部类必须现有外部对象
Outer2 out = new Outer2();
out.method(3);
}
}
【3】静态内部类
/ *
*静态内部类(嵌套类)
*/
public class Out3 {
public static int i = 1;
private int j = 10 ;
public static void out_f1(){
System.out.println("外部静态方法");
}
public void out_f2(){
System.out.println("外部非静态方法");
}
static class Inner{
//静态内部类可以使用public、private、protected修饰
//静态内部类可以定义静态和非静态变量
static int inner_i = 100;
int inner_j = 200;
static void inner_f1(){
System.out.println("测试方法"+i);
out_f1();//静态内部类只能访问外部类的静态变量和方法
}
void inner_f2(){
System.out.println("测试方法");
}
}
public void out_f3(){
System.out.println(Inner.inner_i);//外部类访问内部类静态变量通过“内部类名.变量名”
Inner.inner_f1();<
//外部类访问内部类非静态变量:实例化内部类
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Out3().out_f3();
}
}
【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