一. 静态代码块
-
为什么要用静态代码块?
一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这些代码是自己主动执行的。看下面这个例子,这是一个jdis连接池,首先我必须先加载配置文件才能继续其他工作,为保证加载配置首先执行,而且静态代码块有一个作用就是随着类的加载而执行,而且只执行一次,我只需要在开始加载配置,而不需要每次操作时都加载配置
public class JedisPoolUtils {
private static JedisPool jedisPool;
static {
//读取配置文件
InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
//创建properties对象
Properties properties = new Properties();
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//获取数据,设置到JedisPoolConfig中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal")) );
config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle")) );
//初始化Jedispool
jedisPool = new JedisPool(config,properties.getProperty("host"),Integer.parseInt(properties.getProperty("port")) );
}
/**
* 获取连接的方法
*/
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
-
静态代码块和非静态代码块的区别
(1) 静态代码块,在虚拟机加载类的时候就会加载执行,而且只执行一次;
(2)非静态代码块,在创建对象的时候(即new一个对象的时候)执行,每次创建对象都会执行一次直接来看代码:
public class Static {
//构造方法
public Static(){
System.out.println("构造方法--");
}
//非静态代码块
{
System.out.println("非静态代码块--");
}
//静态代码块
static {
System.out.println("静态代码块--");
}
public static void test(){
System.out.println("静态方法的代码块--");
}
}
public class TestStatic {
public static void main(String[] args) {
Static p1 = new Static();
p1.test();
System.out.println("-----------");
Static p2 = new Static();
p2.test();
}
}
输出结果:
可以看到,静态代码块只执行了一次,而且是在最开始就执行的,非静态代码块,在每次创建对象时都会执行。
执行顺序为:
* 静态代码块-->非静态代码块-->构造方法-->方法
* 非静态代码块-->构造方法-->方法
-
在父类有静态代码块怎么办?
(1)首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后.
(2)再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后.
(3)它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块,子类的非静态代码块执行完毕再去执行子类的构造方法。总结: 静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。
二. 静态修饰符static
-
静态修饰符的作用
不需要实例化对象就可以引用成员,最基本的有Integer.parseInt(),Float.parseFloat()等等用来把对象转换为所需要的基本数据类型,这样的变量和方法我们又叫做类变量和类方法。 -
静态修饰符为什么可以直接拿类名引用?
在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员。但是静态方法在类加载的时候就随着一起加载了,是最先执行的,相当于一个不需要实例化的类。
- 被static修饰后的变量的值的问题
被static修饰后的成员,在编译时由内存分配一块内存空间,直到程序停止运行才会释放,那么就是说该类的所有对象都会共享这块内存空间
package Static_value;
public class TStatic{
//静态变量
static int i;
//无参构造方法
public TStatic(){
i = 4;
}
//有参构造
public TStatic(int j){
i = j;
}
public static void main(String args[]){
TStatic t = new TStatic(5); //声明对象引用,并实例化
TStatic tt = new TStatic(); //同上
System.out.println(t.i);
System.out.println(tt.i);
System.out.println(t.i);
}
}
结果输出:4,4,4
分析:这段代码里面Tstatic类有一个static的int变量I,有两个构造函数,第一个用于初始化I为4,第二个用于初始化i为传进函数的值,在main中所传的值是5,程序首先声明对象的引用t,然后调用带参数的构造函数实例化对象,此时对象t的成员变量I的值为5,接着声明对象tt,调用无参数的构造函数,那么就把对象tt的成员变量i的值初始化为4了,注意了,在这里i是static,那就是说该类的所有对象都共享该内存,那也就是说在实例化对象tt的时候改变了i的值,那么实际上对象t的i值也变了,因为实际上他们引用的是同一个成员变量。最后打印的结果是三个4。
用static修饰的,它会在内存中单独放在一块内存中,跟变量,对象不是在一块内存中。在程序运行的时候就加载好,当程序结束的时候才会释放内存。所以用static修饰的,就可以直接用 类名.方法名 就出来了,因为程序运行的时候就加载好这个方法了就不用再new一个对象去访问这个方法了。
- 静态变量和成员变量之间的区别?
(1)两个静态方法,可以直接互相调用
(2)两个普通方法,可以直接互相调用
(3)普通方法可以调用静态方法
(4)静态方法却只能访问静态成员
(5)普通方法 可以 对象.方法
(6)静态方法 则是 类.方法
生命周期
静态变量随类的加载而加载,随类的销毁而销毁
成员变量随对象的加载而加载,随对象的销毁而销毁
调用方式不同
一个是类调用,一个是对象调用
存储的位置不同
静态变量存储在静态区,而成员变量保存在堆里
- 为什么被staic修饰的方法只能访问静态成员?
因为静态方法在类加载的时候就随着一起加载了,此时其他成员和方法并没有初始化,换个理解 static 属于类,而普通成员和方法属于对象,对象不一定相同,因此static方法里不能用 super和this。