一、概念

 内部类就是在一个类的内部定义的类,在一个类的内部进行其它类结构的嵌套的操作。

二、内部类的作用(为什么要存在?)

 a.内部类允许把一些逻辑相关的类组织在一起,并且控制内部类代码的可视性。
 b.内部类方法可以访问该类定义所在作用域中的数据,包括被private修饰的私有数据。
 c.内部类可以对同一包中的其它类(除外部类外)隐藏起来。
 d.内部类可以弥补Java单继承的缺陷。(一类套一类)
 e.当我们想要定义一个回调函数却不想写大量代码时,可以选择用匿名内部类实现。

三、内部类和外部类的关系

  a.对于非静态内部类,内部类的实例化依赖于外部类的实例对象,必须先对外部类进行实例化后,才可以将内部类实例化。
  b.内部类可以访问外部类的所有成员(包括private修饰的成员),但是外部类不能直接访问内部类的成员。
  c.外部类可以通过实例化内部类间接访问内部类的元素。
  d.内部类是一个相对独立的个体,与外部类不是类的父子继承关系(is-a关系)。
  e.在多重嵌套时,内部类可以访问其所有外围类的元素。
  f.一个外部类可以实例化多个内部类,但是一个内部类实例只会引用一个外部类。

四、内部类的分类、说明和使用

1.成员内部类

不被static修饰的内部类。如:

class A{
                    class B{//B为成员内部类
           
                      }
                 }

  定义成员内部类:

外部类.内部类  内部对象=new 外部类().new 内部类();   eg:A.B b=new A().new B();

说明:

a.成员内部类中不能含有任何被static修饰的变量、方法和内部类。
b.成员内部类的实例化依赖于外部类,只有当外部类实例化后,内部类才可以实例化。
c.如果成员内部类B和外部类A具有相同的变量名v,这没有任何影响。在类B中,用this.v代表类B的变量v;用A.this.v代表类A的变量v.

2.静态内部类

用static修饰的内部类。如:

class A{
               class B{
                        int v1;//实例变量
                        static int v2;//静态变量
                        public class C{//静态内部类
                                   static int v3;
                              }
                            }
                     }

  定义静态内部类:

外部类.内部类 内部对象=new 外部类.内部类();    eg:A.B b=new A.B();

  说明:

a.静态内部类不能使用外部类的任何非静态成员,这些成员必须通过外部类的实例化访问。
b.静态内部类可以直接访问外部类的静态成员。A.B.v2=1;
c.在静态内部类中可以定义静态成员和非静态成员。
d.客户类可以通过完整的类名直接访问静态内部类的静态成员。

如: 在上例中,

访问v1:   A.B b=new A.B();     b.v1=1;
访问v2:  A.B.v2=1;
访问v3:  A.B.C.v3=5;

 3.方法内部类

定义在外部类方法中的内部类,只在该方法内有效。如:

public class Test{
	public static void main(String[] args){
	A a=new A();
        A.fun();	
	}
           }
class A{
	int age;
	static void fun(){
		class B{
			String date="2018-11-17";
                        public B(){
				System.out.println("我是内部类的构造方法");
			  }
			public void print(){
				date="1998-8-20";
				date="2018-11-18";
				System.out.println(date);//通过定义匿名对象来调用方法内部类的属性
				System.out.println("我是方法内部类");
			}
		}
		new B().print();//通过定义匿名对象来调用方法内部类的函数
	}
}

结果:

2018-11-18
我是方法内部类

说明:

a.静态内部类的实例化不依赖于外部类,可以直接创建。
b.方法内部类的作用域只在该方法内部有效。对于外部类,该内部类都是无效的。
c.局部内部类如果想使用方法形参,该形参必须使用final声明。(JDK8中形参声明为隐式final声明)。
d.局部内部类不允许使用任何修饰符public、private、protected修饰。

4.匿名内部类

没有名字的方法内部类.因此,它符合方法内部类的所有约束。    如:

public class Test{
	public static void main(String[] args){
	Outer outer=new Outer();
	outer.display(20);
	}
}
interface MyInterFace{
	void test();
}
class Outer{
	private int num;
	public void display(int para){
		//匿名内部类,实现MyInterface接口
		new MyInterFace(){
			public void test(){
				System.out.println("匿名内部类"+para);
			}
		}.test();
	}
}

结果:

   匿名内部类20
说明:

a.匿名内部类不允许使用任何修饰符public、private、protected修饰。
b.匿名内部类必须继承一个抽象类或实现一个接口。
c.匿名内部类中不能存在任何静态方法或成员。
d.匿名内部类因为没有名字,不能有任何构造方法。
e.匿名内部类可以引用方法形参,但是必须声明为final。

五、内部类的一些其它说明

1.如果在外部类和内部类中定义了相同的属性(变量名相同,但是内容不同),则按照就近原则。要想在内部类中访问外部类的属性或方法,需要定义  外部类.this.属性名/方法名。

package com.xupu.testinnerclass;

class Outter{
    private String str="Outter";
    private class Inner{//只能由外部类定义
        private String str="Inner";
        void fun(){
            System.out.println("我是成员内部类"+" "+str);
        }
    }
    public void fun(){
        System.out.println(str);
        Inner inner=new Inner();
        inner.fun();
    }
}
public class TestInnerClass {
    public static void main(String[] args) {
        Outter outter=new Outter();
        outter.fun();

    }
}

结果:

Java内部类的详解 java中内部类的作用_Java内部类的详解