GVKun编程网logo

Java 面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式 (饿汉式和懒汉式)?

3

如果您想了解Java面试-什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于4-1如何定义Java中的方

如果您想了解Java 面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式 (饿汉式和懒汉式)?的相关知识,那么本文是一篇不可错过的文章,我们将为您提供关于4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、C#单例---饿汉式和懒汉式、Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError 解决的有价值的信息。

本文目录一览:

Java 面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式 (饿汉式和懒汉式)?

Java 面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式 (饿汉式和懒汉式)?

<font color="red"> 什么是单例设计模式?</font>

单例设计模式就是一种控制实例化对象个数的设计模式。

<font color="red"> 为什么要使用单例设计模式?</font>

使用单例设计模式可以节省内存空间,提高性能。因为很多情况下,有些类是不需要重复产生对象的。 如果重复产生对象的话,会导致大量的内存空间被占用,性能降低。 例如:在程序启动中,加载已保存的数据信息。这些数据信息是由一个单例对象统一读取,其他程序只需要通过这个单例对象获取加载的数据信息即可。

单例设计模式分为饿汉式和懒汉式。饿汉式是在系统加载类的时候就会自动提供类的实例化对象如 Computer computer。 懒汉式是在第一次使用的时候进行实例化对象处理。

<font color="red"> 饿汉式单例设计模式实现源码:</font>

class Computer{

  //1、私有化 Computer 构造函数
  private Computer(){
    System.out.println("私有化 Computer 构造函数");
  }
  public void printInfo(){
    System.out.println("Computer 类使用的就是单例设计模式");
  }

  // 2、调用私有化 Computer 构造函数并将computer属性设置为static
  private static Computer computer = new Computer();

  // 3、提供getCompter()方法,便于调用
  public static Computer getCompter(){
    return computer;
  }
}

public class Demo {

  public static void main(String[] args) {
    // 产生单例对象
    Computer computer = Computer.getCompter();

    // 调用printInfo()方法
    computer.printInfo();
  }
}

运行结果:

私有化 Computer 构造函数
Computer 类使用的就是单例设计模式

<font color="red"> 饿汉式单例设计模式的实现过程分析:</font>

1、所有新的实例化对象的产生都会调用构造方法,如果无法正常调用构造方法的话,也就不能产生新的实例化对象。 如果想控制实例化对象个数的话,那么就应该控制构造函数。因此首先将该类的构造方法定义为私有方法。

private Computer(){
    System.out.println("私有化Computer 构造函数");
  }

2、类的构造方法私有化后,在类的外部就不能产生实例化对象。但是 Private 修饰的构造方法可以在类的内部访问。 如果要访问 Private 修饰的构造方法,可以在类的内部调用构造函数。

private Computer computer = new Computer();

3、computer 作为普通属性,只有在实例化对象产生之后才能被调用。由于类的外部无法产生实例化对象,如果想获取 computer 属性,可以将 computer 属性设置为 static。

private static Computer computer = new Computer();

4、对于 private 属性 computer 来说,如果想在类的外部获取该属性,则需要通过 getComputer () 方法获取。

public static Computer getCompter(){
    return computer;
  }

由于饿汉式在类加载的时候就完成了对象实例化,如果程序始终没有用到这个实例化对象,那么就会造成内存空间的浪费。 为了不浪费内存空间,懒汉式是在第一次使用的时候进行实例化对象处理。

<font color="red"> 懒汉式单例设计模式实现源码:</font>

class Computer{

  //1、私有化 Computer 构造函数
  private Computer(){
    System.out.println("私有化 Computer 构造函数");
  }
  public void printInfo(){
    System.out.println("Computer 类使用的就是单例设计模式");
  }

  // 2、调用私有化 Computer 构造函数并将computer属性设置为static
  private static Computer computer;

  // 3、提供getCompter()方法,便于调用
  public static Computer getCompter(){

    // 懒汉式,按需创建 即在第一次使用的时候进行实例化对象
    if(computer == null){
      computer = new Computer();
    }
    return computer;
  }
}

public class Demo {
  public static void main(String[] args) {
    // 产生单例对象
    Computer computer = Computer.getCompter();

    // 调用printInfo()方法
    computer.printInfo();
  }
}

