类(静态)变量和类(静态)static方法以及main方法、代码块,final方法的使用,单例设计模式
类的加载:时间
1、创建对象实例(new 一个新对象时)
2、创建子类对象实例,父类也会被加载
3、使用类的静态成员时(静态属性,静态方法)
一、static 静态变量:类变量,静态属性(会被该类的所有对象共享)
1、静态类变量可以根据类名共享,static类变量在类加载的时候就生成了
2、类变量是该类的所有对象共享的,而实例变量是每个对象共享的。
3、加上static称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量
4、类变量可以通过 类名。类变量名 或者 对象名。类变量名 来访问
5.类变量是在类加载时就初始化了,即使没有创建对象,只要类加载了,就可以使用类变量了了
6、类变量的生命周期是随类的加载开始,随着类的消亡而销毁。
二、静态方法(类)
1、当方法使用了static修饰后,该方法就是静态方法
2、静态方法就可以访问静态属性/变量
3、静态方法的使用:通常将一些通用的方法设计成静态方法,这样
我们不需要创建对象就可以使用了,比如打印一堆数组,冒泡排序,完成某个计算任务
4、类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:类方法中无this和super(对象方法)的参数
总结:静态方法只能访问静态成员;普通成员方法,既可以访问非静态成员,也可以访问静态成员
三、main方法
1、main方法是虚拟机调用,所以该方法的访问权限必须是public
2、java虚拟机在调用main方法时不必创建对象,所以该方法必须是public
3、该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数,传参时间(是在)执行程序时传递进去的。
四、代码块:
1、相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化操作
2、如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性
注意细节和详情:
(1):static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,执行一次。
(2)普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。
(3):创建一个对象时调用顺序:先静态代码块和静态属性在类加载时先调用,如果同时有多个静态属性和静态代码块,就会按照定义的先后顺序进行初始化和调用。再调用普通代码块和普通属性初始化,如果有多个,则按照顺序依次进行调用。最后调用构造方法。
(4):静态代码只能调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。
小结:static代码块是类加载时执行一次(只执行一次),代码块是在创建对象时调用的,创建一次,调用一次。
五:单例设计模式
单例模式的优点
系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
单例模式的使用场景
• 需要频繁的进行创建和销毁的对象;
• 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
• 工具类对象;
• 频繁访问数据库或文件的对象。
1、饿汉式:(弊端;可能创建了,但是没有被调用,出现资源的浪费)
步骤
(1):将构造器私有化
(2):在类的内部直接创建对象(该对象是static)
(3):提供一个公共的static方法,返回 该static对象;
public class TestSingle { /** * 创建一个不可改变的实例 */ private final static TestSingle TEST_SINGLE = new TestSingle(); private TestSingle() { }//构造器 public static TestSingle getInstance() {//只可通过这个方法获得该类的唯一一个实例 return TEST_SINGLE; } public void helloWorld(){ System.out.println("hello test single1"); } }
如图中代码,该类不能被实例化(生成对象),唯一的对象是本身自己实例好的静态对象,该对象只能被该类唯一的公共类调用。所以,不管怎么调用,该类始终只有一个对象;
2、懒汉式:
步骤
(1):构造器私有化
(2):定义一个static静态属性对象
(3):提供一个public的static方法,可以返回一个定义的对象
(4):只有当需要时,调用了public方法才会生成一个实例对象,当多次调用该
public方法时,每次返回的就是原来的那个对象;从而保证了单例
class TestSingle1{ /** * 创建一个静态的实例 */ private static TestSingle1 testSingle1; private TestSingle1() { } /** 判断是否已经存在该实例,存在就直接返回,不存在就new 一个实例对象 */ public static TestSingle1 getTestSingle1(){ if (testSingle1 == null) { testSingle1 = new TestSingle1(); } return testSingle1; } public void helloWorld(){ System.out.println("hello test single2"); } }
3、使用枚举类进行单例模式设计
public enum TestSingle2 { /** * 返回一个该对象的实例 */ INSTANCE; public void helloWord() { System.out.println("test single hello world3"); } }
对以上三种单例设计模式进行测试:
public class Test1 extends Test implements TestHello{ public static void main(String[] args) { TestSingle instance = TestSingle.getInstance(); instance.helloWorld(); TestSingle1.getTestSingle1().helloWorld(); TestSingle2.INSTANCE.helloWord(); } }
/**
*
hello test single1
hello test single2
test single hello world3
*/
4、饿汉式和懒汉式的对比
(1)、二者创建的时机不同,前者是加载时就生成对象,后者是需要时才生成对象
(2)、懒汉式存在线程问题
(3)、饿汉式存在浪费资源的可能。
六、final:可以修饰属性,方法和类以及局部变量
1、当不希望类被继承时,可以用final修饰。
2、当不希望父类的某个方法被子类覆盖、重写(override)时,可以使用final关键字修饰
3、当不希望累的某个属性的值被修改,可以用final修饰。
4、当不希望某个局部变量被修改,可以使用final修饰
final的使用细节和注意事项:
(1):final修饰的属性又叫常量,一般用XX_ XX_XX来命名
(2):final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在
:定义时、在构造器中、在代码块中。
(3)如果final修饰的属性是静态的,则初始化的位置只能是:定义时、在静态代码块,不能在构造器中赋值
(4):final类不能继承,但是可以实例化对象。
(5):如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。
(6):一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。
(7):final不能修饰构造方法(即构造器)
(8):final和 static往往搭配使用,效率更高,不会导致类加载.底层编译器做了优化处理。
(9):包装类(Integer,Double,Float, Boolean等都是final),String也是final类。