​java-内部类详解

目录

 内部类概念

1、成员内部类

(联想到成员变量和成员方法,内部类所在位置和类的成员同级)

2、静态内部类 (联想到静态成员,使用static修饰)

 3、局部内部类(联想到局部变量,位于外部类的成员方法之中)

4、匿名内部类(联想到匿名对象和匿名数组,内部类没有名称,需要存在一个类或接口)


内部类概念

定义:把类定义在其他类的内部,这个类被称为内部类(嵌套类)。

分类:根据其所在位置及形式的不同,分为成员内部类、静态内部类、局部内部类、匿名内部类。

1、成员内部类

(联想到成员变量和成员方法,内部类所在位置和类的成员同级)

// 外部类
class OuterClass01 {

// 成员内部类

class InnerClass01 {



}

}

观察一下生成的字节码文件,有两个:OuterClass01.class、OuterClass01$InnerClass01.class,

成员内部类字节码名称为: 外部类名称$成员内部类名称.class。

创建方式:

1.1 创建成员内部类对象的方式1:通过调用成员内部类的构造函数。

格式:外部类名.内部类名 成员内部类对象名 = 外部类对象.new 内部类构造函数();

方法1、OuterClass01.InnerClass01 innerClass01 = (new OuterClass01()).new InnerClass01();

方法2、OuterClass01.InnerClass01 innerClass01 = new OuterClass01().new InnerClass01();

package cn.temptation;

public class Test {

    public static void main(String[] args) {

    //创建出外部类对象

        OuterClass01 outerClass01 = new OuterClass01();

        OuterClass01.InnerClass01 innerClass01 = outerClass01.new InnerClass01();

        System.out.println(innerClass01);

        // cn.temptation.OuterClass01$InnerClass01@15db9742

    }

}

 理解:OuterClass01.InnerClass01 innerClass01 = outerClass01.new InnerClass01();

可以理解为:OuterClass01.InnerClass01 innerClass01 = outerClass01.(new InnerClass01());(这种写法语法有错,只是为了方便理解才这样写)即,通过对象名.这样的方式调用类的成员,这里的成员内部类也是这个外部类的成员,也就考虑使用对象名.这样的方式进行调用且这里要获取的是成员内部类对象,所以通过new 成员内部类的构造函数获取成员内部类对象

1.2 创建成员内部类对象的方式2:

通过调用成员内部类所在的外部类的成员方法,在外部类中创建出成员内部类的对象

// 外部类
class OuterClass02 {

// 成员变量

private InnerClass02 innerClass02;

// 成员方法

// 多例创建方法(在类的内部,成员方法可以访问成员)

public InnerClass02 getInnerClass02() {

return new InnerClass02();

}


// 单例创建方法(懒汉式,在类的内部,成员方法可以访问成员)

public InnerClass02 getInstance() {

if (innerClass02 == null) {

innerClass02 = new InnerClass02();

}


return innerClass02;

}


// 成员内部类

class InnerClass02 {

// 设置构造函数为私有

private InnerClass02() {


}

}

}
package cn.temptation;



public class Test {

    public static void main(String[] args) {

        OuterClass02 outerClass02 = new OuterClass02();



        // 创建成员内部类对象的写法(多例)

        OuterClass02.InnerClass02 innerClass02 = outerClass02.getInnerClass02();

        System.out.println(innerClass02);  

        //cn.temptation.OuterClass02$InnerClass02@15db9742

        OuterClass02.InnerClass02 innerClass02Ex = outerClass02.getInnerClass02();

        System.out.println(innerClass02Ex);  

        //cn.temptation.OuterClass02$InnerClass02@6d06d69c


        System.out.println("----------------------");


        // 创建成员内部类对象的写法(单例)

        OuterClass02.InnerClass02 innerClass02Demo = outerClass02.getInstance();

        System.out.println(innerClass02Demo);      

       //cn.temptation.OuterClass02$InnerClass02@7852e922

        OuterClass02.InnerClass02 innerClass02DemoEx = outerClass02.getInstance();

        System.out.println(innerClass02DemoEx);          

       //cn.temptation.OuterClass02$InnerClass02@7852e922

    }

}

