static 关键字在java语言中的特性

一,将自己注入到一个静态变量中实现静态类,如下写法

以上方法的目的是要实现一个静态类,方便用类名获取对象实例,一般情况下调用普通方法需要对象实例.这对象要么new出来,要么spring的注入如下是spring注入对象,

将对象赋值给一个静态变量后,则可以用类名先调用该类变量获取实例,再调用方法.

一般情况下static不能直接在类名前修饰,但是静态内部类可以,因此static也用于静态内部类
以下代码是内部类的作用域
/**
* 1,内部类一般只为其外部类使用;
* 2,内部类提供了某种进入外部类的窗户;
* 3,每个内部类都能独立的继承一个接口,而无论外部类是否已经继承了某个接口,因此内部类使得多重继承得以实现
* @Author jisen
* @Date 2019/3/5 14:30
*/
public class OutClass extends ClassB {
//常量,类变量,普通变量
private static final Object OUTREFERENCECONSTANT = new Object();//外部常量
private static Object outStaticRefField = new Object();//外部类变量
private Object outField = new Object();//外部普通变量
//外部类方法
public void outmethod(){}//外部普通方法
public static void outstaticmethod(){}//外部静态方法
//静态内部类可继承可实现
static class InnerStaticClass extends ClassA implements ClassC{
private static final Object INREFERENCECONSTANT2 = new Object();//静态内部类常量
private static Object inStaticRefField = new Object();//静态内部类,类变量
private Object inField = new Object();//静态内部类普通变量
//静态内部类的静态方法只能访问静态内外成员
public static void innerStaticClassMethod(){
//outmethod();
//innerClassMethod();
outstaticmethod();
innerStaticClassMethod();
System.out.println(OUTREFERENCECONSTANT);
System.out.println(INREFERENCECONSTANT2);
System.out.println(outStaticRefField);
System.out.println(inStaticRefField);
//System.out.println(outField);
//System.out.println(inField);
}
////静态内部类的普通方法只能访问外部静态成员,以及内部所有成员
public void innerClassMethod(){
//outmethod();//静态方法不能访问外部非静态方法
innerClassMethod();
outstaticmethod();
innerStaticClassMethod();
System.out.println(OUTREFERENCECONSTANT);
System.out.println(INREFERENCECONSTANT2);
System.out.println(outStaticRefField);
//System.out.println(outField);
System.out.println(inField);
}
}
//普通内部可继承可实现
class InnerClass extends ClassA implements ClassC{
private final Object INREFERENCECONSTANT3 = new Object();//可以定义不可变量
//private static final Object INREFERENCECONSTANT4 = new Object();//无法定义常量
//private static Object inStaticRefField2 = new Object();//不可定义类变量
private Object inField2 = new Object();//可定义普通变量
//普通内部类只能有普通方法,可访问外部类的所有成员
public void innerMethod(){
System.out.println(OUTREFERENCECONSTANT);
System.out.println(outStaticRefField);
System.out.println(outField);
}
//public static void innerMethod2(){}
}
}
内部类的使用方法
/**
* @Desc 内部类的使用
* @Author jisen
* @Date 2019/3/5 14:34
*/
public class TestStatic {
public void method(){
//通过外部类对象所能到达的所有操作
OutClass outClass = new OutClass();
outClass.outmethod();
OutClass.InnerClass innerClass = outClass.new InnerClass();
innerClass.innerMethod();
//通过外部类名所能达到的操作
OutClass.outstaticmethod();//访问外部公共静态成员
OutClass.InnerStaticClass.innerStaticClassMethod();//访问公共静态成员,再访问静态成员内部的静态成员
//静态内部类对象,静态内部类可以不通过外部实例对象,直接new产生
OutClass.InnerStaticClass innerStaticClass = new OutClass.InnerStaticClass();
innerStaticClass.innerClassMethod();//用静态内部类实例对象访问成员
//普通静态内部类,需要外部类的实例对象
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
innerClass1.innerMethod();
}
}
二,static用于单例
//饿汉式,静态常量,类加载的时候在准备阶段这个常量就分配了内存并赋值,
//始终只有一个实例,避免了线程安全问题
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
//饿汉式静态代码块,原理跟静态常量一样,在类加载的准备阶段赋初值null,
//初始化阶段执行<client>(),实例化对象并赋值给静态成员
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
//静态内部类,本质上跟第一种是一样的,内部类常量,在类加载的准备阶段就实例化了.
//只有一份避免了线程竞争产生多分
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
类加载的过程:
1,加载是jvm类加载器通过一个类的全限定名获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,并在内存中
生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口.
2,验证,语法,以及class文件的验证
3,准备阶段,
类变量分配内存地址并设置类变量初始值阶段,
类变量分配内存地址并设置类变量初始值阶段,
类变量分配内存地址并设置类变量初始值阶段
重话三,类变量就是被static修饰的变量,不包含普通实例变量,普通实例变量会在对象实例化的时候随着对象一起分配在java堆中,比如 public static int value=123;它
在准备阶段的初始值是0而不是123,因为准备阶段尚未执行任何java方法,而把value赋值为123的putstatic指令时程序被编译后存放于类构造器<client>()方法中,执
行java方法是在初始化阶段.各类型的零值,int 0,long 0L,short (short)0,char '\u0000',byte (byte)0,boolean false,float 0.0f,double 0.0d,reference null
如果是public static final Object value=new Object();这个类字段还被final修饰被定义为ConstantValue,所以常量在准备阶段就被赋值new Object()的内存地址
4解析阶段,将常量池中的符号引用替换为直接引用的过程
5,初始化,在准备阶段类变量已经赋值过一次系统要求的初值,而初始化阶段则将执行类构造器<client>()方法,这个不是类的构造函数,<client>()方法是由编译器
自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的,其顺序是由语句在源文件中出现的顺序所决定的.所以static修饰的语句块或者类变量,如
果他们先后对一个值赋值那取决于最后赋值的那个.其次<client>()方法执行之前会默认先执行父类的<client>()的方法,因此出现在父类的static修饰的类变量和静态
语句块会先执行.
本文通过注入静态变量,静态内部类,单例这三种应用场景来展示了static的使用特点,并详细描述jvm类加载过程,揭示static的内在逻辑
现在做如下总结
1,static是类级别的,被static修饰的变量叫类变量.可以不需要对象(this)访问,而能够通过类名直接访问
2,被static修饰的变量,常量,静态代码块,静态方法,静态类.他们的执行顺序如下分析:
a,基本数据类型静态常量在类加载的准备阶段就分配内存并赋值最终值,如int类型常量 OUTREFERENCECONSTANTINT=3
b,引用数据类型常量和类变量在类加载的准备阶段会赋初值,引用类型为null int为0如下图所示,并在类加载的初始化阶段执行<client>()方法会给它赋代码
值,idea能进入到debug模式表示类加载的初始化阶段调用<client>()方法
c.静态代码块,会在类加载的初始化阶段,也就是执行<client>()方法的时候执行,这个时候与引用数据类型常量类变量的赋值动作,根据代码先后顺序执行
d, 非静态类型的字段在类加载完成并且给对象分配内存的时候初始化.
e,说完了字段静内部态类,它只有在调用的时候才会被加载,就像正常类一样被加载,静态内部类的常量字段,类变量,初始化与正常类的字段一样一
f.静态方法只有在调用它的时候才会执行

