认识java中的static
作者的废话:emm,早就想开始自己的博客生涯,不过只要一打开电脑,映入眼帘的就是一大堆杂乱的笔记,对于整理它们我是提不起丝毫的兴趣,奈何被生活所迫,只有开始我的第一篇杂文这样子来维持生活
注:下面代码中的 中文名称 纯属为了方便理解,实际开发中一般以驼峰命名法
再注:作者(也就是我)使用的jdk为1.8
如:String helloWorld = "你们真棒,若各位发现错误或者作者理解错误的地方,就联系或评论让我们一起变更好吧";
零、static修饰变量
0.0、static修饰的变量称为静态变量
0.1、static不能修饰局部变量
0.2、静态变量被所有对象共享
0.3、同一静态变量在内存中地址唯一,如下:
静态变量:
public static TestEntity 我是静态变量;
测试:
Test 我是测试1 = new Test();
Test 我是测试2 = new Test();
TestEntity 我引用了测试1中静态变量在内存中的地址 = 我是测试1.我是静态变量;
TestEntity 我引用了测试2中静态变量在内存中的地址 = 我是测试2.我是静态变量;
System.out.println(我引用了测试1中静态变量在内存中的地址 == 我引用了测试2中静态变量在内存中的地址);
System.out.println(我引用了测试1中静态变量在内存中的地址 == Test.我是静态变量);
System.out.println(我引用了测试2中静态变量在内存中的地址 == Test.我是静态变量);
测试结果:
虽然是从不同的对象调用但是它们引用着同一个内存地址
0.4、被static修饰的变量只有在类被加载时才被初始化(注:非静态变量是当对象被创建时才初始化)
扩展:内存分区(引用自 博客园作者:吃鱼尾的咩——java中静态变量在内存中的位置 - 吃鱼尾的咩 - 博客园)
而内存分为四个区:stack segment,heap segment,data segment,code segment;
stack 区存放函数参数和局部变量;heap 区存放对象;data 区存放static 的变量或者字符串常量
code 区存放类中的 方法。
一、static修饰方法
1.0、被static修饰的方法称为静态方法
1.1、在静态方法内部无this
1.2、在静态方法内调用非静态方法或者非静态变量,如下:
RunTest runTest = new RunTest();
runTest.我是非静态变量 = "我的电耗子比亚缩还快乐";
runTest.我是非静方法();
注:非静态方法或变量依赖于对象调用
1.3、在本类中可直接调用静态方法,在其他类中调用时需用 类名.方法 方式调用
public static void 调用静态方法() {
被调用的静态方法();
}
public static void 被调用的静态方法() {
}
1.4、我们都知道main方法是显示的用static修饰,那构造器是否是隐式的静态方法呢?
我谈一下我的理解:静态方法无this不能直接调用其他非静态,而构造器可以调用。故我认为构造器不是静态方法。
大家感兴趣可以再次去深究
扩展:
简谈new与构造器:new 构造器();
new:此表达式表示对象的创建。
构造器:对创建的对象进行初始化。
使用new 构造器();的方式创建对象,我理解为保证创建与初始化同时进行。
二、static修饰代码块
2.0、在类被加载时进行一次性执行,一个类中可有多个静态代码块,按静态代码块顺序执行
2.1、可用于进行类加载时的初始化,以达到避免浪费空间、提升程序性能的作用
如下:
private static BigDecimal fiveThousand;
static {
fiveThousand = new BigDecimal(5000);
}
public static boolean lessFiveThousand(BigDecimal wage) {
return wage.compareTo(fiveThousand) == -1 ? true:false;
}
不用每次调用此方法时都new一个BigDecimal对象(此处只是举例)
可能有朋友问为什么不像下面这样做:(我想说的是当实际开发中,为项目编写属于项目本身的工具类时当有许多需要类加载时初始化的变量时放到一个静态类中方便查看与管理)
private static BigDecimal fiveThousand=new BigDecimal(5000);
三、static修饰内部类
3.0、下面举一个effective java中的建造者模式中关于静态内部类的用法:
package lyy;
public class PasswordManager {
private final String id;
private final String account;
private final String password;
private final String salt;
private PasswordManager(Builder b){
id = b.id;
account = b.account;
password = b.password;
salt = b.salt;
}
public static class Builder{
private String id;
private String account;
private String password;
private String salt;
public Builder id(String val) {
id = val;
return this;
}
public Builder account(String val) {
account = val;
return this;
}
public Builder password(String val) {
password = val;
return this;
}
public Builder salt(String val) {
salt = val;
return this;
}
public PasswordManager build() {
return new PasswordManager(this);
}
}
}
此处使用静态内部类Builder的build()方法为PasswordManager创建实例
注:return this;只是为了链式调用
new PasswordManager.Builder().account("22").password("2233").salt("lyy").build()
对于静态内部类的用法作者接触较少,老歌们请允许我为广大程序员呼吁:
留下你们宝贵的经验财富吧。留下你们宝贵的经验财富吧。留下你们宝贵的经验财富吧。
四、static修饰import
4.0、静态导包我理解的好处就是节省代码(粗鄙的见解,哈哈)
导包:
import static java.lang.System.*; 或者
import static java.lang.System.out;
使用:
out.println("lyy");
作者结语:本想在最后分享一些开发经验,奈何我没有控制住自己....(别多想,肚子饭 要吃饿<._.>)
谈谈经验(谈一点和static相关的):
我相信大家都知道transient修饰符是为了不序列化某变量,那你要不要试试static呢
(建议实际开发或作业中别这么干,这会共享的哟亲,只是作为一个扩充知识点)?
谈到静态方法,不知道大家在使用spring开发项目时是否遇到循环引用的情况,大家若遇到此情况如何处理呢?
是否是利用注解@JsonIgnoreProperties来引用目标对象使它不序列化呢
如果你把此对象的get方法加上Static你会发现它竟然没有循环引用了
(建议最好别这么干,目前我并没有想出这样做的缺陷在哪儿,望大家指教。只是作为一个扩充知识点)
若你使用lombok或者希望ide自动帮我们生成get/set的话请往下看:
不知你们可否遇到当变量类型为boolean且变量名为isxxx的时候自动的get/set名如下:
protected boolean isNot;
public boolean isNot() {
return isNot;
}
public void setNot(boolean isNot) {
this.isNot = isNot;
}
具体原因,额....等我翻翻笔记,当我打开Typora一看,默默关了敲下后面的字:大哥大姐们东西在下面给你们了拿去用吧
(哈哈,笔记太乱:当然可能有朋友推荐我用搜索,哼我可以认真且负责的告诉你,我搜了,没 搜 到!!)
对于此我的解决办法为把基本类型boolean改为包装类Boolean就好了,不信你看(不要让我发现你怀疑是我手改的哟>_<坚决没有,不信你试):
protected Boolean isNot;
public Boolean getIsNot() {
return isNot;
}
public void setIsNot(Boolean isNot) {
this.isNot = isNot;
}