Java的static修饰符

Posted 飞鱼的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java的static修饰符相关的知识,希望对你有一定的参考价值。

本文主要介绍:静态域、静态常量、静态方法、工厂方法。

静态域

如果将域定义为 static,每个类中只有一个这样的域。而每一个对象对于所有的实例域却都有自己的一份拷贝。例如,假定需要给每一个雇员赋予唯一的标识码。这里给 Employee 类添加一个实例域 id 和一个静态域 nextld:

class Employee 
	private static int nextId = 1;
	private int id;

现在,每一个雇员对象都有一个自己的 id 域,但这个类的所有实例将共享一个 nextId 域。换句话说,如果有 1000 个 Employee 类的对象,则有 1000 个实例域 id。但是,只有一个静态域 nextld。即使没有一个雇员对象,静态域 nextld 也存在。静态域它属于类,而不属于任何独立的对象。

静态常量

静态变量使用得比较少,但静态常量却使用得比较多。例如,在 Math 类中定义了一个静态常量:

public class Math 
	public static final double PI = 3.14159265358979323846;

在程序中,可以采用 Math.PI 的形式获得这个常量。

如果关键字 static 被省略,PI 就变成了 Math 类的一个实例域。需要通过 Math 类的对象访问 PI,并且每一个 Math 对象都有一份它自己的 PI 拷贝。


另一个多次使用的静态常量是 System.out。它在 System 类中声明:

public class System 
	public static final PrintStream out = ...;

由于每个类对象都可以对公有域进行修改,所以,最好不要将域设计为 public。然而,公有常量(即 public static final 域)却没问题。 因为 out 被声明为 final,所以不允许再将其他打印流赋值给 out。

静态方法

静态方法是一种不能向对象实施操作的方法。例如,Math 类的 pow() 方法就是一个静态方法。表达式 Math.pow(x, a) 计算幂 xa。在计算时不使用任何 Math 对象。换句话说,没有隐式的参数。

可以认为静态方法是没有 this 参数的方法(在一个非静态的方法中,this 参数表示这个方法的隐式参数。)


Employee 类的静态方法不能访问 id 实例域,因为它不能操作对象。但是,静态方法可以访问自身类中的静态域。下面是使用这种静态方法的一一个示例:

public static int getNextId() 
	return nextId; // returns static field

可以通过类名调用这个方法:int n = Employee.getNextId();


在下面两种情况下使用静态方法:

  • 一个方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如:Math.pow())
  • 一个方法只需要访问类的静态域(例如:Employee.getNextId())

Java 中的静态域与静态方法在功能上与 C++ 相同。但是,语法书写上却稍有所不同。在 C++ 中,使用 :: 操作符访问自身作用域之外的静态域和静态方法,如 Math::PI。

工厂方法

静态方法还有另外一种常见的用途。类似 LocalDate 和 NumberFormat 的类使用静态工厂方法(factory method)来构造对象。你已经见过工厂方法 LocalDate.now() 和 LocalDate.of()。

NumberFormat 类如下使用工厂方法生成不同风格的格式化对象:

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();
NumberFormat percentFormatter = NumberFormat.getPercentlnstance();

double x = 0.1;
System.out.println(currencyFormatter.format(x)); // prints $0.10
System.out.println(percentFomatter.format(x)); // prints 10%

为什么 NumberFormat 类不利用构造器完成这些操作呢?这主要有两个原因:

  • 无法命名构造器。构造器的名字必须与类名相同。但是,这里希望将得到的货币实例和百分比实例采用不用的名字。
  • 当使用构造器时,无法改变所构造的对象类型。而 Factory 方法将返回一个 DecimalFormat 类对象,这是 NumberFormat 的子类。

参考资料

《Java核心技术卷一:基础知识》(第10版)第 4 章:对象与类 4.4 静态域与静态方法

Java面向对象_static修饰符

2018-04-29

树欲静而风不止 

 

static修饰符

 

