static 关键字详解java
final关键字主要用在三个地方:变量、方法、类。函数
static 关键字主要有如下四种使用场景:性能
类名.静态变量名
类名.静态方法名()
import static
这两个关键字连用能够指定导入某个类中的指定静态资源,而且不须要使用类名调用类中静态成员,能够直接使用类中静态成员变量和成员方法。this关键字用于引用类的当前实例。 例如:测试
class Manager { Employees[] employees; void manageEmployees() { int totalEmp = this.employees.length; System.out.println("Total employees: " + totalEmp); this.report(); } void report() { } }
在上面的示例中,this关键字用于两个地方:优化
此关键字是可选的,这意味着若是上面的示例在不使用此关键字的状况下表现相同。 可是,使用此关键字可能会使代码更易读或易懂。this
super关键字用于从子类访问父类的变量和方法。 例如:spa
public class Super { protected int number; protected showNumber() { System.out.println("number = " + number); } } public class Sub extends Super { void bar() { super.number = 10; super.showNumber(); } }
在上面的例子中,Sub 类访问父类成员变量 number 并调用其其父类 Super 的 showNumber()
方法。
使用 this 和 super 要注意的问题:
super()
调用父类中的其余构造方法时,该语句必须处于构造器的首行,不然编译器会报错。另外,this 调用本类中的其余构造方法时,也要放在首行。简单解释一下:
被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中全部对象共享。而 this 表明对本类对象的引用,指向本类对象;而 super 表明对父类对象的引用,指向父类对象;因此, this和super是属于对象范畴的东西,而静态方法是属于类范畴的东西。
被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中全部对象共享,能够而且建议经过类名调用。被static 声明的成员变量属于静态成员变量,静态变量 存放在 Java 内存区域的方法区。
方法区与 Java 堆同样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,可是它却有一个别名叫作 Non-Heap(非堆),目的应该是与 Java 堆区分开来。
HotSpot 虚拟机中方法区也常被称为 “永久代”,本质上二者并不等价。仅仅是由于 HotSpot 虚拟机设计团队用永久代来实现方法区而已,这样 HotSpot 虚拟机的垃圾收集器就能够像管理 Java 堆同样管理这部份内存了。可是这并非一个好主意,由于这样更容易遇到内存溢出问题。
调用格式:
若是变量或者方法被 private 则表明该属性或者该方法只能在类的内部被访问而不能在类的外部被访问。
测试方法:
public class StaticBean { String name; 静态变量 static int age; public StaticBean(String name) { this.name = name; } 静态方法 static void SayHello() { System.out.println(Hello i am java); } @Override public String toString() { return StaticBean{ + name=' + name + ''' + age + age + '}'; } }
public class StaticDemo { public static void main(String[] args) { StaticBean staticBean = new StaticBean(1); StaticBean staticBean2 = new StaticBean(2); StaticBean staticBean3 = new StaticBean(3); StaticBean staticBean4 = new StaticBean(4); StaticBean.age = 33; StaticBean{name='1'age33} StaticBean{name='2'age33} StaticBean{name='3'age33} StaticBean{name='4'age33} System.out.println(staticBean+ +staticBean2+ +staticBean3+ +staticBean4); StaticBean.SayHello();Hello i am java } }
静态代码块定义在类中方法外, 静态代码块在非静态代码块以前执行(静态代码块—非静态代码块—构造方法)。 该类无论建立多少对象,静态代码块只执行一次.
静态代码块的格式是
static { 语句体; }
一个类中的静态代码块能够有多个,位置能够随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,若是静态代码块有多个,JVM将按照它们在类中出现的前后顺序依次执行它们,每一个代码块只会被执行一次。
静态代码块对于定义在它以后的静态变量,能够赋值,可是不能访问.
静态内部类与非静态内部类之间存在一个最大的区别,咱们知道非静态内部类在编译完成以后会隐含地保存着一个引用,该引用是指向建立它的外围类,可是静态内部类却没有。没有这个引用就意味着:
Example(静态内部类实现单例模式)
public class Singleton { 声明为 private 避免调用默认构造方法建立对象 private Singleton() { } 声明为 private 代表静态内部该类只能在该 Singleton 类中被访问 private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getUniqueInstance() { return SingletonHolder.INSTANCE; } }
当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 getUniqueInstance()
方法从而触发 SingletonHolder.INSTANCE
时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,而且 JVM 能确保 INSTANCE 只被实例化一次。
这种方式不只具备延迟初始化的好处,并且由 JVM 提供了对线程安全的支持。
格式为:import static
这两个关键字连用能够指定导入某个类中的指定静态资源,而且不须要使用类名调用类中静态成员,能够直接使用类中静态成员变量和成员方法
Math. --- 将Math中的全部静态资源导入,这时候能够直接使用里面的静态方法,而不用经过类名进行调用 若是只想导入单一某个静态方法,只须要将换成对应的方法名便可 import static java.lang.Math.; 换成import static java.lang.Math.max;具备同样的效果 public class Demo { public static void main(String[] args) { int max = max(1,2); System.out.println(max); } }
静态方法属于类自己,非静态方法属于从该类生成的每一个对象。 若是您的方法执行的操做不依赖于其类的各个变量和方法,请将其设置为静态(这将使程序的占用空间更小)。 不然,它应该是非静态的。
Example
class Foo { int i; public Foo(int i) { this.i = i; } public static String method1() { return An example string that doesn't depend on i (an instance variable); } public int method2() { return this.i + 1; Depends on i } }
你能够像这样调用静态方法:Foo.method1()
。 若是您尝试使用这种方法调用 method2 将失败。 但这样可行:Foo bar = new Foo(1);bar.method2();
总结:
相同点: 都是在JVM加载类时且在构造方法执行以前执行,在类中均可以定义多个,定义多个时按定义的顺序执行,通常在代码块中对一些static变量进行赋值。
不一样点: 静态代码块在非静态代码块以前执行(静态代码块—非静态代码块—构造方法)。静态代码块只在第一次new执行一次,以后再也不执行,而非静态代码块在每new一次就执行一次。 非静态代码块可在普通方法中定义(不过做用不大);而静态代码块不行。
通常状况下,若是有些代码好比一些项目最经常使用的变量或对象必须在项目启动的时候就执行的时候,须要使用静态代码块,这种代码是主动执行的。若是咱们想要设计不须要建立对象就能够调用类中的方法,例如:Arrays类,Character类,String类等,就须要使用静态方法, 二者的区别是 静态代码块是自动执行的而静态方法是被调用的时候才执行的.
Example
public class Test { public Test() { System.out.print(默认构造方法!--); } 非静态代码块 { System.out.print(非静态代码块!--); } 静态代码块 static { System.out.print(静态代码块!--); } public static void test() { System.out.print(静态方法中的内容! --); { System.out.print(静态方法中的代码块!--); } } public static void main(String[] args) { Test test = new Test(); Test.test();静态代码块!--静态方法中的内容! --静态方法中的代码块!-- }
当执行 Test.test();
时输出:
静态代码块!--静态方法中的内容! --静态方法中的代码块!--
当执行 Test test = new Test();
时输出:
静态代码块!--非静态代码块!--默认构造方法!--
非静态代码块与构造函数的区别是: 非静态代码块是给全部对象进行统一初始化,而构造函数是给对应的对象初始化,由于构造函数是能够多个的,运行哪一个构造函数就会创建什么样的对象,但不管创建哪一个对象,都会先执行相同的构造代码块。也就是说,构造代码块中定义的是不一样对象共性的初始化内容。