Java内部类
Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类就像一个实例成员一样存在于外部类中。内部类又分为:静态内部类、实例内部类、本地内部类、匿名内部类四种。
- 静态内部类
当一个内部类前面用static修饰时,我们称之为静态嵌套类或静态内部类。
package ZaiJiaYou;
class OuterClass1{
private int a=10;
private static int b=20;
public OuterClass1(){
System.out.println("进入外部类构造函数");
}
public void show(){
System.out.println("进入外部类方法");
}
static class InnerClass{//静态内部类
private OuterClass1 outer=null;
public InnerClass(OuterClass1 lzq){
outer=lzq;
System.out.println("进入静态内部类构造函数");
}
public void show2(){
System.out.println(outer.a);//不能访问外部类的实例变量,必须通过传入后调用
System.out.println(b);//可以直接访问外部类的静态成员变量
System.out.println("内部类方法");
}
}
}
public class Day106 {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass1 pwd=new OuterClass1();//用外部类去创建一个对象
OuterClass1.InnerClass i=new OuterClass1.InnerClass(pwd);
i.show2();
}
}
输出结果:
静态内部类的特点:
- 可以不依赖于外部类实例被实例化,内部类的对象,并不需要其外围类的对象;
- 静态内部类的非静态成员可以访问外部类的静态变量 n 和调用静态方法,但不允许访问外部类的实例变量 x 以及实例方法;
- 静态内部类可以有静态成员,而非静态内部类则不能有静态成员;
- 静态内部类创建对象必须依赖于外部类来创建
OuterClass1.InnerClass i=new OuterClass1.InnerClass(pwd);
- 访问外部类的实例变量,必须通过传入后调用
private OuterClass1 outer=null;
System.out.println(outer.a);
2、实例内部类
package ZaiJiaYou;
class OuterClass2{
private int b=20;
private static int c=30;
private static final int d=40;
//int static int static final int
public OuterClass2(){
System.out.println("进入外部类构造方法~");
}
public void show(){
System.out.println("进入外部类方法~");
}
class InnerClass{//实例内部类--->实例成员方法、变量
private int data1=10;
private int data2=20;
//private static int data3=30;//error 实例内部类不能设静态成员?
private static final int data4=30;//立即数
//private static final int data5=data1+30;//error
public InnerClass(){
System.out.println("进入内部类构造方法~");
}
public void show(){
//System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println("data1:"+this.data1);//
//System.out.println("outer data1:"+OuterClass2.this.data1);
System.out.println(data2);
System.out.println("进入内部类方法~");
}
}
}
public class Day107 {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass2 outer=new OuterClass2();
//实例化 一个实例内部类
OuterClass2.InnerClass in=outer.new InnerClass();
in.show();//
}
}
输出结果:
实例内部类的特点:
- 内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制;
- 内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得;
内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。
输出顺序:static–>实例–>构造函数每一个实例内部类 必须有一个外部类对象,依赖外部类对象:
OuterClass2 outer=new OuterClass2();
//实例化 一个实例内部类
OuterClass2.InnerClass in=outer.new InnerClass();
3、本地内部类:可以定义在一个方法甚至一个代码块内。
package Practice;
/*
*本地内部类
*
* */
class Student{
private int age;
private String name;
//public static int data1=10;//方法区
public int data2=20;
public Student(){
System.out.println("进入外部类构造函数1~");
}
public Student(String name){
this.name=name;
System.out.println("进入外部类构造函数2~");
}
public void show(){
//static int d=20;//static 定义的一定是类得而数据成员
System.out.println("name:"+name+"age:"+age+"data2:"+data2);
}
//本地内部类:方法内部的类
public void test(){//可以是 static
final int data6=10;//局部变量
//本地内部类 只能访问拥有这个内部类方法的被 final 修饰的变量
class InnerClass{
private int a=10;
//private static int b=20;
private static final int c=20;//立即数
public InnerClass(){
}
public void show(){
System.out.println("data6:"+data6);
System.out.println("进入内部类方法~");
}
}
InnerClass in=new InnerClass();
in.show();
}
}
public class Practiceb {
public static void main(String[] args) {
// TODO Auto-generated method stub
Student s2=new Student();
s2.show();
}
}
输出结果为:
需注意的是:方法中的内部类,只是这个内部类只能在内部调用但是不能在外层的类中调用。
4、匿名内部类:Java 语言允许创建对象的同时定义类的实现,但是未规定类名,Java 将其定义为匿名内部类。Java 的匿名内部类同匿名数组一样,在只需要创建一个类的对象并且用不上它的名字时,或者说有的内部类只需要创建一个它的对象,以后不会用到这个类,在这种情况下一般使用匿名内部类比较合适。匿名内部类的语法规则如下:
new interfacename(){……};
或 new superclassname(){……};
package Practice;
/*
*匿名内部类
* */
class Student{
private int age;
private String name;
//public static int data1=10;//方法区
public int data2=20;
public Student(){
System.out.println("进入外部类构造函数1~");
}
public Student(String name){
this.name=name;
System.out.println("进入外部类构造函数2~");
}
public void show(){
//static int d=20;//static 定义的一定是类得而数据成员
System.out.println("name:"+name+"age:"+age+"data2:"+data2);
}
}
public class Practicea {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Student(){//匿名内部类相当于 当前类的子类
public void show(){
System.out.println("进入匿名内部类~");
}
}.show();
}
}
输出结果:
需要注意的:匿名内部类因为没有名字,所以它没有构造方法(但是如果这个匿名内部类继承了一个只含有带参数构造方法的父类,创建它的时候就必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果要初始化它的数据成员,可以采用下面几种方法:
- 如果是一个方法的匿名内部类,通过这个方法传进需要的参数 ,同时这些参数必须被声明为final;
- 将匿名内部类改造成有名字的局部内部类,这样这个类就可以拥有构造方法;
- 在匿名内部类中是有个初始化代码块。