static关键字有哪些作用
1.修饰成员变量
可以通过类名.变量名直接引用,而不需要new出一个类来,static修饰的成员被所有的对象共享,static是不允许用来修饰局部变量。
成员变量和静态变量的区别:
1.生命周期的不同:
成员变量随着对象的创建而存在随着对象的回收而释放。
静态变量随着类的加载而存在随着类的消失而消失。
2.调用方式不同:
成员变量只能被对象调用。
静态变量可以被对象调用,也可以用类名调用。(推荐用类名调用)
3.别名不同:
成员变量也称为实例变量。
静态变量称为类变量。
4.数据存储位置不同:
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
2.修饰成员方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。
使用注意:
1.静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)
2.静态方法中不可以使用this或者super关键字。
3.主函数是静态的。
3.静态块
随着类的调用或创建实例而执行,而且只执行一次。
作用:
用于给类进行初始化。
4.静态内部类
在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。
作用:
- 更好的封装性
- 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,但外部类不能访问内部类的实现细节,例如内部类的成员变量
- 匿名内部类适合用于创建那些仅需要一次使用的类
静态内部类与非静态内部类的差异:
1.非静态内部类中不允许定义静态成员
2.外部类的静态成员不可以直接使用非静态内部类
3.静态内部类,不能访问外部类的实例成员,只能访问外部类的类成员
举例:
public class Outer {
private String name;
private int age;
public static class Builder {
private String name;
private int age;
public Builder(int age) {
this.age = age;
}
public Builder withName(String name) {
this.name = name;
return this;
}
public Builder withAge(int age) {
this.age = age;
return this;
}
public Outer build() {
return new Outer(this);
}
}
private Outer(Builder b) {
this.age = b.age;
this.name = b.name;
}
}
静态内部类调用外部类的构造函数,来构造外部类,由于静态内部类可以被单独初始化说有在外部就有以下实现:
public Outer getOuter()
{
Outer outer = new Outer.Builder(2).withName("Yang Liu").build();
return outer;
}
如果类的构造器或静态工厂中有多个参数,设计这样类时,最好使用Builder模式,特别是当大多数参数都是可选的时候。如果现在不能确定参数的个数,最好一开始就使用构建器即Builder模式。
5.接口静态方法
java8中为接口新增了一项功能:定义一个或者更多个静态方法。用法和普通的static方法一样。
public interface InterfaceA {
/**
* 静态方法
*/
static void showStatic() {
System.out.println("InterfaceA++showStatic");
}
}
public class Test {
public static void main(String[] args) {
InterfaceA.show();
}
}
注意:实现接口的类或者子接口不会继承接口中的静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用。
6.静态导包(import static)
不同于非static导入,采用static导入包后,在不与当前类的方法名冲突的情况下,无需使用“类名.方法名”的方法去调用类方法了,直接可以采用"方法名"去调用类方法,就好像是该类自己的方法一样使用即可。
特点:
1.简化了一些操作,比如静态导入Math下的所有静态资源,在频繁使用Math类下静态资源的地方,可以少些很多“Math.”
2.但是降低了代码的可读性
static底层原理
这是一个简化版的内存解释,Java的内存包含了栈、堆和静态存储区,栈主要是存放对象的应用,堆是放对象,而静态存储区主要是放一些方法和常量。那么,如果我们有以下的对象:
public class Person{
public String name;
public static Integer age;
}
public class Main{
public static void main(String[] args) {
Person person = new Person();
person.name = "wusicheng";
person.age = 18;
}
}
那么他们在内存当中的分配情况如下图所示:
注意name
和age
存储位置的不同,name
是存储存储到堆上面的,和对象绑定在一起,而age
是Person类进行管理的,存储在静态存储区上面,不论建立多少个对象,都只指向这个一个地方。在类加载的时候,静态存储区中的内容已经初始化完成,所以在内存当中就只有这一份。