1. 构造函数
构造函数是在对象创建(new)时候运行,给对象初始化:包括属性,执行方法中语句;
而一般函数是在对象调用时候才执行。
一个对象建立构造函数只执行一次,而一般函数可以被对象调用多次
如果某个类中没有声明构造函数,默认是public类型构造函数
私有构造函数:
某个类中构造函数是私有的,那么这个类不能通过new的方式创建对应的对象,如果想创建含有私有构造函数的类的对象,那么只能在这个类中创建一个public方法,想创建对象时候通过这个public方法来创建
public class PublicConstruct { public PublicConstruct(String name){ System.out.println("this is publicConstruct: "+name); } } public class PrivateConstruct { private PrivateConstruct(){}; public static PrivateConstruct instanceMethod(){ System.out.println("this is PrivateConstruct method"); return new PrivateConstruct(); } } public class MainTest { public static void main(String[] args) { PublicConstruct publicConstruct=new PublicConstruct("abc"); // PrivateConstruct privateConstruct=new PrivateConstruct(); PrivateConstruct privateConstruct1=PrivateConstruct.instanceMethod(); } }
以上代码执行结果:
this is publicConstruct: abc
this is PrivateConstruct method
由于PrivateConstruct的构造函数是private类型,所以不能通过new方式创建对象,main方法中执行PrivateConstruct privateConstruct=new PrivateConstruct();则会报错:'PrivateConstruct()' has private access in 'com.citi.ark.mls.service.qftest.decorate.PrivateConstruct';这是只能通过PrivateConstruct暴露的public方法创建对应的对象
2. 单例模式
所谓的单例模式就是设计一个类,它在整个程序中只能有一个该类的实例存在。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象
2.1 饿汉模式
private static Singleton instance= new Singleton() 静态变量在类初始化时赋值,而类初始化是线程安全的,不存在初始化多次问题。;饿汉模式在类加载就会完成该类的实Instance例创建
饿汉模式是线程安全的。线程安全的原因是因为线程在访问单例对象前instance就已经创建好;所以说线程每次只能也必定只能拿到这个唯一的对象。
静态方法:声明的方法和属性不需要实例化就能被调用;static修饰的方法先于main方法被加载到方法区,静态方法只加载一次
非静态方法:声明的方法和属性必须实例化后才能被调用
私有方法:声明的方法和属性只能在本类中调用,外部看不见
公有方法:声明的方法和属性可以被外部调用
静态变量:静态变量早于对象创建,是随着类加载而加载;由于类只加载一次则静态变量在内存中也只存放一份,静态变量存在方法区中
public static Singleton getInstance(){...}是共有静态原因:共有是为了被外部调用,static原因是为了不用实例化便可以调用这个方法
instance是private static原因:private 不能被外部调用,static原因:只有static成员才能在没有创建对象时初始化,且类的静态成员在类第一次被使用时初始化后就不再被初始化,保证了单例。static类型的instance存在方法区,每次调用都指向同一个对象。其实存放在静态区中的是引用而不是对象,对象存在堆中
单例模式构造方法是private原因:private的构造方法不允许new对象(每次new对象时候都要调用构造方法)
public class Singleton { private Singleton(){}; //私有构造函数,不允许new方式创建Singleton实例 private static final Singleton instance=new Singleton(); //类初始化时候静态变量赋初始值,实现线程安全 public static Singleton getInstance(){ //公共静态方法,获取该类实例的唯一方法;由于instance在类初始化时候就已经创建好,这里就算有多线程访问也只是get操作,不会存在线程安全问题 return instance; } public static void main(String[] args) { for(int i=0;i<10;i++){ new Thread (()->{ System.out.println(getInstance().hashCode()); }).start(); } } }
output如下,可见这10个线程创建的实例是同一个
373030015
373030015
373030015
373030015
373030015
373030015
373030015
373030015
373030015
373030015
2.2 懒汉模式
2.2.1 线程不安全懒汉模式
由于静态变量没有赋初始值,类加载时候没有立刻实例化,只有在调用时候通过getInstance()实现实例化,所以存在多线程同时调用getInstance()场景,从而线程不安全
public class Singleton(){ private Singleton(){}; private static Singleton singleton = null; public static Singleton getInstance(){ //getInstance()中存在非原子性操作 if (singleton == null){ singleton = new Singleton(); } } }
2.2.2 线程安全懒汉模式
public class Single2 { //懒汉模式 static class Singleton { private Singleton() {} //volatile 避免内存可见性引出的问题 private volatile static Singleton instance = null; public static Singleton getInstance() { //双重检验锁 if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } }
为了保证懒汉模式线程安全,涉及到三个要点:
1.加锁保证线程安全
2.双重if保证效率
3. volatile避免内存可见性引来的问题.
参考文献: https://blog.csdn.net/jike11231/article/details/106229415/