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 ...
随机推荐
- 全文搜索引擎Elasticsearch详细介绍
我们生活中的数据总体分为两种:结构化数据 和 非结构化数据. 结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理.指具有固 ...
- EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案使用详情功能-通道配置Excel导入导出
使用EasyNVR的用户都有知道,由于EasyNVR是将设备与EasyNVR的通道进行绑定的,因此EasyNVR是通过手动的通道配置来进行设备接入的,这样可以做到将设备的和通道对应的接入.但是,如果手 ...
- 快速修改Windows系统密码命令
因现场需要,要对30多台虚拟机进行密码修改.正常修改方式为进入控制面板--用户账户--修改密码,输入原始密码.2遍新密码(一遍用于密码确认)完成密码修改. 这种方式操作较为繁琐,我们可以直接通过命令的 ...
- nginx添加sticky模块-cookie保持会话
cookie不同于session,一个存于客户端,一个存于服务端. 环境nginx 1.8.0 centos6.X sticky:1.2.5 wget https://bitbucket.org/n ...
- ArcGIS Server 10.2忘记用户名密码的解决方案
忘记了ArcGIS Server Manager的密码,可以采用以下方法进行重置. 1.找到ArcGIS Server的安装目录 D:\Program Files\ArcGIS\Server\tool ...
- Linux 就该这么学 CH02新手必须掌握的Linux命令
0 概述 本章内容如下 强大的shell. 帮助文档命令(1) 系统工作命令(10) 系统状态监测命令(8) 工作目录切换命令(3) 文本文件编辑命令(9) 文件目录管理命令(7) 打包压缩或搜索命令 ...
- 基于Livy的Spark提交平台搭建与开发
为了方便使用Spark的同学提交任务以及加强任务管理等原因,经调研采用Livy比较靠谱,下图大致罗列一下几种提交平台的差别. 本文会以基于mac的单机环境搭建一套Spark+Livy+Hadoop来展 ...
- LeetCode二叉树Java模板
public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } impor ...
- [译] QUIC Wire Layout Specification - Introduction & Overview | QUIC协议标准中文翻译(1) 简介和概述
本文同步发布于: https://www.pengrl.com/p/33330/ ,转载请注明出处,谢谢. 目录 Introduction | 简介 Conventions and Definitio ...
- RabbitMQ之消息模式(下)
目的: RabbitMQ之消息模式(上):https://www.cnblogs.com/huangting/p/11994539.html 消费端限流 消息的ACK与重回队列 TTL消息 死信队列 ...