【Java基础】内部类
非静态内部类不能拥有静态变量 为什么
下面这段代码,如果Lazyholder没有static修饰,则编译不过
class Singleton2 {
private static class LazyHolder {
private static Singleton2 singleton;
}
public Singleton2 getInstance() {
return LazyHolder.singleton;
}
}
"非静态内部类不能拥有静态变量" ,可以这样理解,因为JVM类加载的顺序为:
java根据需要在运行时把字节码载入到内存,它分三个步骤:
1、加载:类加载器查找到字节码(.class文件)并根据这些字节码创建一个Class对象;
2、链接:验证类中的字节码,为静态域分配存储空间,需要的话同时解析这个类其它类的所有引用;
3、初始化:当类的静态方法(构造器是特殊的静态方法)或者非常数静态域(即不是编译器常量)被首次引用时,执行静态初始化块和初始化静态数据。
然后才能执行对象创建
如果LazyHolder没有static,则本质上,它其实是Singleton2的非静态成员,则他必须在Singleton2对象创建之后才会进行加载,然而问题在于,另一方面根据JVM的加载顺序,static 的singleton变量又必须在LazyHolder对象存在之前完成加载,这就矛盾了。
靠,上面的是昨天写的,今天突然看不懂了。我想了想,更简单的理解是:
静态变量是要能够直接用类名.静态变量的方式来访问的,在上面这个例子中,实际上就是Singleton2.LazyHolder.singleton,是这样去访问,但是如果LazyHolder不是静态类,那问题就来了,你会发现singleton无法被访问了!因为Singleton.LazyHolder就已经不合法了,根本没法往下走。嗯,我觉得我自己的理解比网上查到的靠谱多了
什么是匿名内部类
实际上匿名内部类是对下面这种写法的简化
public class InnerClassLearn {
class MyThread extends Thread {
private int i = 11;
public int value() {return i;}
}
public Thread thread() {return new MyThread();}
public static void main(String[] args) {
Thread thread = new InnerClassLearn().thread();
}
}
用匿名内部类的方式重写上面的代码:
public class InnerClassLearn {
public Thread thread() {
return new Thread() {
private int i = 11;
public int value() {return i;}
};
}
public static void main(String[] args) {
Thread thread = new InnerClassLearn().thread();
}
}
其中红色部分就是一个继承于 Thread类的匿名内部类
【Java基础】内部类的更多相关文章
- 第30节:Java基础-内部类
内部类 // 外部类 class Demo{ private int num = 3; // 定义内部类 class Int{ void show(){ System.out.println(&quo ...
- Java 基础 内部类
Java 基础 内部类 内部类(嵌套类) nested class 目的为外围类enclosing class提供服务. 四种: 静态成员类 static member class 非静态成员类 no ...
- JAVA基础——内部类详解
JAVA内部类详解 在我的另一篇java三大特性的封装中讲到java内部类的简单概要,这里将详细深入了解java内部类的使用和应用. 我们知道内部类可分为以下几种: 成员内部类 静态内部类 方法内部类 ...
- Java基础-内部类-为什么局部和匿名内部类只能访问局部final变量
先看下面这段代码: public class Test { public static void main(String[] args) { } public void test(final int ...
- Java基础-内部类-为什么成员内部类可以无条件访问外部类
在此之前,我们已经讨论过了成员内部类可以无条件访问外部类的成员,那具体究竟是如何实现的呢?下面通过反编译字节码文件看看究竟.事实上,编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面 ...
- Java基础-内部类
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类. 下面就先来了解一下这四种内部类 ...
- Java基础内部类、包的声名、访问修饰符、代码块整理
内部类 14.1内部类概念 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类.其他类也称为外部类. 内部类分为成员内部类与局部内部类. 我们定义内部类时,就 ...
- Java基础-内部类介绍
java内部类介绍 内部类一共分为4种 成员内部类 静态内部类 方法内部类 匿名内部类 下面我会为大家详细介绍每一个内部类!! 成员内部类 成员内部类就好像是外部类的一个成员属性,也是内部类中最常见的 ...
- Java基础—内部类(转载)
转载自:java中的匿名内部类总结 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部 ...
- Java基础——内部类
一.什么是内部类 将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类 内部类所在的类在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$In ...
随机推荐
- Fuel9.0部署
一.安装环境(准备工作): 1. 所需物理主机的要求如下 内存:8GB+,推荐16GB:(少于8GB的就免谈了) 磁盘:500GB+: 物理机OS:ubuntu-desktop-amd64 14.04 ...
- VMware主机使用无线上网
VMware主机使用无线上网,默认的NAT连接在ubuntu下上不了网,需要把网络适配器改成桥接模式.
- Ubuntu下Cmake编译C++程序Helloworld
1.首选新建工程目录 mkdir helloworld 2.新建文件目录 cd helloworld mkdir bin mkdir lib mkdir src mkdir include mkdir ...
- Lambda学习总结(一)--函数式接口
Lambda 表达式是 JDK 1.8 里面的一个重要更新,这意味着 Java 也开始承认了函数式编程,并且尝试引入其中,我们今天就来了解下它的使用. 一.函数式接口 1.1 概念 函数式接口在 Ja ...
- Linux下lazarus交叉编译 win32[win64]
环境 vmvare + deepin Linux64 + lazarus2.0.6 参考:https://wiki.freepascal.org/Cross_compiling_for_Win32_u ...
- 创建一个Django项目
创建一个django项目: 1. django-admin startproject student_manage(项目名) 2. cd student_manage python manage.p ...
- redis 日志等级说明
redis loglevel 安装默认的设置为 verbose 1)debug:会打印出很多信息,适用于开发和测试阶段 2)verbose(冗长的):包含很多不太有用的信息,但比debug要清晰一些 ...
- mysql LAST()函数 语法
mysql LAST()函数 语法 作用:返回指定的字段中最后一个记录的值. 语法:SELECT LAST(column_name) FROM table_name 注释:可使用 ORDER BY 语 ...
- SpringBoot项目中,表单的验证操作
在创建Springboot项目中,我们使用了表单验证操作,这一操作将极大地简化我们编程的开发 1.接收数据,以及验证 @PostMapping("/save") public Mo ...
- CF191C Fools and Roads - 树剖解法
Codeforces Round #121 (Div. 1) C. Fools and Roads time limit per test :2 seconds memory limit per te ...