文章首发地址:https://mp.weixin.qq.com/s?__biz=MzI4NTEzMjc5Mw==&mid=2650554779&idx=1&sn=1d08bcc184c9f4224af14a02d11059c5&chksm=f3f8330dc48fba1b7f87d1fe8487e9d8753cf0e9b8a9df23d6a1ab6f7215fa8845913431abf1&token=2005887224&lang=zh_CN#rd
公众号:

static 关键字在java语言中的特性的更多相关文章
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- Java语言中的面向对象特性:封装、继承、多态,面向对象的基本思想(总结得不错)
Java语言中的面向对象特性(总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知道jav ...
- Java语言中的面向对象特性
面向对象的基本特征 1.封装性 封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义: ◇ 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位( ...
- java 对象的this使用 java方法中参数传递特性 方法的递归
一.this关键字,使用的情形,以及如何使用. 1.使用的情形 类中的方法体中使用this --初始化该对象 类的构造器中使用this --引用,调用该方法的对象 2.不写this,调用 只要方法或 ...
- Java语言中的这些知识点有没有用过,工作中有没有入过这些坑?
在Java语言中,有一些相对生僻的知识,平时用的机会可能不是很多,但如果不了解不掌握这些知识点的话,也可能会掉入陷阱之中,今天我们就来初步梳理一下: 1. goto是java语言中的关键字. &quo ...
- JAVA语言中冒号的用法
近来由于本人要介入android平台的开发,所以就买了本JAVA语言的书学习.学习一段时间来,我的感觉是谭浩强就是厉害,编写的<C编程语言>系列丛书不愧是经典.书中对C语言的介绍既系统又全 ...
- IT兄弟连 Java语法教程 Java语言的其他特性
Java语言中除了非常重要的跨平台特性外,还有如下几个关键特性: ● 语法简单易学 Java语言的语法简单明了,容易掌握,而且是纯面向对象(OOP)的语言,Java语言的简单性主要体现在以下几个方面 ...
- Java语言中的异常处理
Java语言中的异常处理包括声明异常.抛出异常.捕获异常和处理异常四个环节. throw用于抛出异常. throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异 ...
- 列举java语言中反射的常用方法
package review;/*12:43 2019/7/21*/ import model.AnotherClass; import model.OneClassMore; import mode ...
随机推荐
- nexus 3.x最新版下载安装和上传下载jar
注意: nexus 3.x最新版好像不用下载索引了,目前我使用一些基本功能没有索引也能耍的很6 下载 nexus最新版下载https://www.sonatype.com/download-oss-s ...
- simplexml_load_string 转换xml为数组
php simplexml_load_string 函数可以很简单转换 xml 字符串为 SimpleXMLElement 对象 但是,对象的值不好取,例如: result => SimpleX ...
- [ ceph ] CEPH 部署完整版(CentOS 7 + luminous)
1. 前言 拜读了 胖哥的(el7+jewel)完整部署 受益匪浅,目前 CEPH 已经更新到 M 版本,配置方面或多或少都有了变动,本博文就做一个 ceph luminous 版本完整的配置安装. ...
- Centos7之阿里Arthas部署
阿里Arthas Arthas(阿尔萨斯)是Alibaba开源的一个Java诊断工具,无需做任何配置,就可以直观的获取各种维度的性能数据,方便开发者进行问题的定位和诊断. 应用场景 动态跟踪Java代 ...
- Caused by java.lang.Exception Failed to send data to Kafka Expiring
flink 写kafka,报错,作业挂掉 Caused by: java.lang.Exception: Failed to send data to Kafka: Expiring 89 recor ...
- mysql 连接远程阿里云数据库
一.修改mysql 数据库的远程访问权限 use mysql; SELECT HOST,user,PASSWORD FROM USER; -- 查询用户信息 UPDATE USER SET HOST= ...
- CentOS下安装Tomcat
CentOS版本:CentOS-7-x86_64-Minimal-1810 1.安装JDK 详情查看:CentOS下安装JDK-rpm文件.CentOS安装JDK-tar.gz文件 2.下载tomca ...
- [xsy3132]数表
题意:一个$n\times m$的数表,数值$\in[0,4)$,你可以任意次选择一行或一列$+1,\text{mod }4$,要最小化所有数的和 因为$n\leq10$,所以数表可以看成$m$个$n ...
- Servlet3.0对异步处理的支持
Servlet工作流程 Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下: Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理: 调用业务接口的某些方 ...
- Ribbon和Nignx的区别
Ribbon属于客户端负载均衡:在调用接口的时候,会通过服务别名到eureka上获取服务的信息列表,缓存到jvm本地,在本地采用RPC远程调用技术去调用接口,实现负载均衡.可以设置调用的规则是请求总数 ...