内部类的分类
成员内部类
静态内部类
局部内部类
匿名内部类
如图,在A类中声明了另一个B类,B类就是一个内部类。
class A{
class B{
}
}
成员内部类
内部类访问外部类属性和方法
class A{
private String name = "A的名字";
private static int age = 1;
public void a(){
System.out.println("外部类方法");
}
class B{
private String nameb = "B的名字";
private int ageb = 2;
public void b(){
System.out.println("内部类的name:"+this.nameb);
System.out.println("外部类的name:"+A.this.name);
System.out.println("外部类的静态属性:"+A.this.age);
A.this.a();
}
}
}
public class Test2 {
public static void main(String[] args) {
A a = new A(); //新建A类对象
A.B b = a.new B(); //新建内部类对象
b.b();
}
}
运行结果:
内部类的name:B的名字
外部类的name:A的名字
外部类的静态属性:1
外部类方法
外部类访问内部类属性和方法。
第一种:在外部类中创建内部类对象。
class A{
private String name = "A的名字";
private static int age = 1;
public void method(){
B b = new B();
System.out.println(b.ageb);
b.b();
}
public class B{
private String nameb = "B的名字";
private int ageb = 2;
public void b(){
System.out.println("内部类方法");
}
}
}
public class Test2 {
public static void main(String[] args) {
A a = new A(); //新建A类对象
a.method();
}
}
运行结果:
2
内部类方法
第二种:在其他类中调用。
class A{
private String name = "A的名字";
private static int age = 1;
// public void method(){
// B b = new B();
// System.out.println(b.ageb);
// b.b();
// }
public class B{
// private String nameb = "B的名字";
// private int ageb = 2;
public void b(){
System.out.println("内部类方法");
}
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
A.B b = a.new B();
b.b();
}
}
只有内部类不是private修饰的时候,才可以在其他类访问。
在其他类中,使用这个非private修饰的成员内部类的时候,需要注意以下几点: 1. 这个内部类需要import导入,并且是 外部类.内部类 的形式导入。 2. 在创建对象的时候,需要先创建出外部类对象,然后使用外部类对象再创建内部类对象。 形式为: 外部类对象.new 内部类对象();
静态内部类
静态内部类访问外部类的属性和方法
四种内部类中,只有静态内部类中可以创建静态方法和属性。(只有这样才能在初始化时,让静态内部类和其内部的静态内容初始化的时候同步。)
class A{
private String name = "A的名字";
private static int age = 1;
public static void a1(){
}
public void a2(){
}
public static class B{
private String nameb = "B的名字";
private static int ageb = 2;
public void b1(){
System.out.println("内部类非静态方法");
A.age = 2;
A.a1();
// A.a2();
}
}
}
静态内部类中只能调用外部类的静态方法,和静态属性。
外部类访问静态内部类的属性和方法
class A{
public void a2(){
}
public void test(){
B.ageb = 3; //外部类访问内部类静态属性
B.b1(); //外部类访问内部类静态方法
}
public static class B{
private String nameb = "B的名字";
private static int ageb = 2;
public static void b1(){
}
public void b2(){
}
}
}
其他类访问静态内部类的属性和方法
class A{
public void a2(){
}
public void test(){
B.ageb = 3; //外部类访问内部类静态属性
B.b1(); //外部类访问内部类静态方法
}
public static class B{
private String nameb = "B的名字";
private static int ageb = 2;
public static void b1(){
}
public void b2(){
}
}
}
public class Test {
public static void main(String[] args) {
A.B b = new A.B(); //创建静态内部类对象的方式
// A a = new A();
// A.B b1 = a.new B(); 这种对于成员内部类创建对象的方式会报错
b.b2(); //调用静态内部类中的非静态方法,用对象调用
A.B.b1(); //调用静态内部类中的静态方法,用 外部类.内部类.静态方法名 的方式
}
}
关于静态内部类与成员内部类的总结:
类的初始化发生在两种情况下,一个是new对象的时候,一个是反射机制。
类的初始化会先初始化静态成员(静态属性,静态方法,静态内部类),而非静态成员的初始化发生在创建对象的时候。所以,如果一个静态内部类中有一个外部类的非静态方法,而此时,外部类的对象还没有创建,就会发生错误。
因此,外部类和内部类的所有被static修饰的静态成员,都可以直接访问。而无论外部类还是内部类,静态方法中都不能直接访问彼此的非静态方法。
局部内部类
局部内部类就是在方法中定义一个类,它的作用范围也是只在此方法中。也只能在此方法中创建对象。很少用。
public class Test {
public static void main(String[] args) {
A();
}
public static void A(){
int num = 1;
class B{
private String name = "fga";
public B(){
}
}
B b = new B(); //在方法中创建对象
System.out.println(b.name);
}
}
局部内部类访问外部类成员
public class Test {
public static void main(String[] args) {
A a = new A();
a.a3();
}
}
class A{
private String name = "我是A";
static int age = 2;
public static void a1(){
System.out.println("我是外部类的静态方法a1");
}
public void a2(){
System.out.println("我是外部类的非静态方法a2");
}
public void a3(){
String name = "我是局部内部类所在的方法a3";
class B{
public void b1(){
System.out.println("调用外部类的非静态属性:"+A.this.name);
System.out.println("调用外部类的静态属性:"+A.age);
System.out.println("调用所在方法的属性:"+name);
A.this.a2(); //调用外部非静态方法
A.a1(); //调用外部静态方法
}
}
B b = new B(); //局部内部类所在的方法中创建对象,调用方法
b.b1();
}
}
局部内部类所在方法的变量,默认都是final修饰,无法再次赋值。
匿名内部类
匿名内部类是内部类的一种简单写法。
如果要使用一个接口的方法,一般步骤是:
1 创建一个类,用来实现这个接口。
2 在类中重写这个方法。
3 在其他类中创建这个类的对象。
4 调用这个对象的重写后的方法。
以上步骤略冗长,为了更加简化代码,也迎合Java的面向对象思想(着重做什么,而不是怎样做),引入了匿名内部类。
如下,
实现接口
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() { //Runnable是一个接口,其中只有一个run()方法
public void run() {
System.out.println("执行重写后的方法"); //重写run()方法
}
};
r.run(); //调用
}
}
实现抽象类
public abstract class Futher {
public abstract void test();
}
public class A{
public static void main(String[] args) {
Futher fa = new Futher(){
@Override
public void test() {
System.out.println("arafrar");
}
};
fa.test();
}
}