1.static关键字
(1)可以修饰静态语句块
静态语句块是类加载的阶段就会执行,并且只执行一次,自上而下执行。
public class StaticTest {
/*静态语句块
*
*/
static{
System.out.println("1");
}
static{
System.out.println("2");
}
static{
System.out.println("3");
}
static{
System.out.println("4");
}
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
/*输出结果
1
2
3
4
Hello world!
*/
public class StaticTest {
/*静态语句块
*
*/
static{
System.out.println("A");
}
/*
* 实例语句块 每次调用构造方法之前执行,执行顺序也是自上而下
*/
{
System.out.println("1");
}
{
System.out.println("2");
}
{
System.out.println("3");
}
public StaticTest() {
System.out.println("我是构造方法");
}
public static void main(String[] args) {
new StaticTest();
new StaticTest();
}
}
/*
输出结果:
A
1
2
3
我是构造方法
1
2
3
我是构造方法
*/
(2)修饰的方法叫做“静态方法”
一般情况下,工具类中的方法绝大部分是静态方法,静态方法不用创建对象也能直接访问该方法。
public class StaticTest02 {
/*
* 成员方法
* 成员方法必须使用"引用."调用
*/
public void m1() {
System.out.println("我是成员方法");
}
/*
* 静态方法
* 可以使用“类名.” 方式调用,静态方法也可以使用"引用."访问,但是编译通过,真正执行的时候是使用"类名."的方法,该方法执行不需要对象。
* 静态方法中不能直接访问非静态数据
* 静态方法中不能使用this
*/
public static void m2() {
System.out.println("我是静态方法");
}
public static void main(String[] args) {
StaticTest02.m2();//也可以省掉类名,m2();
StaticTest02 staticTest02=new StaticTest02();
staticTest02.m1();
staticTest02.m2();//静态方法也可以使用"引用."访问,但是编译阶段检查处staticTest02是StaticTest02类型,编译通过,真正执行的时候是使用"类名."的方法,该方法执行不需要对象。
StaticTest02 a=null;
a.m2();//这里静态方法调用,不会报空指针异常,因为m2方法不是成员方法,是静态方法,即使引用是空,也不会报空指针异常。
}
}
(3)修饰的变量叫做“静态变量”
变量分类:局部变量、成员变量(实例变量、非静态变量)、静态变量(方法区存储)
静态变量在类加载的时候赋值,并且只赋值一次。同静态方法。
什么时候声明成静态变量?
如果这个属性所有对象都有,并且这个属性值是相同的,则该属性声明成静态属性。
public class StaticTest03 {//没用static情况下
/*
* 类{
* 成员变量
* 成员方法
*
* 静态变量
* 静态方法
*
* 静态语句块
* 实例语句块
*
* 构造方法
* this
* }
*/
public static void main(String[] args) {
Animal a1=new Animal("AAA", 10);
Animal a2=new Animal("BBB", 11);
}
}
// 抽象现实世界中的动物“陆生”动物
class Animal{
/*
* 成员变量(一个对象一份)
* 成员变量在创建对象的时候初始化,并且存储在堆中的每一个对象中
*/
String name;
int age;
String type="陆生";
Animal(String name,int age) {
this.name=name;
this.age=age;
}
}
public class StaticTest03 {//使用静态变量
public static void main(String[] args) {
Animal a1=new Animal("AAA", 10);
Animal a2=new Animal("BBB", 11);
//静态变量访问
System.out.println(a1.type);
System.out.println(a2.type);
}
}
// 抽象现实世界中的动物“陆生”动物
class Animal{
/*
* 成员变量(一个对象一份)
* 成员变量在创建对象的时候初始化,并且存储在堆中的每一个对象中
*/
String name;
int age;
/*
* 静态变量,被存储在方法区
* 所有的java对象共享这一份,
* 所以,静态变量是类级别,使用"类名."的方式访问
*/
static String type="陆生";
Animal(String name,int age) {
this.name=name;
this.age=age;
}
}
public class StaticTest04 {
static{
System.out.println(i);//编译不通过,非法向前引用
}
static int i=100;
public class StaticTest04 {
static int i=100;
static{
System.out.println(i);//编译通过
}
2.单例模式初步
注:单例模式最大缺点,无法被继承,因为其构造方法私有化。
(1)懒汉式(用到对象时才会创建对象)
类加载时候,初始化对象,默认为null,并且只初始化一次。调用方法的时候,赋值对象。
public class Singleton02 {
//提供一个当前类型的静态变量
private static Singleton02 singleton02;//类加载时候,赋值为null
//构造方法私有化
private Singleton02(){}
//提供一个公开静态方法,能够获取Singleton02对象
public static Singleton02 getSingleton02() {
if (singleton02==null){
singleton02=new Singleton02();//每调用时,才赋值对象,因此为懒汉式
}
return singleton02;
}
}
(2)饿汉式
类加载时候,初始化对象,并且只初始化一次。
/*目的:为了少的创建对象(只创建一次),减少内存开销
* 满足条件:
* 1.构造方法为私有.
* 2.对外提供一个公开静态方法,能够访问,获取当前类型对象
* 3.提供一个当前类型的静态变量
*/
public class Singleton {
private static Singleton sinleton=new Singleton();
private Singleton(){}
public static Singleton getSingleton(){
Singleton singleton_get=sinleton;
return singleton_get;
}
}
输出测试:
public class PrintTest {
public static void main(String[] args) {
Singleton s1=Singleton.getSingleton();
Singleton s2=Singleton.getSingleton();
Singleton s3=Singleton.getSingleton();
System.out.println(s1==s2);//true
System.out.println(s2==s3);//true
Singleton02 a1=Singleton02.getSingleton02();
Singleton02 a2=Singleton02.getSingleton02();
Singleton02 a3=Singleton02.getSingleton02();
System.out.println(a1==a2);//true
System.out.println(a2==a3);//true
}
}