Java基础:static的理解(含义、用法及静态修饰的优先顺序)

简介: Java基础:static的理解(含义、用法及静态修饰的优先顺序)


前言:


在java的关键字中,static和final是两个我们必须掌握的关键字。不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。我们经常见到static,例如每个main方法都会被标记为static修饰符,下面我们先来了解一下static关键字及其用法。


static关键字


一、静态域


如果将域(属性)定义为static,每个类中只有一个这样的域。而每一个对象对于所有的实例却都有自己的一份拷贝。


例如:假定需要给每一个雇员赋予唯一的标志码。这里给Employee类添加一个实例域id和一个静态域nextId。


代码示例:


class Employee{
  private static int nextId = 1;
  private int id;
  ...
}


 现在每个雇员都有一个自己的id域,但这个类的所有实例将共享一个nextId域。换句话说,如果有1000个Employee类的对象,则有1000个实例域id,但只有一个静态域nextId 。

我们从内存看一下原因:


20190306005507663.png


从内存理解可以清楚的看出static的作用,另外我们要知道,即使没有一个雇员对象,静态域nextId也已经存在。即它属于类,而不属于任何独立的对象,不属于实例。

static类型在实例化创建的时候不会新建,节省内存,但是有一个实例改变他的值,所以的实例里面都会对应修改,如果不想被修改,应该用final修饰。


二、静态常量

静态变量使用的比较少,但静态常量却使用得比较多。这里就不做赘述。


三、静态方法

   静态方法是一种不能向对象实施操作的方法。静态方法可以访问自身类中的静态域。


下面我们看代码1:


package practice6;
public class Employee3 {  
  static{
    System.out.println("这是静态初始化块1");
  }
  private static int nextId = 90;
  private int id;
  private String name = "巴啦啦";
  private double salary;
  {
    System.out.println("这是非静态初始化块:" + nextId + "==name:" + name);
    id = nextId;
    nextId++;
  } 
  static{
    System.out.println("这是静态初始化块2:" + nextId);    
  }
  public Employee3(String n ,double s) {
    name = n;
    salary = s;
  }
  public Employee3() {    
    System.out.println("这是构造方法");
    name = "";
    salary = 0;
  } 
}
package practice6;
public class Test4 {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Employee3 a = new Employee3();  
  }
}


运行结果:

20190306015330478.png


解释:


这里我们似乎可以看到,静态初始化块都先输出了,因为被static修饰,即使没有实例化对象,也已经存在,但是静态初始化块修饰的无论是什么情况下都会优先输出吗???目前的代码似乎是这个意思。


下面我们再看一下更改的代码2:


实例化一个静态方法Employee3,其他不变


package practice6;
public class Employee3 {  
  static{
    System.out.println("这是静态初始化块1");
  }
  private static int nextId = 90;
  private int id;
  private String name = "巴啦啦";
  private double salary;
  //我们在这里实例化了一个静态Employee3方法
  private static Employee3 as32 = new Employee3();
  {
    System.out.println("这是非静态初始化块:" + nextId + "==name:" + name);
    id = nextId;
    nextId++;
  } 
  static{
    System.out.println("这是静态初始化块2:" + nextId);    
  }
  public Employee3(String n ,double s) {
    name = n;
    salary = s;
  }
  public Employee3() {    
    System.out.println("这是构造方法");
    name = "";
    salary = 0;
  } 
}


运行结果:

20190306021427360.png

这里我们发现并不是所有被static修饰的都会优先输出,为什么???


解释:

首先我们看到运行结果,第一行静态初始化块1在函数的最顶部,所以优先加载出来,然后第二、三行加载的静态初始化块和构造方法,第四行开始实际是加载实例化静态方法Employee3的,由于static修饰的只会加载一次,所以static修饰的尽量会在实例化静态方法Employee3中才加载靠后输出。


下面我们再看一下更改的代码3:

在static修饰的方法里面实例化一个Employee3,其他不变

package practice6;
public class Employee3 {  
  static{
    System.out.println("这是静态初始化块1");
    Employee3 as = new Employee3(); //改变所在行
  }
  private static int nextId = 90;
  private int id;
  private String name = "巴啦啦";
  private double salary;
  private static Employee3 as32 = new Employee3();  
  {
    System.out.println("这是非静态初始化块:" + nextId + "==name:" + name);
    id = nextId;
    nextId++;
  } 
  static{
    System.out.println("这是静态初始化块2:" + nextId);    
  }
  public Employee3(String n ,double s) {
    name = n;
    salary = s;
  }
  public Employee3() {    
    System.out.println("这是构造方法");
    name = "";
    salary = 0;
  } 
}