运行结果:

私有化 Computer 构造函数
Computer 类使用的就是单例设计模式

<font color="red"> 懒汉式单例设计模式的实现源码分析:</font>

为了避免实例化的对象始终没有被使用,造成内存空间的浪费,所以增加了对实例化对象的判断, 即如果实例化对象为 null 则创建实例化对象。

// 懒汉式,按需创建 即只有在第一次使用的时候才进行实例化对象
    if(computer == null){
      computer = new Computer();
    }

但是如果在多线程下,会出现这样的情况即一个线程进入了 if 语句, 另一个线程也通过了 if 语句。 这样就产生了多个实例化对象。 为了避免这样的问题,可以采用双重加锁机制。

<font color="red"> 双重加锁机制优化懒汉式源码:</font>

class Computer{
  //1、私有化 Computer 构造函数
  private Computer(){
    System.out.println("私有化 Computer 构造函数");
  }

  public void printInfo(){
    System.out.println("Computer 类使用的就是单例设计模式");
  }

  // 2、调用私有化 Computer 构造函数并将computer属性设置为static
  private volatile static Computer computer;

  // 3、提供getCompter()方法,便于调用
  public static Computer getCompter(){
    // 第一次检查
    if(computer == null){
      // 加锁
      synchronized (Computer.class){
        // 第二次检查
        if (computer == null){
          computer = new Computer();
        }
      }
    }
    return computer;
  }
}

public class Demo {
  public static void main(String[] args) {
    // 产生单例对象
    Computer computer = Computer.getCompter();

    // 调用printInfo()方法
    computer.printInfo();
  }
}

运行结果:

私有化 Computer 构造函数
Computer 类使用的就是单例设计模式

<font color="red"> 双重加锁机制优化懒汉式源码分析:</font>

 // 2、调用私有化 Computer 构造函数并将computer属性设置为static
  private volatile static Computer computer;

  // 3、提供getCompter()方法,便于调用
  public static Computer getCompter(){
    // 第一次检查
    if(computer == null){
      // 加锁
      synchronized (Computer.class){
        // 第二次检查
        if (computer == null){
          computer = new Computer();
        }
      }
    }
    return computer;
  }

1、volatile 可以保证多线程下的可见性即保证了子线程的会跟主线程的一致。 2、当 thread2,进入第一个 if (computer == null) 语句,子线程的 computer 为空的,thread2 释放资源给 thread3。 3、当 thread3,进入第一个 if (computer == null) 语句,子线程的 computer 为空的,thread3 释放资源给 thread2。 4、当 thread2,进入第二个 if (computer == null) 语句,执行 computer = new Computer (),实例化对象 computer,volatile 修饰的变量 computer,会马上同步到主线程的变量 computer,执行完成后 thread2 释放资源给 thread3。 5、当 thread3,进入第二个 if (computer == null) 语句,此时子线程的 computer 不为空,所以 thread3 不再会重复实例化 computer。

4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;

4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;

1.一般情况下,定义一个方法的语法是:

访问修饰符 返回值类型 方法名(参数列表){
方法体
}

1、 访问修饰符:方法允许被访问的权限范围, 可以是 public、protected、private 甚至可以省略 ,其中 public 表示该方法可以被其他任何代码调用,其他几种修饰符的使用在后面章节中会详细讲解滴

2、 返回值类型:方法返回值的类型,如果方法不返回任何值,则返回值类型指定为 void ;如果方法具有返回值,则需要指定返回值的类型,并且在方法体中使用 return 语句返回值

3、 方法名:定义的方法的名字,必须使用合法的标识符

4、 参数列表:传递给方法的参数列表,参数可以有多个,多个参数间以逗号隔开,每个参数由参数类型和参数名组成,以空格隔开 

根据方法是否带参、是否带返回值,可将方法分为四类:

Ø 无参无返回值方法

Ø 无参带返回值方法

Ø 带参无返回值方法

Ø 带参带返回值方法

public class HelloWorld {
    
    //定义了一个方法名为 print 的方法,实现输出信息功能
    public void print() {
        System.out.println("Hello World");
    }
    
