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

大家应该都明白静态方法/字段比普通方法/字段的写法要多一个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. Linux的外部命令的执行

    查看外部命令的路径 whereis 不但能显示出外部命令的路径还能显示出帮助文档 which -a |--skip-alias whereis

  2. Markdown--补充版

    markdown语法实例 markdown语法实例 强调 分割线 引用 标题Setext方式 大标题 小标题 标题Atx方式 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 无序列表 有序 ...

  3. Anderson《空气动力学基础》5th读书笔记 第4记——黏性流动入门

    目录 一.边界层的概念 二.边界层的产生原因 三.剪切力的公式 四.温度分布情况 五.雷诺数与层流.湍流 一.边界层的概念 我们先来介绍边界层的概念(边界层正是黏性流动的产物),边界层是紧挨物体的薄层 ...

  4. JavaScript正则表达式随笔

    概念先行. 正则表达式:又称规则表达式.常用于检索,替换符合某种符合(规则)的文本. 组成:普通字符和元字符,普通字符就是一个普通的查找串,如abc,原字符具有特殊含义. 这里研究的是JavaScri ...

  5. Mybatis---03Mybatis配置文件浅析(一)

    一.写入mybatis配置文件的约束 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE co ...

  6. JavaScript监听滚动条的进度条

    <style type="text/css"> *{ margin: 0; padding: 0; } .g-box{ width: 100%; height: 400 ...

  7. 虚拟化下Centos7 扩容根分区

    查看分区大小和挂载情况 用到的命令df.lsblk [root@localhost ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/ ...

  8. Java获取不到Canal服务器端数据问题汇总(坑人的东西)

    情况1:(基本都是这样的问题,) 1.需要修改canal.properties配置 vim conf/canal.properties canal.instance.parser.parallelTh ...

  9. Unknown CMake command

    Unknown CMake command "add_clang_library".等 在官网上照着打 发现上面错误 结果是版本问题 选好版本和选项catkin还是rosbuild

  10. Python练手项目实例汇总(附源码下载)

    今天给大家分享几个有趣的Python练手项目实例,希望对Python初学者有帮助哈~ 一.经典的俄罗斯方块   1. 绑定功能 1 # 绑定功能 2 class App(Frame): 3 def _ ...