运行结果:

20190306022613489.png

解释:

这里我们只解释一下为什么第一个输出的非静态初始化块的nextId 值为0,我们明明给nextId 赋值为90了啊。

这就是受static修饰的不论被实例化多少次,只会加载一次的影响,我们是这样定义的:private static int nextId = 90; 既然nextId 被static修饰,那么执行as 方法的时候会先跳过去执行非静态方法,所以调用nextId 时,会使用nextId 的默认值,int的默认值是0。


总结


Java中static的含义和用法:

static:静态的,用于修饰成员(成员变量,成员方法);


1.被static所修饰的变量或者方法会储存在数据共享区;


2.被static修饰后的成员变量只有一份!


3.当成员被static修饰之后,就多了一种访问方式,除了可以被对象调用之外,还可以直接

被类名调用,(类名.静态成员);


4.static的特点:

a.随着类的加载而被加载;

b.优先于对象存在;

c.被所有对象共享;


5.被static修饰的变量成为静态变量(类变量)或者实例变量;


6.存放位置

a.类变量随着类的加载而存在于date内存区;

b.实例变量随着对象的建立而存在于堆内存;


7.生命周期:

a.类变量周期生命最长,随着类的消失而消失;

b.实例变量生命周期比类变量短,它是随着对象的消失而消失;


8.方法注意事项:

a.静态的方法只能访问静态的成员;

b.非静态得方法即能访问静态得成员(成员变量,成员方法)又能访问非静态得成员;

c.局部变量不能被static修饰;

d.静态得方法中是不可以定义this、super关键字的,因为静态优先于对象存在,所以静态方法不可以出this;


9.什么时候使用static修成员:

当属于同一个类的所有对象出现共享数据时,就需要将存储这个共享数据的成员用static修饰;


10.什么时候使用static修饰方法:

当功能内部没有访问到非静态的成员时(对象特有的数据)那么该功能可以定义成静态的.


注意:


  1. 非静态的成员变量只能使用对象进行访问,不能使用类名进行访问。
  2. 千万不要为了方便访问数据而使用static修饰成员变量,只有成员变量的数据是真正需要被共享的时候才使用static修饰。


目录
相关文章
|
25天前
|
设计模式 JavaScript 前端开发
java中的static关键字
欢迎来到瑞雨溪的博客,博主是一名热爱JavaScript和Vue的大一学生,致力于全栈开发。如果你从我的文章中受益,欢迎关注我,将持续分享更多优质内容。你的支持是我前进的动力!🎉🎉🎉
47 8
|
2月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
87 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
1月前
|
存储 Java
Java 中的静态(static)
【10月更文挑战第15天】静态是 Java 语言中一个非常重要的特性,它为我们提供了一种方便、高效的方式来管理和共享资源。然而,在使用过程中,我们需要谨慎考虑其优缺点,以确保代码的质量和可维护性。
|
2月前
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。
|
2月前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
36 3
|
2月前
|
Java 编译器
在Java中,关于final、static关键字与方法的重写和继承【易错点】
在Java中,关于final、static关键字与方法的重写和继承【易错点】
27 5
|
3月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
2月前
|
Java
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
这篇文章详细解释了Java中static和final关键字的用法,包括它们修饰类、方法、变量和代码块时的行为,并通过代码示例展示了它们的具体应用。
233 0
Java关键字 —— static 与 final 详细解释!一看就懂 有代码实例运行!
|
3月前
|
存储 Java
Java之静态(static)与实例(instance)
Java之静态(static)与实例(instance)
|
3月前
|
Java
Java 正则表达式高级用法
Java 中的正则表达式是强大的文本处理工具,用于搜索、匹配、替换和分割字符串。`java.util.regex` 包提供了 `Pattern` 和 `Matcher` 类来高效处理正则表达式。本文介绍了高级用法,包括使用 `Pattern` 和 `Matcher` 进行匹配、断言(如正向和负向前瞻/后顾)、捕获组与命名组、替换操作、分割字符串、修饰符(如忽略大小写和多行模式)及 Unicode 支持。通过这些功能,可以高效地处理复杂文本数据。
59 10