原文网址:Java--static--用法/使用位置/实例_IT利刃出鞘的博客-CSDN博客
简介
本文用示例介绍Java中的static的用法。
使用位置包括:修饰成员属性,修饰成员方法,修饰代码块,修饰内部类,静态导包。
用法1:修饰成员属性
说明
给属性加了static关键字之后,对象就不再拥有该属性了,该属性会由类去管理,即多个对象只对应一个属性。
使用场景
一般用于定义一些常量。
示例:
package com.example.a;
class Test{
public static String NAME = "Tony";
}
public class Demo {
public static void main(String[] args) {
System.out.println(Test.NAME);
}
}
执行结果
Tony
用法2:修饰成员方法
说明
方法本来就是存放在类的定义当中的。static修饰成员方法的作用是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗。
示例:
package com.example.a;
class Test{
public static void sayHello(String name) {
System.out.println("Hello," + name);
}
}
public class Demo {
public static void main(String[] args) {
Test.sayHello("Tony");
}
}
结果
Hello,Tony
用法3:修饰代码块
static { }就是静态块,当类加载器载入类的时候,这一部分代码被执行,常用于对静态变量进行初始化工作。当其他代码用到这个类,类加载器才会将它载入。
代码只能执行一次,不能再调用。在静态块中,可以访问静态变量,调用静态方法。
如果去掉static,{ }中的代码则会在创建类对象的时候才执行,(相当于把这部分代码复制到各个构造函数中),这样可以实现块中的内容在多个构造函数中的复用。
package com.example.a;
class Test{
static {
System.out.println("This is static Block");
}
{
System.out.println("This is Block");
}
public Test(){
System.out.println("This is Test()");
}
public Test(String string){
System.out.println("This is Test(String string)");
}
}
public class Demo {
public static void main(String[] args) {
System.out.println("------------------------");
Test test1 = new Test();
System.out.println("------------------------");
Test test2 = new Test("Hello");
}
}
执行结果
------------------------
This is static Block
This is Block
This is Test()
------------------------
This is Block
This is Test(String string)
用法4:修饰内部类
static不能修饰普通类,但可以修饰内部类。原因如下:
static修饰的东西被我们成为类成员,它会随着类的加载而加载,比如:静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等。若把一个Class文件中的外部类设为static,那目的何在呢?难道让这个类随着应用的启动而加载吗?如果我在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。
为什么内部类可以使用static修饰呢,因为内部类算是类的成员了,如果我们没有使用静态来修饰,那么我们在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。
实例:
单例模式的静态内部类写法(Java设计模式--单例模式--使用/详解/实例_IT利刃出鞘的博客-CSDN博客)
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
public class Demo{
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton);
}
}
用法5:静态导包
导入时,使用static关键字,而且在引入类的最后还加上了“.*”,它的作用就是将PrintHelper类中的所有类方法直接导入。不同于非static导入,采用static导入包后,在不与当前类的方法名冲突的情况下,无需使用“类名.方法名”的方法去调用类方法了,直接可以采用"方法名"去调用类方法,就好像是该类自己的方法一样使用即可。
/* PrintHelper.java文件 */
package com.dotgua.study;
public class PrintHelper {
public static void print(Object o){
System.out.println(o);
}
}
import static com.dotgua.study.PrintHelper.*;
public class Demo{
public static void main( String[] args )
{
print("Hello World!");
}
}
static加载顺序
首先思考,下边程序是否能编译通过?若可以编译通过,那么执行结果是什么?
package com.example.a;
class User{
private static String name;
public void setName(String name) {
this.name = name;
}
public static String getName() {
return User.name;
}
}
public class Demo {
public static void main(String[] args) {
new User().setName("Tony");
System.out.println(User.getName());
}
}
结果
Tony
从上述结果可见,实例对象可以访问访问类变量。
如果将setName改为static类型,则无法编译通过。static里边不能有this,这与类加载流程有关,见:JVM原理系列--类加载过程(有实例)_IT利刃出鞘的博客-CSDN博客