    public static void main(String[] args){
        
        //在 main 方法中调用 print 方法
        HelloWorld test=new HelloWorld();
        test.print();
    }
}

2.Java 中无参无返回值方法的使用(如果方法不包含参数,且没有返回值,称为无参无返回值的方法。

方法的使用分两步

例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 “ welcome to imooc. ”

注意:

1、 方法体放在一对大括号中,实现特定的操作

2、 方法名主要在调用这个方法时使用,需要注意命名的规范,一般采用第一个单词首字母小写,其它单词首字母大写的形式

第二步,调用方法

当需要调用方法执行某个操作时,可以先创建类的对象,然后通过  对象名.方法名();  来实现(关于类和对象的概念在后面章节中会详细讲解滴,先熟悉语法,表着急哦~~)

例如:在下面的代码中,我们创建了一个名为 hello 的对象,然后通过调用该对象的 show( ) 方法输出信息

运行结果为:  welcome to imooc.

3.Java 中无参带返回值方法的使用

如果方法不包含参数,但有返回值,我们称为无参带返回值的方法。

例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果

     在 calSum( ) 方法中,返回值类型为 int 类型,因此在方法体中必须使用 return 返回一个整数值。

运行结果为: 两数之和为:17

不容忽视的“小陷阱”:

1、 如果方法的返回类型为 void ,则方法中不能使用 return 返回值!

2、 方法的返回值最多只能有一个,不能返回多个值

3、 方法返回值的类型必须兼容,例如,如果返回值类型为 int ,则不能返回 String 型值

 

 

 

 

 

 

 

 

5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块

5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块

1.Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。当然,鉴于他作用的特殊性更推荐用类名访问

使用 static 可以修饰变量、方法和代码块。

    

2. 与静态变量一样,我们也可以使用 static 修饰方法,称为静态方法或类方法。其实之前我们一直写的 main 方法就是静态方法。静态方法的使用如:

         

注意:

1、 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员。如:

    

如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。如:

2、 在普通成员方法中,则可以直接访问同类的非静态变量和静态变量,如下所示:

3、 静态方法中不能直接调用非静态方法,需要通过对象来访问非静态方法。如:

          

3.Java 中的 static 使用之静态初始化块

Java 中可以通过初始化块进行数据赋值。如:

   在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。

注意:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量  

 

 

 

 

 

 

C#单例---饿汉式和懒汉式

C#单例---饿汉式和懒汉式

单例模式:

步骤:

1.定义静态私有对象

2.构造函数私有化

3.定义一个静态的,返回值为该类型的方法,一般以Getinstance/getInit为方法名称

单例模式有懒汉和饿汉,最好使用饿汉

1.饿汉式---先实例化

public class Singleton
    {
        private static Singleton  _singleton = new Singleton();//1
        private Singleton()  //2
        {
        }
        public static Singleton GetInstance()  //3
        {

            return _singleton;
        }


    }

 

2.懒汉式---后实例化

using System;

namespace 单例懒汉
{

 public class Singleton

    {
        private static Singleton _singleton;   //1
        private Singleton()   // 2
        {

        }
        public static Singleton GetInstance()  3
        {
            if (_singleton == null)
            {
                _singleton = new Singleton();
            }
            return _singleton;
        }
   }
}

 

Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError 解决

Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError 解决

Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError 解决

IDEA 发现一个奇怪的错误
今天用 IDEA2018.1 运行 SpringBoot 项目报错如下:
Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/metadata/ConfigurationMetadata at org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:169)
解决方案:
分下看这个跟 Eclipse 有关,可是这个不是 Eclipse 项目(没有 Eclipse 的 Workspeace 信息),后来查找发现跟 Eclipse 有关设置就是之前自己设置锅编译器,改过来问题得到解决。解决步骤:IDEA 中 File-->settings-->Bulid Execution Deloyment-->Complier-->Java Complier 中的 user complier 有原来的 Eclipse 改为 javac 即可

今天的关于Java 面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式 (饿汉式和懒汉式)?的分享已经结束,谢谢您的关注,如果想了解更多关于4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、C#单例---饿汉式和懒汉式、Error:java: Internal compiler error: java.lang.Exception: java.lang.NoClassDefFoundError 解决的相关知识,请在本站进行查询。

本文标签: