static & final关键字
文章目录
1.static关键字
static
是java中一个常见关键字,是一个修饰符,可以使用static
修饰类(内部类),修饰方法,修饰属性,修饰初始化块。被static
修饰的元素则与对象无关,与类直接相关,即需要使用这些元素,只需要通过类名访问即可(无需创建对象)。这些元素也有一些特定的名词:
- 类变量
- 类方法
1.1. 类变量
所谓类变量即静态变量,使用static
修饰的成员变量即为类变量,类变量与对象已经没有关系了,变量的数据值有类进行控制,是一个所有对象都共享的变量,只要有其中一个对象将其修改,所有对象看到都是相同的值,语法:
static 数据类型 变量名
例如:
static int i = 10;
static String str;
类变量的初始化时间是在类加载时就初始化,而非创建对象时
类变量,成员变量,局部变量生命周期?
- 当对象中的成员方法执行完毕时,方法内部的局部变量会被回收
- 当对象使用完毕时,GC清理对象,同时将对象中申请的成员变量空间清理
- 最后当JVM结束时,才清理
static
变量
1.2. 类方法
所谓类方法即静态方法,使用static
修饰成员方法,被修饰的方法与对象无关,在访问该方法时,只需要通过类名称即可方法,无需创建对象调用,语法:
[<访问修饰符>] static 返回值类型 方法名([<参数列表>]){
//执行体
}
例如:
public static void add(int a,int b){
return a + b;
}
调用类方法时分为两种情况
在当前类直接调用,直接使用
方法名()
调用即可在其他类中访问当前类静态方法,
类名称.方法名()
调用Math.random() Arrays.sort(); Arrays.binearySearch();
注意事项
- 不能在静态方法中使用非静态的成员,除非通过对象访问(成员变量,成员方法)
成员对象实例
常见的类和类方法
Java中对于一些工具类经常会将其方法定义为静态的:
- java.util.Arrays
- java.lang.Math
- java.util.Collections
- …
对于
static
的使用不能滥用,因为static
成员会常驻内存,只有JVM结束时才会随之销毁,所以会带来一定空间消耗影响程序的执行效率.
1.3. 初始化块与静态初始化块
在一个Java类中主要由以下几个部分构成:
- 属性
- 方法
- 构造方法
除了以上一些常见的元素之外,一个类中还允许使用一种特殊的语句块:初始化块
初始化块
初始化块又称游离块,是一个没有名称的代码块,执行时间一般在创建对象执行构造器前先执行,并且执行次数取决于对象的创建次数,作用于将多个构造器中的重复代码提取到一起统一执行.
静态初始化
静态初始化块也称之为静态块,即使用static
关键字对初始化块进行修饰,一旦类被加载,则立即执行静态块,并且,静态不会随着对象的创建而反复执行,只会执行一次;
静态块一般作用于无论创建多少对象,只需要执行一次的需求,例如数据库驱动的加载:
static{
Class.forName("com.mysql.jdbc.Driver");
}
比如Object类的registerNatives
private static native void registerNatives();
static {
registerNatives();
}
观察以下代码,查看执行顺序
public class Test { private String name; int i; int j; int k; static{ System.out.println("静态初始化块"); } //初始化块 { i = j = k =10; System.out.println("初始化块执行。。。"); } public Test(){ System.out.println("无参构造器执行"); } public Test(String name){ this.name = name; System.out.println("有参构造器"); } public static void main(String[] args) { new Test("hello"); new Test(); } }
运行结果:
静态初始化块 初始化块执行。。。 有参构造器 初始化块执行。。。 无参构造器执行
注:
- 静态初始化块无论创建多少次,只会执行一次
- 初始化块会随对象的创建次数而执行对应次
1.4. 设计模式之-singleton(单例模式)
1.4.1. 设计模式概述
设计模式是一种源自于早期建筑行业的工程化技术,在计算机软件行业也引入这种概念,设计模式即在多年软件领域的技术迭代过程中,衍生出的一些用于解决某些特定问题的解决方案。
java中常见的设计模式分为23种:
- 创建模式
- 单例模式
- 结构模式
- 代理模式
- 适配模式
- 桥接模式
- 行为模式
- 模板方法模式
单例模式:
单例模式即单个实例模式也称之单态,单子模式;在程序的运行过程中无论如何创建对象,始终只存在一个实例,这种模式称为单例模式;一句话解释单例:无论何时获得的对象永远是同一个对象
1.4.2.饿汉式
饿汉式是单例模式中的一种以空间换时间的创建方式,后续需要使用当前对象时,只需要通过方法返回即可:
public class People {
private static People people = new People();
//构造器私有化,防止外加随意访问
private People(){
}
//提供一个static方法用于返回当前类的对象
public static People newInstance(){
return people;
}
}
1.4.3. 懒汉式
懒汉式与饿汉式相反,是一种以时间换空间创建方式,类加载时不会创建对象,只有当调用方法时才会选择创建:
public class User {
private static User user;
private User(){}
public static User newInstance(){
//当调用当前方法时,检查对象是否存在
//若不存在则创建
if(user == null){
user = new User();
}
return user;
}
}
1.4.4. 应用场景
JDK中提供了一个与本机环境交互的类java.lang.Runtime
,该类的实现就是基于单例模式(饿汉式),实现代码如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class <code>Runtime</code> are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the <code>Runtime</code> object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
//...
}
使用Runtime类可以直接与本机环境交互,比如开启应用程序,执行window命令等:
public class RuntimeDemo {
public static void main(String[] args) throws IOException {
//JDK内置的一个java类,用于与本机环境交互的类
Runtime r = Runtime.getRuntime();
// r.exec("calc"); //启动计算器
// r.exec("mspaint"); //启动画图板
//执行关机命令 300秒
// r.exec("shutdown -s -t 300");
for (int i = 0; i < 5; i++) {
r.exec("C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQScLauncher.exe");
}
}
}
static
关键字总结
- 使用static修饰属性,方法
- 使用与初始化语句块:静态块
- 使用static构建单例模式
- 使用static可以修饰内部类(缓存数据)
2.final关键字
final
关键字,表示最终,不可更改的意思,是一个修饰符,可以用于修饰类,修饰属性,修饰方法,修饰局部变量:
- 被final修饰的类不可被继承(断子绝孙类)
- 被final修饰的变量不可被修改(一般和static组很使用,用于定义常量)
- 被final修饰的方法不能被重写
- 被final修饰的局部变量可以被延长使用生命周期,不会随着方法的执行结束而清理,而是跟使用他的语句块生命周期一致(内部类)
public final class Supermen {
/**常量*/
static final String NAME = "kobe";
final int i;
public Supermen(int i){
this.i = i;
}
public final void changeName(String name){
final int k = 10;
// k = 20;
}
}