如何让一个类不能被实例化
2017-03-05 11:56 ttylinux 阅读(6648) 评论(0) 编辑 收藏 举报本文涉及的概念:
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
引用:
版权声明:
作者:ttylinux
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。