特点: 

1、成员内部类可以直接访问其所在的外部类的非静态成员变量和静态的成员变量

// 外部类

class OuterClass04 {

// 非静态的成员变量

public int i = 2;

private int j = 3;

// 静态的成员变量

public static int x = 4;

private static int y = 5;



// 成员内部类

class InnerClass04 {

// 成员方法

public void showByInner() {

// 成员内部类对于其所在的外部类的非静态成员变量均可以访问(不论使用public修饰,还是private修饰)

System.out.println(i);

System.out.println(j);

// 成员内部类对于其所在的外部类的静态成员变量均可以访问(不论使用public修饰,还是private修饰)

System.out.println(x);

System.out.println(y);

}

}

外部类和内部类成员变量相同时: 获取的变量值采取的是就近原则

// 外部类

class OuterClass05 {

// 非静态的成员变量

public int i = 2;

// 外部类的成员变量和内部类的成员变量同名

public int k = 4;

// 静态的成员变量

public static int x = 6;

public static int z = 8;



// 成员内部类

class InnerClass05 {

// 非静态的成员变量

public int j = 3;

// 外部类的成员变量和内部类的成员变量同名

public int k = 5;

// 静态的成员变量:在非静态的成员内部类中定义静态的成员变量,语法出错

// 语法错误:The field y cannot be declared static in a non-static inner type, unless initialized with a constant expression

// public static int y = 7;

// 语法错误:The field z cannot be declared static in a non-static inner type, unless initialized with a constant expression

// public static int z = 9;



// 成员方法

public void showByInner() {

System.out.println(i); // 2

System.out.println(j); // 3

System.out.println(k); // 5 --- 内部类的成员变量(就近原则)

System.out.println(this.k); // 5 --- 内部类的成员变量(this指的是当前这个成员内部类对象)

System.out.println(this); // cn.temptation.OuterClass05$InnerClass05@15db9742



// 问题:就想在成员内部类的成员方法中使用其所在的外部类的同名成员变量,怎么办?

// 思路1、考虑创建外部类对象,再通过外部类对象.成员变量获取

System.out.println((new OuterClass05()).k); // 4 --- 外部类的成员变量

// 思路2、考虑成员内部类对象创建出来时,其所在的外部类对象是否创建了,如果创建了,是什么样的访问形式

// 答:创建了,访问形式为外部类类名.this

System.out.println(OuterClass05.this); // cn.temptation.OuterClass05@6d06d69c

System.out.println(OuterClass05.this.k); // 4 --- 外部类的成员变量



// 访问外部类的静态成员变量,直接通过外部类类名.静态成员变量

System.out.println(OuterClass05.x); // 6

System.out.println(OuterClass05.z); // 8

}

}

2、成员内部类的成员方法可以访问其所在的外部类的所有成员方法(不论是否公有,不论是否静态)

// 外部类

class OuterClass06 {

// 成员方法

public void method1() {

System.out.println("外部类的公有非静态成员方法");

}



private void method2() {

System.out.println("外部类的私有非静态成员方法");

}



public static void method3() {

System.out.println("外部类的公有静态成员方法");

}



private static void method4() {

System.out.println("外部类的私有静态成员方法");

}



// 成员内部类

class InnerClass06 {

// 成员方法

public void showByInner() {

// 成员内部类的成员方法可以访问其所在的外部类的所有成员方法(不论是否公有,不论是否静态)

method1();

method2();

method3();

method4();

}

}

2、静态内部类 (联想到静态成员,使用static修饰)

// 外部类

class OuterClass08 {

// 静态内部类

static class InnerClass08 {



}

}

观察一下生成的字节码文件,有两个:OuterClass08.class、OuterClass08$InnerClass08.class,静态内部类字节码名称为:外部类名称$静态内部类名称.class。

创建方式:

格式:外部类名.内部类名   静态内部类对象名  =  new 外部类名.静态内部类构造函数();

package cn.temptation;



public class Test {

    public static void main(String[] args) {

        OuterClass08.InnerClass08 innerClass08 = new OuterClass08.InnerClass08();

        System.out.println(innerClass08);

        // cn.temptation.OuterClass08$InnerClass08@15db9742



    }

}