static修饰符表示静态的,该修饰符可以修饰字段、方法、内部类使用该关键字修饰的内容,在面向对象中static修饰的内容是隶属于类,而不是直接隶属于对象的,所以static修饰的成员变量一般称作类成员变量,而static修饰的方法一般称作类方法。

 

static修饰符的特点:

  1)static修饰的成员(字段/方法),随着所在类的加载而加载。

    当JVM把字节码加载进JVM的时候,static修饰的成员已经在内存中存在了。

  2)优先于对象的存在。

    对象是我们手动通过new关键字创建出来的。

  3)satic修饰的成员被该类型的所有对象所共享。

    根据该类创建出来的任何对象,都可以访问static成员。

      分析:表面上通过对象去访问static成员,其本质依然使用类名访问,和对象没有任何关系(通过反编译可以看到)。

  4)直接使用类名访问static成员 。

    因为static修饰的成员直接属于类,不属于对象,所以可以直接使用类名访问static成员。

 

类成员和实例成员的访问

  1)类成员:使用static修饰的成员。

  2)实例成员:没有使用static修饰的成员。

  3)static方法中,只能调用static成员。无法从静态上下文中引用非静态变量

  4)非static方法可以访问静态成员,也可以访问实例成员。

  -----------------------------------------------------------------------------------

  类成员只能访问类成员,实例成员只能访问实例成员

  -----------------------------------------------------------------------------------

  类成员直接属于类,可以通过类来访问static字段和static方法。

  实例成员只属于对象,通过对象来访问非static字段和非static方法(对象其实可以访问类成员,但是底层依然使用类名访问的)。

 

静态与非静态的区别:

(1)

非静态成员变量又称为实例变量。

静态成员变量又称为类变量。 

(2)

非静态成员变量,随着对象的创建而存在,随着对象的消失而消失。

静态成员变量,随着类的加载而存在,随着类的消失而消失。

(3)

非静态变量存在于对象堆内存中。

静态变量存在于方法区中。

(4)

非静态变量只能被对象所调用。

静态变量可以被类名调用,也可以被对象调用。 

 

 

什么时候定义成static的字段和方法:

  如果这个一个状态或行为属于整个事物(类),就直接使用static修饰,被所有对象所共享。 在开发中,往往把工具方法使用static修饰。如果不使用static修饰,则这些方法属于该类的对象,我们得先创建对象再调用方法,在开发中工具对象只需要一份即可,可能创建N个对象,此时我们往往把该类设计为单例的,但还是有点麻烦。所以,一般在开发中设计工具方法,为了调用简单,我们使用static修饰。

 

static成员在JVM中的存储:

代码举例:

 1 class Person
 2     {
 3         String name;//名字
 4         int age;//年纪
 5 
 6         static int totalNum = 5;//人类总人数5
 7 
 8         //构造函数
 9         Person(String n, int a){
10             name = n;//将n赋给name
11             age = a;//将a赋给age
12             totalNum++;
13         }
14 
15         void die(){
16             totalNum--;
17             System.out.println("死亡");
18         }
19 
20         //只有人类才有毁灭
21         static void destory(){
22             totalNum = 0;
23             System.out.println("人类毁灭");
24         }
25     }
26 
27 
28 //演示static修饰符
29 class PersonDemo2
30 {
31     
32         public static void main(String[] args) 
33         {
34             System.out.println(Person.totalNum);
35             Person p1 = new Person("张三",10);
36             Person p2 = new Person("李四",5);
37             System.out.println(Person.totalNum);//使用类调用对象
38 
39             p2.die();//p2死亡
40             System.out.println(Person.totalNum);
41 
42             Person.destory();
43             System.out.println(Person.totalNum);
44     }
45 }

 

 

输出结果:

 

以上是关于Java的static修饰符的主要内容,如果未能解决你的问题,请参考以下文章

java面向对象之static修饰符

java final .static修饰符

Java常用的修饰符关键字

[Java基础]final和static修饰符

Java修饰符 abstract,static,final 的区别详解

访问修饰符与可选修饰符static的使用