在类 A 中定义类 B,那么类 B 就是内部类,也称为嵌套类,相对而言,类 A 就是外部类。
如果有多层嵌套,例如类 A 中有内部类 B,而类 B 中还有内部类 C,那么通常将最外层的类称为顶层类或者顶级类)。
内部类也可以分为多种形式,与变量非常类似。
内部类的特点:
A:内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件, 但是前面冠以外部类的类名和$符号。
B:内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以 自由地访问外部类的成员变量,无论是否为 private 的。
C:内部类声明成静态的,就不能随便访问外部类的成员变量,只能访问外部类的 静态成员变量。
有关内部类的说明有如下几点:
A:外部类只有两种访问级别:public 和默认;内部类则有 4 种访问级别:public、 protected、private 和默认。
B:在外部类中可以直接通过内部类的类名访问内部类。 InnerClass ic = new InnerClass(); // InnerClass为内部类的类名
C:在外部类以外的其他类中则需要通过内部类的完整类名访问内部类。 Test.InnerClass ti = newTest().new InnerClass(); // Test.innerClass是内 部类的完整类名
D:内部类与外部类不能重名。
在Java中内部类分为几种:
Java实例内部类:
实例内部类是指没有用 static 修饰的内部类,有的地方也称为非静态内部类。
- 在外部类的静态方法和外部类以外的其他类中,必须通过外部类的实例创建内部类的实例。
2.在实例内部类中,可以访问外部类的所有成员。提示:如果有多层嵌套,则内部类可 以访问所有外部类的成员。
3.在外部类中不能直接访问内部类的成员,而必须通过内部类的实例去访问。
4.外部类实例与内部类实例是一对多的关系,也就是说一个内部类实例只对应一个外部 类实例,而一个外部类实例则可以对应多个内部类实例。
5.在实例内部类中不能定义 static 成员,除非同时使用 final 和 static 修饰。
public class InstanceInnerClassDemo {
public static void main(String[] args) {
OuterClass1.InnerClass1 innerClass1=new OuterClass1().new InnerClass1();
innerClass1.print();
OuterClass1 o=new OuterClass1();
o.testStaticMethod();
new OuterClass1().testCallInner();
}
}
class OuterClass1{
public int intA=1;//实例变量
public static String str_name="OuterClass1";//类变
//实例内部类
public class InnerClass1{//看作外部类的一个实例方法
public int in_a=2;
//public static String in_str_name="InnerClass1";//错误 在实例 内部类中不能定义static成员
public static final String in_str_name="InnerClass1";
//在内部类中定义一个构造器
public void print() {
//调用外部类的实例变量和类变量
System.out.println("内部类InnerClass1.print() "
+"intA="+intA+" str_name="+str_name);
outPrint();//调用外部类的实例方法
outStaticMethod();//调用外部类的静态方法
}
//错误 不能有静态方法
// public final static void inStaticMethod() {
//
// }
}
//静态方法
public static void testStaticMethod() {
OuterClass1 oj=new OuterClass1();
System.out.println(oj.intA);
InnerClass1 innerClass1=new OuterClass1().new InnerClass1();
// innerClass1.print();//调用实例内部类的构造方法
}
//实例方法
public void testCallInner() {
//在外部类的实例方法中
//final static修饰的成员可以通过InnerClass1调用
System.out.println("InnerClass1.in_str_name="+InnerClass1.in_str _name);
InnerClass1 ic=new InnerClass1();
System.out.println("ic.in_a="+ic.in_a);
ic.print();
InnerClass1 ic2=new InnerClass1();
InnerClass1 ic3=new InnerClass1();
InnerClass1 ic4=new InnerClass1();
}
//实例方法
public void outPrint() {
System.out.println("OuterClass1实例方法outPrint()");
}
//静态方法
public static void outStaticMethod() {
System.out.println("OuterClass1静态方法outStaticMethod()");
}
}
Java静态内部类
public class StaticInnerClassDemo {
public static void main(String[] args) {
OuterClass2.testStaticMethod();//调用OuterClass2的静态方法
System.out.println("--------------");
OuterClass2 oc=new OuterClass2();//创建OuterClass2的对象
oc.testInstanceMethod();//调用OutClass类中的实例方法
System.out.println("---------------------------------");
System.out.println("在外部类以外去访问静态内部类");
//访问静态内部类的static成员
System.out.println(OuterClass2.InnerClass2.in_str_name);
OuterClass2.InnerClass2.inStaticMethod();
System.out.println("---------------------------");
//访问静态内部类的实例成员 需要先new 内部类实例
OuterClass2.InnerClass2 ic=new OuterClass2.InnerClass2();
System.out.println(ic.in_a);
ic.inInstanceMethod();
}
}
class OuterClass2{
public int out_a=0;
public static String out_str_name="OutClass2";
//静态内部类
public static class InnerClass2{
public int in_a=1;//实例变量
public static String in_str_name="InnerClass2";//类变量
//静态内部类的实例方法
public void inInstanceMethod() {
System.out.println("静态内部类的实例方法inInstanceMethod "+"out_str_name="+out_str_name);
outStticMethod();
//在静态内部类访问外部类的实例成员 new一个外部类的实例
OuterClass2 oc=new OuterClass2();
System.out.println(oc.out_a);
}
//静态内部类的静态方法
public static void inStaticMethod() {
System.out.println("静态内部类的静态方法inStaticMethod "+"out_str_name="+out_str_name);
outStticMethod();
//在静态内部类访问外部类的实例成员 new一个外部类的实例
OuterClass2 oc=new OuterClass2();
System.out.println(oc.out_a);
}
}
public static void outStticMethod() {
System.out.println("外部类的静态方法outStticMethod");
}
//静态方法
public static void testStaticMethod() {
//使用静态内部类的 类变量
System.out.println(InnerClass2.in_str_name);
//调用静态内部类的方法
InnerClass2.inStaticMethod();
//使用静态内部类的实例方法和实例变量, 需要先new
InnerClass2 ic=new InnerClass2();
System.out.println(ic.in_a);
ic.inInstanceMethod();
}
//实例方法
public void testInstanceMethod() {
//使用静态内部类的 类变量
System.out.println(InnerClass2.in_str_name);
//调用静态内部类的方法
InnerClass2.inStaticMethod();
//使用静态内部类的实例方法和实例变量, 需要先new
InnerClass2 ic=new InnerClass2();
System.out.println(ic.in_a);
ic.inInstanceMethod();
}
}
Java局部内部类
局部内部类是指在一个方法(或代码块)中定义的内部类。
局部内部类有如下特点:
1. 局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
2. 局部内部类只在当前方法中有效。
3. 局部内部类中不能定义 static 成员。4. 局部内部类中还可以包含内部类,但是 这些内部类也不能使用访问控制修饰符(public、private 和 protected)和 static 修 饰符修饰。
5. 在局部内部类中可以访问外部类的所有成员。
6. 在局部内部类中只可以访问当前方法中 final 类型的参数与变量。如果方法中的成 员与外部类中的成员同名,则可以使用 OuterClassName.this.MemberName的形式访问 外部类中的成员。
public class LocalInnerClassDemo {
public static void main(String[] args) {
OuterClass3 class3=new OuterClass3();//创建OuterClass的对象
class3.outInstanceMethod1();//调用类中的实例方法
}
}
class OuterClass3{
int out_a=1;//实例变量
static int out_b=2;//静态变量
int b=10;//实例变量
//静态方法
public static void outStaticMethod() {
System.out.println("outStaticMethod");
}
//实例方法
public void outInstanceMethod() {
System.out.println("outInstanceMethod");
}
//实例方法,在这个实例方法中,写一个局部内部类
public void outInstanceMethod1() {
int a=1;//java8开始 自动为局部内部类中被使用的变量添加final修饰符
final int b=2;//final修饰的变量,也叫常量
//局部内部类
class InnerClass3{
public int in_a=2;
// public static String str_static="";//局部内部类中不能定义static 成员
public void test() {
System.out.println(out_a);
System.out.println(out_b);
outStaticMethod();//调用外部类的静态方法
outInstanceMethod();//调用外部类的实例方法
System.out.println(b);//输出这个方法中的局部变量
System.out.println(a);//输出这个方法中的局部变量
System.out.println(OuterClass3.this.b);//调用外部类实例变量
// a=3;//java8 开始自动为局部内部类中被使用的变量添加final修饰符
}
}
InnerClass3 ic=new InnerClass3();//实例化局部内部类
ic.test();//调用局部内部类的实例方法
}
}
Java匿名内部类
匿名内部类是指没有类名的内部类,必须在创建时使用 new 语句来声明类。
匿名内部类有两种实现方式:
继承一个类,重写其方法。
实现一个接口(可以是多个),实现其方法。
匿名内部类有如下特点:
1. 匿名类和局部内部类一样,可以访问外部类的所有成员。如果匿名类位于一个方法 中,则匿名类只
能访问方法中 final 类型的局部变量和参数。
2. 匿名类中允许使用非静态代码块进行成员初始化操作。
3. 匿名类的非静态代码块会在父类的构造方法之后被执行。
public class AnonymousClassDemo {
public static void main(String[] args) {
Object obj=new Object() {
public void print() {
System.out.println("这时一个匿名类");
}
};
System.out.println(obj);
//直接new一个Interface1接口的匿名具体类
Interface1 interface1=new Interface1() {
//重写接口的抽象方法
@Override
public void show(String str) {
System.out.println(str);
}
};
interface1.show("interface1接口的匿名实现类");
System.out.println(interface1);
TestClass testclass=new TestClass() {
int s;
{
System.out.println("TestClass的匿名子类初始化代码块");
s=1;
}
public void say() {
System.out.println("TestClass的匿名子类的say方法");
System.out.println(s);
}
};
testclass.say();
System.out.println(testclass);
System.out.println(testclass instanceof TestClass);
}
}
interface Interface1{
void show(String str);
}
class TestClass{
//无参构造方法
public TestClass() {
System.out.println("TestClass的构造器");
}
//构造方法
public void say() {
System.out.println("TestClass的say方法");
}
}