 特点:

1、静态内部类中不论是静态的成员方法,还是非静态的成员方法,只能访问其所在的外部类的静态成员变量

// 外部类

class OuterClass09 {

// 非静态的成员变量

public int i = 2;

private int j = 3;

// 静态的成员变量

public static int x = 4;

private static int y = 5;



// 静态内部类

static class InnerClass09 {

// 非静态的成员方法

public void showByInner() {

// 静态内部类中的非静态成员方法无法访问其所在的外部类的非静态的成员变量

// Cannot make a static reference to the non-static field i

// System.out.println(i);

// Cannot make a static reference to the non-static field j

// System.out.println(j);



// 静态内部类中的非静态成员方法可以访问其所在的外部类的静态的成员变量

System.out.println(x); // 4

System.out.println(y); // 5

}



// 静态的成员方法

public static void showByInnerStatic() {

// 静态内部类中的静态成员方法无法访问其所在的外部类的非静态的成员变量

// Cannot make a static reference to the non-static field i

// System.out.println(i);

// Cannot make a static reference to the non-static field j

// System.out.println(j);



System.out.println(x); // 4

System.out.println(y); // 5

}

}

 2、静态内部类中不论是静态的成员方法,还是非静态的成员方法,只能访问其所在的外部类的静态成员方法

// 外部类

class OuterClass10 {

// 成员方法

public void method1() {

System.out.println("外部类的公有非静态成员方法");

}



private void method2() {

System.out.println("外部类的私有非静态成员方法");

}



public static void method3() {

System.out.println("外部类的公有静态成员方法");

}



private static void method4() {

System.out.println("外部类的私有静态成员方法");

}



// 静态内部类

static class InnerClass10 {

// 非静态的成员方法

public void showByInner() {

// 语法错误:Cannot make a static reference to the non-static method method1() from the type OuterClass10

// method1();

// 语法错误:Cannot make a static reference to the non-static method method2() from the type OuterClass10

// method2();



method3();

method4();

}



// 静态的成员方法

public static void showByInnerStatic() {

// 语法错误:Cannot make a static reference to the non-static method method1() from the type OuterClass10

// method1();

// 语法错误:Cannot make a static reference to the non-static method method2() from the type OuterClass10

// method2();



method3();

method4();

}

}

 3、局部内部类(联想到局部变量,位于外部类的成员方法之中)

// 外部类

class OuterClass12 {

// 成员方法

public Object showByOuter() {

// 局部内部类

class InnerClass12 {



}



// 在外部类的成员方法中实例化局部内部类

InnerClass12 innerClass12 = new InnerClass12();

return innerClass12;

}

}

观察一下生成的字节码文件,有两个:OuterClass12.class、OuterClass12$1InnerClass12.class 局部内部类字节码名称为: 外部类名称 $ 编号 局部内部类名称.class。这里的编号是局部内部类类型的相应的编号,同一种局部内部类编号从1开始。

注意:在同一个外部类的成员方法中,不允许创建多个同名的局部内部类;外部类中的不同成员方法中可以定义相同名称的局部内部类,这些局部内部类可以名称相同、成员不同。

局部内部类的成员方法访问局部内部类所在的外部类的成员方法中定义的局部变量,局部变量可以使用final修饰,也可以不使用final修饰 ,但是不论是否使用final修饰,对于局部内部类的成员方法均只能访问(读取),而不能设置(赋值)

创建方式:

// 只能通过其所在的外部类的成员方法返回在成员方法中创建出的局部内部类对象

OuterClass12 outerClass12 = new OuterClass12();

System.out.println(outerClass12.showByOuter());    

