如何确保只在特定类中实例化类?

时间:2015-03-30 23:29:17

标签: java

假设我有一个ParkingMeter课程和一个ParkingSlip课程。 ParkingSlips只能在ParkingMeter班级内创建,但ParkingSlips应该可以通过名为Car的外部班级访问(这样您就可以检查每辆车是否已支付停车费用)。

有没有办法确保只能在ParkingMeter中创建ParkingSlips但仍可供其他类访问?

3 个答案:

答案 0 :(得分:2)

如果您不想将ParkingSlip作为内部类,请将这两个类放在同一个包中,并使ParkingSlip的构造函数包为private。它不会阻止同一个包中的其他类创建停车单,但它会阻止其他包中的恶人。

package parking;

public class ParkingSlip {
    ParkingSlip() {
    }
}

public class ParkingMeter {
    public ParkingSlip getSlip() {
        return new ParkingSlip();
    }
}

答案 1 :(得分:2)

最安全的方法是使ParkingSlip公共内部静态类ParkingLter并为其提供私有构造函数。

public class ParkingMeter {
    public static class ParkingSlip {
        private ParkingSlip() {
        }
    }
}

一种不太安全但更有用的方法是给构造函数提供默认(也称为“包”)的可见性,并将ParkingMeter放在同一个包中,但来自同一个包的任何其他类 - 甚至来自不同的项目 - 都将有权访问构造函数。

请注意,无论你走哪条路,反思都可以绕过它。

答案 2 :(得分:1)

实际上有一种方法可以检查是谁调用了构造函数或方法:
通过检查当前的堆栈跟踪
不是我推荐它,但是嘿,它有效:

public ParkingSlip() {

    // get the current stack trace
    // element 0: java.lang.Thread.getStackTrace
    // element 1: this constructor
    // element 2: the class/method calling this constructor
    StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

    // verify that it was indeed the ParkingMeter who invoked the constructor 
    if (!ParkingMeter.class.getName().equals(stackTrace[2].getClassName())) {
        throw new IllegalAccessError("Restricted access, only ParkingMeter is allowed to create instances");
    }
}

一个更干净的解决方案,它在编译时重新构造构造函数访问(上面的解决方案仅在运行时检查)是

  • ParkingMeterParkingSlip(仅限这两个)放在专用包中
  • 保留两个班级public
  • 制作ParkingSlip友好'的构造函数。 (既不是private,也不是protected,也不是public

这确保了ParkingSlip构造函数只能由同一个包中的类访问,并且ParkingMeter是该包中唯一的其他类,您已经得到了所需的内容。

public class ParkingSlip {

   // 'friendly' constructor
   ParkingSlip() {
   }
}