带你认识内部类

什么是内部类?

内部类主要定义在类的内部,定义内部类的作用:
1.内部类是为了更好的封装,把内部类封装在外部类里,不允许同包其他类访问
2.内部类中的属性和方法即使是外部类也不能直接访问
3.相反内部类可以直接访问外部类的属性和方法,即使private
4.利于回调函数的编写。 PS:回调函数是函数的迭代
5.当描述事物,如身体里的大脑时,大脑在身体内部,可以通过内部类直观描述

定义内部类的四种方式:
1,成员内部类。
成员内部类就是作为外部类的成员变量,可以直接使用外部类的成员和方法,即使是private。
外部类需要访问内部类的所有成员变量和方法,则需要通过内部类的对象来实现。
注意:成员内部类不能包含static变量和方法。(因为成员内部类是外部类的一部分,必须通过外部实例化以后才能获得,而static在加载外部类的时候就已经初始化了,根本不需要内部类的实例化,即之间相互矛盾了,所以才说成员内部类不能包含static变量和方法)。
(1)成员内部类的形式:

public Class People{
  private String mBody;
  private Brain mBrain;

  public class Brain{
  private String mEyes;
  private String mEars;

  public void thinkObout(){
    System.out.println("I am thinking" );
     }
    }
  }

(2)成员内部类实例化。
A,通过外部类实例话。

People people = new People();
People.Brain brain = people.new Brain();

B,通过匿名外部类创建内部类。

People.Brain brain = new People().new Brain();

2,静态内部类。
静态内部类就是修饰为 static 的内部类。声明为 static 的内部类,不需要内部类对象和外部类对象之间的联系,就是说,用户可以直接引用“外部类.内部类”。
注意:在静态内部类中,
A,他不能访问外部类非静态的成员或方法,可以访问外部类的静态成员或方法。
B,他自身可以定义静态方法或者静态成员。
C,他自身的静态方法和静态成员可以用“.”进行直接访问。
(1)静态内部类的形式:

public class People{
  private String mBody;
  private Brain mBrain;

  public static class Brain{
  private String mEyes;
  private String mEars;

 public void thinkObout(){
    System.out.println("I am thinking" );
     }
  }
}

(2)静态内部类的实例化:

People.Brain brain = new People.brian();

3,方法内部类(局部内部类)
通俗来说,就是在外部内的方法中定义的内部类就是局部内部类。
局部内部类由于是在方法中定义的,因此,其作用域也是在方法内部中,方法外执行到,则被JVM回收。局部内部类的实例化也只能在方法中进行。
注意:在方法内部类中,
1)可以访问外部类中的成员
2)不能被static private 修饰,因为他不再是成员位置,只有成员才能被修饰为static…
3)因此内部类不能有静态成员
4)内部类要访问外部方法中的局部变量时,该局部变量需要被修饰成final。
(1)方法内部类的形式。

public class People{
 private  String mBody="body";
 public String mFeet ="feet";
     public void Say(){
        final String mMouth ="mouth" ;
           class Brain{
                  private String mEyes;
                  private String mEars;
                  public  String data="hehe";
                  public  void thinkObout(){
                     mBody="whahah";
                    System.out.println("I am thinking static"+ mBody+mMouth);
                     }
                    }
           Brain brain =new Brain();
           brain.thinkObout();
           mFeet =brain.data;// mFeet和data不论是public还是private都OK。

      }
      }

(2)测试实例。

public class InnerClassTest {

    public static void main(String[] args) {
        OutContainInnerClass out = new OutContainInnerClass();
        out.Say();
        System.out.println(out.mFeet);
    }
}
得到结果为:I am thinking staticwhahahmouth
hehe
hehe

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();
    }
}

实例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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值