 特点

1、局部内部类中可以直接访问其所在的外部类的非静态的成员变量 和 静态的成员变量

// 外部类

class OuterClass13 {

// 非静态的成员变量

public int i = 2;

private int j = 3;

// 外部类和局部内部类同名的成员变量

public int k = 4;

// 静态的成员变量

public static int x = 6;

private static int y = 7;

public static int z = 8;



// 成员方法

public void showByOuter() {

// 局部内部类

class InnerClass13 {

// 非静态的成员变量

// 外部类和局部内部类同名的成员变量

public int k = 5;

// 静态的成员变量

// 语法错误:The field z cannot be declared static in a non-static inner type, unless initialized with a constant expression

// public static int z = 8;



// 成员方法

public void showByInner() {

// 局部内部类对于其所在的外部类的非静态成员变量均可以访问(不论使用public修饰,还是private修饰)

System.out.println(i); // 2

System.out.println(j); // 3

// 局部内部类对于其所在的外部类的静态成员变量均可以访问(不论使用public修饰,还是private修饰)

System.out.println(x); // 6

System.out.println(y); // 7



System.out.println(k); // 5 --- 局部内部类的非静态成员变量(就近原则)

System.out.println(this.k); // 5 --- 局部内部类的非静态成员变量(this指的是局部内部类对象)

System.out.println(this); // cn.temptation.OuterClass13$1InnerClass13@15db9742



System.out.println(OuterClass13.this); // cn.temptation.OuterClass13@6d06d69c

System.out.println(OuterClass13.this.k); // 4 --- 外部类的非静态成员变量



System.out.println(OuterClass13.z); // 8

}

}



// 在外部类的成员方法中实例化局部内部类对象

InnerClass13 innerClass13 = new InnerClass13();

innerClass13.showByInner();

}

 2、局部内部类中可以直接访问其所在的外部类的非静态的成员方法 和 静态的成员方法

// 外部类

class OuterClass14 {

// 成员方法

public void method1() {

System.out.println("外部类的公有非静态成员方法");

}



private void method2() {

System.out.println("外部类的私有非静态成员方法");

}



public static void method3() {

System.out.println("外部类的公有静态成员方法");

}



private static void method4() {

System.out.println("外部类的私有静态成员方法");

}



public void showByOuter() {

// 局部内部类

class InnerClass14 {

// 成员方法

public void showByInner() {

// 局部内部类对于其所在的外部类的非静态成员方法均可以访问(不论使用public修饰,还是private修饰)

method1();

method2();

// 局部内部类对于其所在的外部类的静态成员方法均可以访问(不论使用public修饰,还是private修饰)

method3();

method4();

}

}



// 在外部类的成员方法中实例化局部内部类对象

InnerClass14 innerClass14 = new InnerClass14();

innerClass14.showByInner();

}

4、匿名内部类(联想到匿名对象和匿名数组,内部类没有名称,需要存在一个类或接口)

// 定义接口

interface Foo {

public abstract void show();

}



// 接口的实现类

class FooImpl implements Foo {

@Override

public void show() {

System.out.println("接口的实现类的成员方法");

}

}



// 外部类

class OuterClass18 {

// 成员方法

public Foo showByOuter() {

// 多态的写法,创建接口类型的变量,接收接口实现类类型的对象,并返回

// Foo foo = new FooImpl();

// return foo;



// 对上述写法的变形,匿名对象的写法

// return new FooImpl();



// 实现了Foo接口的匿名内部类(位置位于类似局部内部类的位置)

return new Foo() {

@Override

public void show() {

System.out.println("实现了接口的匿名内部类");

}

};


}

观察一下生成的字节码文件,有两个:OuterClass18.class、OuterClass18$1.class

匿名内部类字节码名称为: 外部类名称$编号.class

创建方式

通过调用匿名内部类所在的外部类的成员方法

package cn.temptation;



public class Test {

