目录
- 1.内部类介绍
- 2.实例内部类
- 3.静态内部类
- 4.局部内部类
- 5.匿名内部类
1.内部类介绍
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在 Java 中,**可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。**内部类也是封装的一种体现。
注意事项
1.定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类,举例如下
public class A{
}
class B{
}
// A 和 B是两个独立的类,彼此之前没有关系
2.内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。如下说示:
class OuterClass{
public int data1=1;
private int data2=2;
class InnerClass{
public int data1=100;
public int data3=3;
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
OuterClass.InnerClass innerClass=out.new InnerClass();
}
}
编译后产生的字节码文件
2.实例内部类
代码形式
class OuterClass{
public int data1=1;
private int data2=2;
class InnerClass{
public int data1=100;
public int data3=3;
}
}
1.外部类中的任何成员都可以在实例内部类方法中直接访问
class OuterClass{
public int data1=1;
private int data2=2;
public void test(){
System.out.println("OuterClass::test()");
System.out.println(data1);
}
class InnerClass{
public void test1(){
System.out.println("InnerClass::test()");
System.out.println(data1);
System.out.println(data2);
//直接调用外部类的data1和data2并打印
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
OuterClass.InnerClass innerClass=out.new InnerClass();
innerClass.test1();
}
}
运行结果
2.实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
使用private修饰后,下面实例化的时候就会报错,如下所示
被public修饰就不展示了
3.在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问
class OuterClass{
public int data1=1;
private int data2=2;
public void test(){
System.out.println("OuterClass::test()");
System.out.println(data1);
}
class InnerClass{
public int data1=100;//与外部类同名成员
public void test1(){
System.out.println("InnerClass::test()");
System.out.println(this.data1);
System.out.println(data2);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
OuterClass.InnerClass innerClass=out.new InnerClass();
innerClass.test1();
}
}
运行结果
如果要想访问到外部类的同名方法,修改如下
public void test1(){
System.out.println("InnerClass::test()");
System.out.println(OuterClass.this.data1);
System.out.println(data2);
}
运行结果
4.实例内部类对象必须在先有外部类对象前提下才能创建
下面提供两种实例化方式
public static void main(String[] args) {
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
OuterClass out=new OuterClass();
OuterClass.InnerClass innerClass=out.new InnerClass();
OuterClass.InnerClass innerClass1=new OuterClass().new InnerClass();
}
5.实例内部类的非静态方法中包含了一个指向外部类对象的引用
class OuterClass{
public int data1=1;
private int data2=2;
public void test(){
System.out.println("OuterClass::test()");
System.out.println(data1);
}
class InnerClass{
public void test1(){
OuterClass out=new OuterClass();
//在内部类方法中创建一个外部类对象,通过这个对象调用外部类成员方法
out.test();
System.out.println("=================");
System.out.println("InnerClass::test()");
System.out.println(data1);
System.out.println(data2);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
OuterClass.InnerClass innerClass=out.new InnerClass();
innerClass.test1();
}
}
运行结果
6.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
class OuterClass{
public int data1=1;
private int data2=2;
public void test(){
OuterClass.InnerClass innerClass=new InnerClass();
//在外部类中实例化了一个内部类对象调用内部类成员
innerClass.test1();
System.out.println("===================");
System.out.println("OuterClass::test()");
System.out.println(data1);
}
class InnerClass{
public void test1(){
System.out.println("InnerClass::test()");
System.out.println(data1);
System.out.println(data2);
}
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
out.test();
}
}
运行结果
3.静态内部类
1.在静态内部类中只能访问外部类中的静态成员
class OuterClass{
public int data1=1;
private int data2=2;
static int data3=3;
public void test(){
System.out.println("OuterClass::test()");
System.out.println(data1);
}
static class InnerClass{
public void test1(){
System.out.println("InnerClass::test()");
System.out.println(data1);//非静态成员,会报错
System.out.println(data2);//非静态成员,会报错
System.out.println(data3);//静态成员正常访问
}
}
}
如果确实想访问,我们该如何做?
在内部类方法里实例化一个外部类方法
static class InnerClass{
public void test1(){
OuterClass out=new OuterClass();
System.out.println("InnerClass::test()");
System.out.println(out.data1);
System.out.println(out.data2);
System.out.println(data3);
}
运行结果
2.创建静态内部类对象时,不需要先创建外部类对象
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass innerClass=new OuterClass.InnerClass();
//直接通过外部类调用就可创建静态内部类的对象
innerClass.test1();
}
}
4.局部内部类
定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式。
1.局部内部类只能在所定义的方法体内部使用
class OuterClass{
public void method() {
int data1=1;
class InnerClass{
void test1(){
System.out.println("InnerClass::test1()");
System.out.println(data1);
}
}
//只能在方法体内部使用
InnerClass innerClass=new InnerClass();
innerClass.test1();
}
}
public class Test {
public static void main(String[] args) {
OuterClass out=new OuterClass();
out.method();
}
}
运行结果
如果在方法题外部使用会出现报错
2.不能被public、static等修饰符修饰
报错结果如下
3.编译器也有自己独立的字节码文件,命名格式:外部类名字$数字内部类名字.class
4.几乎不会使用
5.匿名内部类
匿名内部类可以用来实现一个接口并创建一个新的线程,举例如下
interface ITestable{
void test();
}
public class Test {
public static void main(String[] args) {
new ITestable(){//直接实现这个接口
@Override
public void test() {
System.out.println("hello zzuli");
}
};
}
}
上面的代码相当于下面通过implments
来实现一个接口
interface ITestable{
void test();
}
class A implements ITestable{
@Override
public void test() {
System.out.println("hello zzuli");
}
}
public class Test {
public static void main(String[] args) {
A a=new A();
}
}
我们通过匿名内部类来实现接口,那么我们应该怎么使用接口里的方法呢?
下面提供两种方法
方法一:直接通过.来调用,代码如下
interface ITestable{
void test();
}
public class Test {
public static void main(String[] args) {
new ITestable(){
@Override
public void test() {
System.out.println("hello zzuli");
}
}.test();//直接调用
}
}
方法二:通过创建一个变量来调用(推荐使用)
interface ITestable{
void test();
}
public class Test {
public static void main(String[] args) {
ITestable I=new ITestable(){
@Override
public void test() {
System.out.println("hello zzuli");
}
};
I.test();//通过变量名调用
}
}