• 如何让一个类不能被实例化


    本文涉及的概念:
    1.在面向对象编程中,在什么场景下会需要做到让一个类不能被实例化
    2.让一个类不能被实例化的方法
     
     
    什么样的场景会需要让一个类不能被实例化
    工具类(utility class),实例化对它们没有意义的工具类。这时候,就要做到不让该类被实例化
    java.lang.Math:
    把与Math相关的基本类型的值和相关的方法组合到该Math类中。Math类不需要实例化,使用了私有构造器。不过,它可以在Math类中内部被实例化。
    使用私有构造器,没有子类;使用final修饰,没有子类。
    package java.lang;
    import java.util.Random;
     
    public final class Math {
     
      /**
      * Don't let anyone instantiate this class.
      */
      private Math() {}
     
      /**
      * The {@code double} value that is closer than any other to
      * <i>e</i>, the base of the natural logarithms.
      */
      public static final double E = 2.7182818284590452354;
     
      public static final double PI = 3.14159265358979323846;
     
      public static double sin(double a) {
      return StrictMath.sin(a); // default impl. delegates to StrictMath
      }
     
    ....    
      public static double toRadians(double angdeg) {
      return angdeg / 180.0 * PI;
      }
     
      public static float scalb(float f, int scaleFactor) {
      return sun.misc.FpUtils.scalb(f, scaleFactor);
      }
    }
     
     
    让一个类不能被实例化的方法
    0.不写显式的构造器---不可行,编译器会自动提供一个公有的,无参的缺省的构造器
    1.抽象类的方式---不可行
    子类可以继承父类,从而实例化
    public abstract class Parent {
     
    public Parent() {
    }
     
    public static void main(String[] args){
     
    // Parent one = new Parent();
    }
    }
     
    public class Child extends Parent {
     
    public Child() {
    }
     
    }
     
     
    2.使用私有构造器----可行,需要在构造器中添加限制
    在使用私有构造器的基础下,再在构造方法中返回一个异常,因为虽然外部类无法实例化该类,但是内部类可以实例化该类.
    如果只是通过私有化构造器,那么通过反射的方式,还是可以实例化该类。
    必须在私有构造器中添加一个异常,这样,当执行构造方法的时候,就会抛出异常,从而停止实例化
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    
    public class Elvis2 {
        private Elvis2(){
            throw new AssertionError();
        }
        
        public void getIt(){
            System.out.println("Now you get it");
        }
        
        public static void main(String[] args){
       
             try {
                  Class<?> classType = Elvis2.class;  
                 Constructor<?> c = classType.getDeclaredConstructor(null);  
                 c.setAccessible(true);  
                Elvis2 e1 = (Elvis2)c.newInstance();
                e1.getIt();
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                e.printStackTrace();
            }  
        }
    }

     输出结果: 抛出了AssertionError异常,达到期望

    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at chapterOne.Elvis2.main(Elvis2.java:21)
    Caused by: java.lang.AssertionError
    at chapterOne.Elvis2.<init>(Elvis2.java:8)
    ... 5 more

     
    引用:
     
     
     
  • 相关阅读:
    Oracle配置手册
    Vim配置手册
    高斯消元
    dp专场的蒟蒻题解
    mac 软件意外退出
    spring security整体流程
    服务启动shell脚本
    nohup 启动命令
    linux service脚本
    docker 安装prometheus和grafna
  • 原文地址:https://www.cnblogs.com/ttylinux/p/6504822.html
Copyright © 2020-2023  润新知