    public static void main(String[] args) {

        OuterClass18 outerClass18 = new OuterClass18();

        // 定义接口类型的变量来接收匿名内部类对象的返回

        Foo foo = outerClass18.showByOuter();

        System.out.println(foo);

        // cn.temptation.OuterClass18$1@15db9742

        foo.show(); // 这句语句实际调用接口实现对象(匿名内部类对象)的成员方法

    }

}

特点

1、匿名内部类没有构造函数,且使用者无法创建构造函数,但是实际上JDK为匿名内部类生成了构造函数

2、匿名内部类的成员方法中可以访问其所在的外部类的成员变量(不论是否公有私有,不论是否静态非静态),变量相同时也是就近原则

// 接口

interface Sample {

public abstract void show();

}



// 外部类

class OuterClass22 {

// 成员变量

public int i = 2;

private int j = 3;

int k = 6;

public static int x = 4;

private static int y = 5;



// 成员方法

public void showByOuter() {

// 局部变量

int k = 7;



// 匿名内部类

(new Sample() {

@Override

public void show() {

System.out.println(i); // 2

System.out.println(j); // 3

System.out.println(x); // 4

System.out.println(y); // 5



System.out.println(k); // 7 --- 局部变量(就近原则)

// 语法错误:k cannot be resolved or is not a field

// System.out.println(this.k);

System.out.println(this); // cn.temptation.OuterClass22$1@15db9742

System.out.println(OuterClass22.this); // cn.temptation.OuterClass22@6d06d69c

System.out.println(OuterClass22.this.k);// 6

}

}).show();

}

  • 32
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: nohup java -jar命令是在Linux系统中运行Java程序的命令。其中,nohup表示不挂断地运行命令,即使终端关闭也不会停止程序的运行;java表示运行Java程序;-jar表示运行一个打包成jar文件的Java程序。 具体来说,nohup java -jar命令可以在后台运行一个Java程序,而不会受到终端关闭等操作的影响。这对于需要长时间运行的程序非常有用,比如服务器端的应用程序。 需要注意的是,nohup java -jar命令需要在Linux系统中使用,而且需要安装Java环境。同时,需要将Java程序打包成jar文件才能使用该命令运行。 ### 回答2: nohup java -jar命令是一个常用的命令,用于在后台运行Java应用程序。它的作用是让Java应用程序在用户退出登录后继续运行,并且不受挂起信号的影响。 nohup命令是词组“no hang up”的缩写,表示不挂断。nohup命令后紧跟着的是要在后台运行的命令,本例中是java -jar命令。这个命令指定使用Java虚拟机(JVM)来运行一个以jar包形式打包的Java应用程序。 使用nohup java -jar命令有很多好处。首先,它可以让Java应用程序在后台持续运行,即使您退出了登录。其次,它可以防止Java应用程序被终止,即使系统发送了中断信号或挂起信号。此外,nohup命令还会将输出信息保存到一个文件中。默认情况下,该文件名为nohup.out,但是您可以使用重定向运算符(>)将它重定向到其他文件。 举个例子,如果您想在Linux系统上运行一个名为myapp.jar的Java应用程序,您可以使用以下命令: nohup java -jar myapp.jar & 此命令将启动myapp.jar并将其放在后台运行,同时也将输出信息保存到nohup.out文件中。要停止该应用程序,请使用kill命令。 总之,nohup java -jar命令使得Java应用程序可以在后台持续运行,并且不会被系统中断。它是一个非常有用的命令,可以为Java开发者提供方便和保障。 ### 回答3: nohup java -jar命令是Linux系统中常用的命令,它可以让我们在后台运行Java应用程序。下面对该命令进行详细解析: 1. nohup命令 nohup是No Hang Up的缩写,意思是不挂断。它的作用是让我们在后台运行命令时,即使断开终端连接,命令还是能够继续运行,直到执行完毕。 2. java -jar命令 java -jar命令是运行Java应用程序的命令,其中-jar参数表示运行一个打包的Java应用程序。使用该命令可以忽略classpath环境变量和-classpath命令行选项,方便我们打包和运行Java应用程序。 3. 组合使用 nohup java -jar命令的组合使用,可以让我们在后台运行Java应用程序,且即使断开终端连接,应用程序也能够继续运行。使用该命令时,需要指定Java应用程序的jar包路径,如下所示: nohup java -jar /path/to/app.jar & 其中,&表示将命令放入后台运行。 除了上述常见用法外,nohup java -jar命令还可以搭配其他命令使用,如结合grep命令对Java应用程序输出的日志进行过滤,或者使用tee命令将日志保存到文件中。 总之,nohup java -jar命令是在Linux系统中常用的命令,它能够在后台运行Java应用程序,并且即使断开终端连接,应用程序也能够继续运行,非常方便实用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香菜+

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值