1 非静态内部类、静态内部的初始化
public class OuterClass {
//静态内部类
static class StaticInnerClass {
//静态内部类中,可以定义静态及非静态方法/变量
public static String staticFlag;
public String nonStaticFlag;
public static void printStaticFlag(String flag) {
StaticInnerClass.staticFlag = flag;
System.out.println("Call static method in staticInnerClass : " + flag);
}
public void printNonStaticFlag(String flag) {
this.nonStaticFlag = flag;
System.out.print("Call non-static method in staticInnerClass : " + flag);
}
}
//非静态内部类
class NonStaticInnerClass {
public String flag;
public void printFlag(String flag) {
this.flag = flag;
System.out.println("Call non-static method in NonStaticInnerClass : " + flag);
}
}
//在外部类的静态方法中,初始化内部类
//外部类中,内部类是可见的
public static void staticFunction() {
//1 不用实例化静态内部类,可以直接调用静态内部类的静态方法
StaticInnerClass.printStaticFlag("Static method in StaticInnerClass");
//2 外部类的静态方法中,可以调用静态内部类,不能直接创建非静态内部类
StaticInnerClass staticInnerClass = new StaticInnerClass(); //Right
//NonStaticInnerClass nonStaticInnerClass = new NonStaticInnerClass(); //Wrong
//3 外部类的静态方法中,可以先实例化外部类,再创建非静态内部类
OuterClass outerClass = new OuterClass();
NonStaticInnerClass nonStaticInnerClass = outerClass.new NonStaticInnerClass();
}
//在外部类的非静态方法中,初始化内部类
public void nonStaticFunction() {
// 非静态方法中,可以使用静态内部类、非静态内部类
// 外部类中,内部类是可见的
StaticInnerClass staticInnerClass = new StaticInnerClass();
NonStaticInnerClass nonStaticInnerClass = new NonStaticInnerClass();
nonStaticInnerClass.printFlag("Non-static method in NonStaticInnerFunction");
}
//外部类中,直接创建静态内部类、非静态内部类
StaticInnerClass staticInnerClass = new StaticInnerClass();
NonStaticInnerClass nonStaticInnerClass = new NonStaticInnerClass();
}
上述代码中,针对静态内部类、非静态内部类共有三种创建方法
第一:静态方法中,可以直接创建静态内部类,无法直接创建非静态内部类。先实例化外部类,再通过OutClass.new 可创建非静态内部类;我的理解是:非静态依附于类的实例化,无法独立于类而存在。
第二:非静态方法中,可以直接创建静态内部类、非静态内部类;
第三:在外部类中,可以直接创建静态内部类、非静态内部类。
参考链接:静态内部类与非静态内部类的区别
2 内部类访问外部类成员
public class OuterClassOne {
public String publicName;
private String privateName;
class InnerClass{
public void setName(String publicStr, String privateStr) {
publicName = publicStr;
privateName = privateStr;
}
public void printName() {
System.out.println("public variable in OuterClassOne : " + publicName);
System.out.println("private variable in OuterClassOne :" + privateName);
}
public OuterClassOne getOutClass() {
return OuterClassOne.this;//在内部类中,获取对外部类的引用
}
}
public static void main(String[] args) {
OuterClassOne outerClassOne = new OuterClassOne();
OuterClassOne.InnerClass innerClass = outerClassOne.new InnerClass();
innerClass.setName("public-variable","private-variable");
innerClass.printName();
System.out.println("OuterClassOne reference : " + innerClass.getOutClass().toString());
}
}
/* Output:
public variable in OuterClassOne : public-variable
private variable in OuterClassOne :private-variable
OuterClassOne reference : one.OuterClassOne@1b6d3586
*/
如代码所示,内部类具备所有外部类成员的访问权限,即使是private权限。原因:当外部类创建内部类对象时,内部类会获取指向该外部类对象的引用,并通过该引用来访问外部类的成员。如果想在内部类中获取对外部类的引用,可以使用OuterClassOne.this。
3 匿名函数
匿名函数就是不具名函数,主要特征就是用后即丢,一次性使用。主要用于接口实现,对比下即可发现:
3.1 普通情况(不使用匿名函数)
//不使用匿名类
//定义一个接口
interface Person {
public String getName();
public int getID(int id);
}
public class SchoolPerson {
//实现Person类
class Student implements Person {
String name = "DuJing";
public String getName() { return name; }
public int getID(int id) { return id; }
}
public Person getPerson() { return new Student();}//调用Student类的默认构造函数
public static void main(String[] args) {
SchoolPerson schoolPerson = new SchoolPerson();//调用SchoolPerson类的默认构造函数
Person student = schoolPerson.getPerson();
System.out.println("Student name : " + student.getName());
System.out.println("Student ID : " + student.getID(888));
}
}
/* Output:
Student name : DuJing
Student ID : 888
*/
现在我们假设该Student的定义只会使用一次,那么这个类也没必要出现,使用匿名函数代码如下:
3.2 使用匿名类
//使用匿名类
//定义一个接口
interface Person {
public String getName();
public int getID(int id);
}
public class SchoolPerson {
public Person getPerson() {
return new Person(){
String name = "DuJing";
public String getName() { return name; }
public int getID(int id) { return id; }
};
}
public static void main(String[] args) {
SchoolPerson schoolPerson = new SchoolPerson();//调用SchoolPerson类的默认构造函数
Person student = schoolPerson.getPerson();
System.out.println("Student name : " + student.getName());
System.out.println("Student ID : " + student.getID(888));
}
}
/* Output:
Student name : DuJing
Student ID : 888
*/
对比3.1不使用匿名类、3.2使用匿名类的代码发现:使用匿名类后,即将原先Student类的定义转移至getPerson()方法中,其余代码没有变动。Student类变成了匿名类,该类的定义只有在调用getPerson()方法时才会出现。
3.3 普通类的匿名类(普通类、带有构造函数、能够传参)
//基类,含有构造函数、内部方法、变量等
class Person {
public String name;
public int ID;
Person(String str, int id) { this.name = str; this.ID = id;}
public void getPersonMessage() {System.out.println("Person name : " + name + " Person ID : " + ID);}
public int getID() { return ID; }
}
public class SchoolPerson {
public Person getPerson() {
//匿名类,相当于继承Person,产生新的无具名类
return new Person("DuJing",888){//调用基类的构造函数
public int getID() { return super.getID() + 1000;}//覆盖基类的getID()方法
};
}
public static void main(String[] args) {
SchoolPerson schoolPerson = new SchoolPerson();//调用SchoolPerson类的默认构造函数
Person student = schoolPerson.getPerson();//使用基类Person指向不具名的子类
System.out.print("student message : ");
student.getPersonMessage();//调用匿名类方法,与基类中的定义相同
System.out.println("student new ID : " + student.getID());//调用匿名类方法,与基类中的定义不同
}
}
/* Output:
student message : Person name : DuJing Person ID : 888
student new ID : 1888
*/
通过代码得出:
第一:不仅是接口类,普通类,哪怕是包含构造函数,也可以进行匿名类设计;
第二:针对接口类,其匿名类相当于implements。针对普通类,其匿名类相当于extends,且可以覆盖原有的函数定义
第三:匿名类的定义只会在调用对应代码块的时候才会加载。
第四:匿名类可以传参,且能够调用基类的构造函数。