静态/非静态 方法/变量的写法

大家应该都明白静态方法/字段比普通方法/字段的写法要多一个static关键字,简单写下他们的写法吧,了解的可以直接略过

class Test{
// 静态变量
public static int id = 1;
// 普通变量
public int usualId = 2;
// 静态常量
public static final int finalNextId = 3;
// 静态方法
public static void A(){
// 静态方法只能访问静态字段,不能访问非静态字段
System.out.println("this is static function A!");
}
// 普通方法
public void B(){
// 普通方法可以访问静态字段和非静态字段
System.out.println("this is usual function B!");
}
}

  

静态变量

静态变量(带有static关键字的字段)是属于类的,所有该类的对象共用该字段;
非静态变量(普通字段)是属于类的对象的,每一个该类的对象都有自己的非静态字段,他们互不影响。

class Test{
// 静态变量
public static int id = 1;
// 普通变量
public int usualId = 2;
}
class TestA{
// 对于静态字段,不实例化类(即创建对象)就可使用
Test.id; // 对于普通字段,Test.usualId 就会报错
// 对于普通字段,需要先实例化类
Test test = new Test();
test.usualId; // 不会报错
}

  

静态方法

静态方法与普通方法的区别,与静态字段与普通字段的区别类似
静态方法是不在对象上执行的方法,在调用静态方法时,不需要实例化该类而调用普通方法必须实例化该类。

class Test{
// 静态方法
public static void A(){
// 静态方法只能访问静态字段,不能访问非静态字段
System.out.println("this is static function A!");
}
// 普通方法
public void B(){
// 普通方法可以访问静态字段和非静态字段
System.out.println("this is usual function B!");
}
}
class TestA{
// 对于静态方法,不实例化类(即创建对象)就可调用
Test.A(); // 对于普通字段,Test.B()就会报错
// 对于普通方法,需要先实例化类
Test test = new Test();
test.B(); // 不会报错
}

  

可以了解下Java中类的生命周期,就能知道为什么访问静态方法/字段不需要实例化类而访问非静态的方法/字段需要实例化类
静态字段/方法在类的连接阶段就存在了,几乎可以理解为类存在,静态字段/方法就存在;
非静态字段/方法在类初始化后(new 类名)才会存在,也就是对象存在后,非静态字段/方法才会存在。

类的生命周期

此部分几乎搬运了“三级小野怪”的文章,参考链接:https://blog.csdn.net/zhengzhb/article/details/7517213

当我们编写一个Java源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在Java虚拟机中运行,Java类的声明周期就是指一个class文件从加载到卸载的全过程。

一个Java类的完整的生命周期会经历加载,连接,初始化,使用,卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况。

jvm中的几个重要的内存区域

方法区:专门用来存放已经加载的类信息,常量,静态变量以及方法代码的内存区域
常量池:是方法区的一部分,主要用来存放常量和类中的符号引用等信息;
堆区:存放类的对象实例
栈区:也叫Java虚拟机栈,由一个个的栈帧组成的后进先出的栈式结构,存放方法运行时产生的局部变量,方法出口等信息。当调用一个方法时,虚拟机栈就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法调用了其他方法,则继续在栈顶创建新的栈帧。

加载

在加载阶段,Java虚拟机会找到需要加载的类,并把类信息放到jvm的方法区中,然后堆中实例化。
是类的生命周期中的第一个阶段,加载阶段之后是连接阶段,但是有时连接阶段并不会等加载阶段完成之后才开始,而是交叉进行,可能一个类只加载了一部分之后,连接阶段就已经开始了。但是两个阶段总的开始时间和完成时间总是固定的:加载阶段总在连接阶段之前开始,连接阶段总是在加载阶段完成之后完成。

连接

连接阶段主要任务是做一些加载后的验证工作以及一些初始化前的准备工作

验证:当一个类被加载会后,验证类是否合法,比如这个类的变量与方法是不是有重复,数据类型是否有效等,目的是保证加载的类能够被jvm所运行。
准备:为类的静态变量分配内存并设为jvm默认的初始值,非静态变量则不分配内存。需要注意的是,这时候静态变量的初值是jvm默认的初始值而不是我们再程序中设定的初值。jvm默认的初值是这样的:
1.基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
2.引用类型的默认值为null。
3.常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。
解析

初始化

如果一个类被直接引用就会触发类的初始化,直接引用的情况有:

通过new关键字实例化对象,读取或设置类的静态变量,调用类的静态方法
通过反射执行以上三种行为
初始化子类的时候,会触发父类的初始化
作为程序入口直接运行时(也就是直接调用main方法)
除了以上四种情况,其他使用类的方法叫做被动引用,被动引用不会触发类的初始化
主动引用代码示例

class InitClass{
static {
System.out.println("初始化InitClass")
}
public static String a = null;
public static void method(){}
}
class SubInitClass extends InitClass{} public class Test1{
public static void main(){
// 主动引用引起类的初始化:new 对象、读取或者是类的静态变量,调用类的静态方法
new InitClass();
InitClass.a = "";
String a = InitClass.a;
InitClass.method(); // 主动引用引起类的初始化,通过反射实例化对象,读取或设置类的静态变量,调用类的静态方法
Class cls = InitClass.class;
cls.newInstance();
Field f = cls.getDeclaredField("a");
f.get(null);
f.set(null,"s");
Method md = cls.getDeclaredMethod("method");
md.invoke(null, null); // 主动引用引起类的初始化,实例化子类
new SubInitClass();
}
}

  

