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

 
PublicConstruct类中构造函数是在main方法中创建对象时候:public PublicConstruct(String name){...}执行

由于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/

posted on 2023-03-08 15:41  colorfulworld  阅读(31)  评论(0编辑  收藏  举报