内部类:在类内部进行其他类结构嵌套操作。
举栗说明:
class Outter{
private String msg = "Outter中的字符串";
//内部类
class Inner{
private String inMsg = "Inner中的字符串";
public void fun(){
//直接调用外部类的私有属性
System.out.println(msg);
}
}
public void test(){
//生产内部类对象
Inner in = new Inner();
in.fun();
}
}
public class Test{
public static void main(String[] args){
Outter out = new Outter();
out.test();
}
}
缺点:结构复杂
将Inner类提出来,主方法不变,实现相同的功能:
class Outter{
private String msg = "Outter中的字符串"; //因为这里是private属性,所以不能直接访问,需提供getter方法
public String getMsg(){
return this.msg;
}
public void test(){
//this表示当前对象
Inner in = new Inner(this);
in.fun();
}
}
class Inner{
private String inMsg = "Inner中的字符串";
private Outter out; //通过构造方法给Inner内传入一个Outter类,专业叫做【构造注入】
//此时Outter是Inner内的普通属性
public Inner(Outter out){ //这里的Outter out就是一个参数
this.out = out; //为Inner中的out变量初始化
}
public void fun(){
System.out.println(out.getMsg());
}
}
public class Test{
public static void main(String[] args){
Outter out = new Outter();
out.test();
}
}
提出来之后我们发现代码变得更加麻烦,难理解,此时我们在这里可以提一下内部类的优点:
- 内部类的优点:
a.内部类与外部类可以方便的访问彼此的私有域(包含私有方法,私有属性)
存在私有内部类(静态,成员均可)
【ArrayList中Node内部类,HashMap中Entry内部类(私有内部类)】
b.内部类是另外一种封装(保护性),对外部的其他类隐藏(心脏包在人身体内部)
c.内部类可以实现Java单继承的局限。
– 使用内部类实现Java的多继承:
class A{
private String msg = "test";
public String getMsg(){
return msg;
}
}
class B{
private int age = 20;
public int getAge(){
return age;
}
}
class C{
class InnerClassA extends A{
public String name(){
return super.getMsg();
}
}
class InnerClassB extends B{
public int age(){
return super.getAge();
}
}
public String name(){
return new InnerClassA().name();
}
public int age(){
return new InnerClassB().age();
}
}
public class Test{
public static void main(String[] args){
C c = new C();
System.out.println(c.name());
System.out.println(c.age());
}
}
多继承还是推荐多层继承。
– 内部类和外部类的关系:(不推荐使用)
1.对于非静态内部类,内部类的创建需要依赖外部类对象,在没有外部类实例之前无法创建非静态内部类。
2.内部类是一个相对独立的个体,与外部类没有is-a关系。
3.内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问。
针对于第三点:
class Outter{
private String msg;
private int age;
//-----------------内部类-----------------
class Inner{
public void display(){
msg = "test"; //直接使用
//Outter.this.msg = "test";
age = 20; //直接使用
//Outter.this.age = 20;
System.out.println(msg);
System.out.println(age);
}
}
//---------------- -------------------------
public void test(){
Inner in = new Inner();
in.display();
}
}
public class Test{
public static void main(String[] args){
Outter out = new Outter();
out.test();
}
}
内外部类可以直接访问彼此的私有属性:
class Outter{
//-------------------------------------
class Inner{ //1...
private String msg = "InnerClass";
}
//-----------------------------------------
public void test(){
Inner in = new Inner();//2...
System.out.println(in.msg);
}
}
public class Test{
public static void main(String[] args){
Outter out = new Outter();
out.test();
}
}
程序运行结果:
//InnerClass
1.说明了内外部类可以直接访问彼此的私有属性,首先必须创建外部类,才能创建内部类,创建内部类的时候就把外部类的对象传进来了 ,所以可以直接用。
2.外部类访问内部类需要创建内部类的对象以后才能用,这叫间接使用。
– 创建内部类语法(在外部类外部)
a.创建非静态内部类
外部类.内部类 内部类引用 = new 外部类().new 内部类();
Outter.Inner in = new Outter().new Inner();
b.创建静态内部类
外部类.内部类 内部类引用 = new 外部类.内部类();
Outter.Inner in = new Ourtter.Inner();
– 内部类的分类:
1.成员内部类(重点)(成员方法)
a.成员内部类不能存在任何static变量或方法,可以访问外部类的静态域。
b.成员内部类是依附外部类的,所以只有先创建了外部类才能创建内部类。(成员内部类不能拥有静态域,但可以访问外部静态域)
class Outter{
private String name = "test";
private static int age = 20;
//-------------------成员内部类----------------
class Inner{
//private static int age = 50;
//成员内部类不能存在static的变量或方法,会报错:内部类Outter.Inner中的静态声明非法。
public void fun(){
System.out.println(name); //可以访问外部类的静态或者非静态属性
System.out.println(age);
}
}
//------------------------------------------------
}
public class Test{
public static void main(String[] args){
Outter.Inner in = new Outter().new Inner();
in.fun();
}
}
2.静态内部类(重点)(静态方法)
和非静态内部类相比,静态内部类没有指向外部的引用。同时,非静态内部类不能声明静态成员,只有静态内部类才可以声明静态成员。
静态内部类将自动转换为顶层类(top-levelclass),即它没有父类,而且不能引用外部类成员或其他内部类成员。当一个内部类不需要引用外部类成员,只需要隐藏在另一个类中时,可以将该内部类声明为静态的。
a.静态内部类的创建不需要依赖外部类,可以直接创建。
b.静态内部类不可以使用任何外部类的非static域(包含属性与方法),但是可以存在自己的成员变量。
3.方法内部类(局部内部类)
方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是作用域不同,方法内部类只能在该方法中被使用。
a.方法内部类不允许使用访问权限修饰符 public private protected 均不允许。
b.方法内部类对外部完全隐藏除了创建这个类的方法可以访问它以外,其他地方均不能访问。
c.方法内部类如果要想使用方法形参,该形参必须使用final声明(JDK8将形参变为隐式final声明)
public class Test{
public static void main(String[] args){
final int i = 8;
class person{
public String name;
public void show(){
System.out.println(i);
System.out.println(this.name);
}
}
person p = new person();
p.name = "zhangsan";
p.show();
}
}
程序运行结果:
8
zhangsan
上例中,在main方法中定义了person类,它是一个内部类。内部类方法show访问了main方法中定义的final类型的局部变量。其中,方法中内部类只能访问方法中final类型的局部变量,而不能访问其他类型的局部变量,但可以访问外部类的数据成员和成员方法。
4.匿名内部类(lamdba表达式前身)
匿名内部类就是一个没有名字的方法内部类,所以它没有构造方法(但是如果这个匿名内部类继承了只含有带参数构造方法的父类,创建它的时候就必须带上这些参数,并在实现过程中使用super关键字调用相应内容)。因此特点与方法内部类完全一样,除此之外,还有两个自己的特点:
a.匿名内部类必须继承一个抽象类或者实现一个接口。
b.匿名内部类没有构造方法,因为它没有类名。
匿名类的语法规则:
new interfacename(){...}; 或
new superclassname(){...};
总结:内部类的使用暂时不作为设计的首选。
1.破坏了程序的结构。
2.方便进行私有属性的访问。(外部类可以访问内部类的私有域)
3.如果发现类名称上出现了“ . “,应当立即想到内部类的概念。