初始化过程:按照顺序自上而下运行类中的变量赋值语句和静态语句,如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。
在初始化阶段,只会初始化与类相关的静态赋值语句和静态语句,也就是有static关键字修饰的信息,而没有static修饰的赋值语句和执行语句在实例化对象时才会运行

使用
类的使用包括主动引用和被动引用,主动引用上面说过了,下面主要说下被动引用

引用父类的静态字段,只会引起父类的初始化,而不会引起子类的初始化;
定义类数组,不会引起类的初始化;
引用类的常量,不会引起类的初始化。
被动引用代码示例

class InitClass{
static{
System.out.println("初始化InitClass");
}
public static String a = null;
public final static String b = "b";
public static void method(){}
} class SubInitClass extends InitClass{
static {
System.out.println("初始化SubInitClass");
}
} public class Test4 {
public static void main(String[] args) throws Exception{
// String a = SubInitClass.a;// 引用父类的静态字段,只会引起父类初始化,而不会引起子类的初始化
// String b = InitClass.b;// 使用类的常量不会引起类的初始化
SubInitClass[] sc = new SubInitClass[10];// 定义类数组不会引起类的初始化
}
}

  

卸载

如果满足下面的情况,类就会被卸载:

该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
加载该类的ClassLoader已经被回收。
该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

深度分析:Java 静态方法/变量,非静态方法/变量的区别,今天一并帮你解决!的更多相关文章

  1. java中静态方法和非静态方法调用的一点小困扰,已解决。

    public static void main(String[] args) { // TODO Auto-generated method stub SimpleGui1B gui=new Simp ...

  2. Java中堆、栈,静态方法和非静态方法的速度问题

           一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储 ...

  3. Java中synchronized用在静态方法和非静态方法上面的区别

    synchronized 修饰在 static方法和非static方法的区别   在Java中,synchronized是用来表示同步的,我们可以synchronized来修饰一个方法.也可以sync ...

  4. 在java中静态方法与非静态方法

    在java中public void与public static void有什么区别 ? public void 修饰是非静态方法,该类方法属于对象,在对象初始化(new Object())后才能被调用 ...

  5. 【JVM】深度分析Java的ClassLoader机制(源码级别)

    原文:深度分析Java的ClassLoader机制(源码级别) 为了更好的理解类的加载机制,我们来深入研究一下ClassLoader和他的loadClass()方法. 源码分析 public abst ...

  6. 转 C#中静态方法与非静态方法区别比较

    C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用 ...

  7. 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)

    写在前面: Java SE5 提供了一种新的类型 Java的枚举类型,关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能 ...

  8. 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题

    原文:深度分析Java的枚举类型--枚举的线程安全性及序列化问题 枚举是如何保证线程安全的 要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和clas ...

  9. C#静态类 静态方法与非静态方法比较

    静态类 在类(class)上加入static修饰,表示该类无法被实例化,并将该类中,无法实例化变量或函数 静态类的主要特性 仅包含静态成员 无法实例化 静态类的本质,时一个抽象的密封类,所以不能被继承 ...

  10. [转]C#静态方法与非静态方法的比较

    http://wenku.baidu.com/view/4e1704084a7302768e9939e0.html C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他 ...

随机推荐

  1. mybatis 架构及基础模块

    1. mybatis整体架构 基础支撑层详解 1.日志模块 mybatis日志模块没有实现类,需要接入第三方的组件,问题是第三方的组件有各自的log级别,为了能接入第三方组件,mybati日志模块定义 ...

  2. RocketMQ 4.7.1 环境搭建、集群、MQ整合SpringBoot

    导读 之前学过ActiveMQ但是并发量不是很大点我直达,所以又学阿里开源的RocketMQ,据说队列可以堆积亿级别.下面是网上找的消息队列对比图,仅供参考 部署 官网 点我直达 前置条件 推荐使用6 ...

  3. ubuntu18 ssh服务器拒绝连了密码

    问题 xshell 远程连接ubuntu时 解决方法 参考:链接 网上的kenghuo太多!!! 1.如果没有安装ssh服务,请先安装 sudo apt-get install openssh-ser ...

  4. javascript中的描述对象(Descriptor)

    对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为.Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象. 获取对象中属性描述对象 Ob ...

  5. D. Road to Post Office 解析(思維)

    Codeforce 702 D. Road to Post Office 解析(思維) 今天我們來看看CF702D 題目連結 題目 略,請直接看原題. 前言 原本想說會不會也是要列式子解或者二分搜,沒 ...

  6. Java安全之Commons Collections7分析

    Java安全之Commons Collections7分析 0x00 前言 本文讲解的该链是原生ysoserial中的最后一条CC链,但是实际上并不是的.在后来随着后面各位大佬们挖掘利用链,CC8,9 ...

  7. Java学习的第二十七天

    1.内存操作流 缓冲流 用BufferedReader读取数据 使用BufferedWriter写数据 使用BufferInputStream和BufferOutputStream读写图片 2.有很多 ...

  8. python机器学习实现K-近邻算法(KNN)

    机器学习 K-近邻算法(KNN) 关注公众号"轻松学编程"了解更多. 以下命令都是在浏览器中输入. cmd命令窗口输入:jupyter notebook 后打开浏览器输入网址htt ...

  9. uniapp微信小程序获取当前用户手机号码(前端)

    按钮触发获取用户信息 uniapp中与微信小程序官网所写会不同, <button open-type="getPhoneNumber" @getphonenumber=&qu ...

  10. Python列表lists索引关于字符串小纪

    看的出'字符串列表'中的空格也是计算在内的