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

  以上方法的目的是要实现一个静态类,方便用类名获取对象实例,一般情况下调用普通方法需要对象实例.这对象要么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语言中的特性的更多相关文章

  1. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

  2. Java语言中的面向对象特性:封装、继承、多态,面向对象的基本思想(总结得不错)

    Java语言中的面向对象特性(总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知道jav ...

  3. Java语言中的面向对象特性

    面向对象的基本特征 1.封装性 封装性就是把对象的属性和服务结合成一个独立的相同单位,并尽可能隐蔽对象的内部细节,包含两个含义: ◇ 把对象的全部属性和全部服务结合在一起,形成一个不可分割的独立单位( ...

  4. java 对象的this使用 java方法中参数传递特性 方法的递归

    一.this关键字,使用的情形,以及如何使用. 1.使用的情形 类中的方法体中使用this  --初始化该对象 类的构造器中使用this --引用,调用该方法的对象 2.不写this,调用 只要方法或 ...

  5. Java语言中的这些知识点有没有用过,工作中有没有入过这些坑?

    在Java语言中,有一些相对生僻的知识,平时用的机会可能不是很多,但如果不了解不掌握这些知识点的话,也可能会掉入陷阱之中,今天我们就来初步梳理一下: 1. goto是java语言中的关键字. &quo ...

  6. JAVA语言中冒号的用法

    近来由于本人要介入android平台的开发,所以就买了本JAVA语言的书学习.学习一段时间来,我的感觉是谭浩强就是厉害,编写的<C编程语言>系列丛书不愧是经典.书中对C语言的介绍既系统又全 ...

  7. IT兄弟连 Java语法教程 Java语言的其他特性

    Java语言中除了非常重要的跨平台特性外,还有如下几个关键特性: ●  语法简单易学 Java语言的语法简单明了,容易掌握,而且是纯面向对象(OOP)的语言,Java语言的简单性主要体现在以下几个方面 ...

  8. Java语言中的异常处理

    Java语言中的异常处理包括声明异常.抛出异常.捕获异常和处理异常四个环节.   throw用于抛出异常.   throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异 ...

  9. 列举java语言中反射的常用方法

    package review;/*12:43 2019/7/21*/ import model.AnotherClass; import model.OneClassMore; import mode ...

随机推荐

  1. Operation之变换操作符

    buffer buffer方法的作用是缓冲组合, 第一个参数是缓冲时间, 第二个参数是缓冲个数, 第三个参数是线程 该方法简单来说就是缓存Observable中发出的新元素, 当元素达到某个数量, 或 ...

  2. springboot:非web启动

    需要运行一些调度任务,但是又不想放到web容器中运行. 见红色代码: import java.util.concurrent.ThreadPoolExecutor; import org.spring ...

  3. CentOS 7.7安装Erlang和Elixir

    安装之前,先看一下它们的简要说明 Erlang Erlang是一种开源编程语言,用于构建对高可用性有要求的大规模可扩展的软实时系统.它通常用于电信,银行,电子商务,计算机电话和即时消息中.Erlang ...

  4. vim设定Tab缩进长度

    在Linux系统中,vim是一款非常好用的文本编辑器,那么,如何在Linux下的vim编辑器设定Tab的缩进长度呢? Linux系统下,vim编辑器Tab键的默认长度为8个空格,在vim中可以通过修改 ...

  5. python的帮助信息的写法

    # coding = utf-8from optparse import OptionParserfrom optparse import OptionGroup usage = 'Usage: %p ...

  6. [转帖]技术人眼中的Facebook Libra

    技术人眼中的Facebook Libra https://www.jianshu.com/p/ddc733077749 比特币 以太坊 EOS Libra 0.8352019.07.01 14:15: ...

  7. Listener学习

    监听器Listener用于监听web应用中某些对象.信息的创建.销毁.增加,修改,删除等动作的发生,然后作出相应的响应处理.当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法.常用于统计 ...

  8. Java多线程编程(1)--Java中的线程

    一.程序.进程和线程   程序是一组指令的有序集合,也可以将其通俗地理解为若干行代码.它本身没有任何运行的含义,它只是一个静态的实体,它可能只是一个单纯的文本文件,也有可能是经过编译之后生成的可执行文 ...

  9. 树莓派搭建python环境服务器

    树莓派搭建python环境服务器 服务器结构大致为:django+uwsgi+nginx+python+sqlite 配置python环境 系统本身自带了python2.7和python3.5.在这里 ...

  10. John Lemon's Haunted Jaunt(鬼屋游戏笔记)

    1.使用Unity  2019.2.3 2.角色移动的控制脚本 3.后期处理组件PostProcessLayer  (类似给相机加上了一层滤镜) 4.制作简单的怪物AI系统,使用 NAvMeshAge ...