2015-03-30 77 views
3

比方说,我有一个ParkingMeter类和一个ParkingSlip类。 ParkingSlips只能在ParkingMeter课程内创建,但ParkingSlips应该可以通过名为Car的外部课程访问(因此您可以检查每辆车是否支付了停车费用)。如何确保仅在特定类中实例化类?

是否有办法确保ParkingSlips只能从ParkingMeter内部创建,但仍可供其他类访问?

+1

使用ParkingSlips的私有构造函数。 http://stackoverflow.com/questions/17342815/what-is-the-use-of-private-constructor-in-java – chiaboy 2015-03-30 23:32:32

+2

使ParkingSlips成为ParkingMeter的私人内部类。然后写一个getter方法来获得ParkingSlips(而不是setter)。有车在ParkingMeter中呼叫吸气器 – 2015-03-30 23:32:53

+2

当然可以。您可以看到Inner Class:https://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html。您可以将ParkingSlip作为ParkingMeter的内部类。汽车可以通过getter获得ParkingSlip对象。 – MageXellos 2015-03-30 23:33:21

回答

2

如果您不想让ParkingSlip为内部类,请将这两个类放在同一个包中,并使ParkingSlip的构造函数包为私有。它不会阻止同一包裹中的其他班级制作停车卡片,但它会阻止其他包裹中的坏人。

package parking; 

public class ParkingSlip { 
    ParkingSlip() { 
    } 
} 

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

最安全的方法是使ParkingSlip公开内部静态类ParkingMeter并给它一个私人构造函数。

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

一个不太安全的,但更可用,方法是给默认(又名“包”)能见度构造和在同一个包有ParkingMeter,但来自同一个包中的任何其它类 - 即使从不同的项目 - 将有权访问构造函数。

请注意,无论你走到哪里,反射都可以绕过它。

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"); 
    } 
} 

一个清洁的解决方案,这resticts在编译时(在运行时只有以上检查溶液)构造函数访问是

  • 地方ParkingMeterParkingSlip(只有那些二)在专用包
  • 离开这两个类public
  • 使构造函数(一个或多个)的F或ParkingSlip“友好”(均未private,也不protected,也不public

这确保了ParkingSlip构造只能由类在同一包访问,并作为ParkingMeter是唯一的其他类在该包,你有你想要的。

public class ParkingSlip { 

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