Instantiating a generic type - java

I'm trying to convert an existing class to use generics, and am getting stumped while converting the constructors.
The original class was a POJO that contained logic for moving from one room to another in a text-based console game. Literally, it was a class that held some string triggers that would fire the action (eg. the user types "walk right"), a description, and a pointer to the new Location.
The current, non generic version of the class looks like this:
public class Navigation implements Serializable {
private static final long serialVersionUID = 1L;
private String trigger;
private String description;
private Location target;
public Navigation() {
this("", "", new Location());
}
public Navigation(String trigger, String description, Location target) {
this.trigger = trigger;
this.description = description;
this.target = target;
}
// plus getters, setters, etc.
}
(The Location class is another POJO that describes a location. It is irrelevant.)
I want to extend the Navigation class to be able to handle targets that are not Locations. I thought that the best way to do this would be to convert the Navigation class to use generics, so I tried this:
public class Navigation<T> implements Serializable {
private static final long serialVersionUID = 2L;
private String trigger;
private String description;
private T target;
public Navigation() {
this("", "", new T());
}
public Navigation(String trigger, String description, T target) {
this.trigger = trigger;
this.description = description;
this.target = target;
}
// plus getters, setters, etc.
}
However, this doesn't compile at the line this("", "", new T()); because T cannot be instantiated. Is is possible to instantiate the generic type object in this context?

You basically have two choices:
1.Require an instance:
public Navigation(T t) {
this("", "", t);
}
2.Require a class instance:
public Navigation(Class<T> c) {
this("", "", c.newInstance());
}
You could use a factory pattern, but ultimately you'll face this same issue, but just push it elsewhere in the code.

No, and the fact that you want to seems like a bad idea. Do you really need a default constructor like this?

You cannot do new T() due to type erasure. The default constructor can only be
public Navigation() {
this("", "", null);
}
​
You can create other constructors to provide default values for trigger and description. You need an concrete object of T.

Related

Generic Enum Type for anything extended

I like to make a generic enum that accepts anything.
For this example I use TaskStatus, but in the future, I like to use Generic Enum for example; StudentStatus, this student status can take an id and description itself and it will convert automatically. Moreover, iterate every object and finally automatically return. Is there any chance I can make it?
#Getter
#AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum TaskStatusEnum{
READY(1, "Ready"),
ON_GOING (2,"On going");
private final long id;
private final String description;
public static TaskStatusEnum get (long id)
{
for (TaskStatusEnum status : TaskStatusEnum.values()) {
if (status.id == id) {
return id;
}
}
return null;
}
I'm not sure what exactly you want. You can use interface on enum, then you can use interface as status and dont care what exactly status class is.
public interface Status<E extends Enum<E> & Status<E>> {
public long getId();
public String getDescription();
}
student status:
public enum StudentStatus implements Status<StudentStatus>{
NEW(0, "new");
;
private long id;
private String description;
private StudentStatus(long id, String description) {
this.id=id;
this.description = description;
}
#Override
public long getId() {
return id;
}
#Override
public String getDescription() {
return description;
}
}
task status:
public enum TaskStatus implements Status<TaskStatus>{
OPEN(0, "open");
;
private long id;
private String description;
private TaskStatus(long id, String description) {
this.id=id;
this.description = description;
}
#Override
public long getId() {
return id;
}
#Override
public String getDescription() {
return description;
}
}
generic method to find out status by id
public abstract class StatusUtil {
public static <E extends Enum<E> & Status<E>> E get(Class<E> statusClass, long id) {
return Arrays.asList((E[]) statusClass.getEnumConstants())
.stream()
.filter(item -> item.getId() == id)
.findAny()
.orElse(null);
}
}
example how use:
public class Test {
public static void main(String... args) {
StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
statusList.forEach(status -> System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription()));
}
}
if you use JAVA below 8:
public interface Status<E extends Enum<E>> {
public long getId();
public String getDescription();
}
statusUtil:
public abstract class StatusUtil {
public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
for(E item: (E[]) statusClass.getEnumConstants()) {
if(item.getId() == id) {
return item;
}
}
return null;
}
}
test:
public static void main(String... args) {
StudentStatus studentStatus = StatusUtil.get(StudentStatus.class, 0);
TaskStatus taskStatus = StatusUtil.get(TaskStatus.class, 0);
List<Status> statusList = Arrays.asList(studentStatus, taskStatus);
for(Status status: statusList) {
System.out.println(status.getClass().getName()+"\t"+status.getId()+"\t"+status.getDescription());
}
}
This you can use in cases, when enums has this same methods and you need common interface
Your enum is effectively final (no subclass allowed)
Apparently you are asking if TaskStatus enum can be subclassed. For example making a StudentStatus that inherits from TaskStatus.
➥ No, enums in Java cannot be subclassed.
Your enum definition actually is a subclass of Enum. That happens in the background, magically handled by the compiler. The inheritance stops there. Your enum definition is effectively final, not allowing further subclasses.
An enum definition can implement an interface. Instances from multiple enum definitions can be treated as all being objects of the same interface. See Answer by Victor1125.
An enum in Java is a convenient way to automatically instantiate one or more name objects, to represent a limited set of values known at compile time. Those instances all pop into existence when their definition class is loaded by the Java classloader. Those objects remain in memory.
You cannot add more instances dynamically at runtime. The entire domain of the enum’s objects is defined at compile time. (Exception: Some crazy twisted reflection/introspection code may be able to create more instances, but I would not go there.)
If you want inheritance, or dynamically created instances, do not use enums. Use regular classes and subclasses, collected into sets or lists. The sets or lists can be marked (< … >) with generics to allow the superclass of their contained elements. For example Set< Animal > can contain objects of the subclasses Dog, Cat, and Bird.
By the way, you can now define an enum in 3 places: its own class, nested within another class, and now in Java 16 (previewed in Java 15), locally inside a method.
Tip: No need to put "Enum" within the name of your enum. Endeavor to invent names for your enum class and enum objects that read naturally. The fact that they happen to be an enum should fade into the background. For example: See Month (Month.JANUARY) and DayOfWeek (DayOfWeek.MONDAY).
How to handle null point on StatusUtil.class
StatusUtil:
public abstract class StatusUtil {
public static <E extends Enum<E>> E get(Class<E> statusClass, long id) {
for(E item: (E[]) statusClass.getEnumConstants()) {
if(item.getId() == id) {
return item;
}
}
return null;
}

Is it correct to have static factory method to get a new instance with one field updated?

I think the title is self-descriptive but I will give an example to elaborate on my question. I have a DTO class with few fields (a CarDataTransferObj class in my example). In another class (let's call it class A) I need to create a new instance of that object few times, but with only one field updated (length field in my example). Given DTO must be immutable in class A. As there is "many" fields in the class CarDataTransferObj, I thought about following approach (to avoid repeating code in class A):
#Builder
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public static CarDataTransferObj newInstanceWithUpdatedLength(final CarDataTransferObj car, final Integer newLength) {
return CarDataTransferObj.builder()
.id(car.getId())
.color(car.getColor())
.manufacturer(car.getManufacturer())
.model(car.getModel())
.uniqueIdNr(car.getUniqueIdNr())
.nrOfDoors(car.getNrOfDoors())
.engineType(car.getEngineType())
.length(newLength)
.safetyLevel(car.getSafetyLevel())
.build();
}
}
For me it smells like a little anti-pattern usage of static factory methods. I am not sure whether it's acceptable or not, hence the question.
Is using static factory method in the presented way an anti-pattern, and should be avoided ?
In my searching, I didn't come across anyone calling this1 an anti-pattern.
However, it is clear that if you try to do this using a classic builder that is not specifically implemented to support this mode of operation .... it won't work. For instance, the example CarBuilderImpl in the Wikipedia article on the Builder design pattern puts the state into an eagerly created Car instance. The build() method simply returns that object. If you tried to reuse that builder in the way that you propose, you would end up modifying a Car that has already been built.
There is another problem you would need to worry about. In we modified the Wikipedia CarBuilder example to add actual wheels (rather than a number of wheels) to the Car being built, we have to worry about creating cars that share the same wheels.
You could address these things in a builder implementation, but it is unclear whether the benefits out-weigh the costs.
If you then transfer this thinking to doing this using a factory method, you come to a slightly different conclusion.
If you are doing this as a "one-off", that's probably OK. You have a specific need, the code is clunky ... but so is the problem.
If you needed to do this for lots of different parameters, or combinations of parameters, this is not going to scale.
If the objects that are created are mutable, then this approach is could be problematic in a multi-threaded environment depending on how you control access to the objects you are using as templates.
1 - There are no clear measurable criteria for whether something is an anti-pattern or not. It is a matter of opinion. Admittedly, for many anti-patterns, there will be wide-scale agreement on that opinion.
It seems a little inefficient to construct an entirely new instance via a builder every time you want to make a new copy with a small modification. More significantly, it sounds like the places where you need the class to be immutable are isolated to places like class A. Why not try something like this:
public interface ICarDataTransferObject {
public Integer GetId();
public String GetColor();
public String GetManufacturer();
public String GetModel();
public String GetUUID();
public Integer GetDoorCount();
public EngineType GetEngineType();
public Integer GetLength();
public Integer GetSafteyLevel();
}
public class CarDataTransferObject Implements ICarDataTransferObject {
private Integer _id;
private String _color;
private String _manufacturer;
private String _model;
private String _uniqueIdNr;
private Integer _nrOfDoors;
private EngineType _engineType;
private Integer _length;
private Integer _safetyLevel;
public Integer GetId() { return _id; }
public void SetId(Integer id) { _id = id; }
public String GetColor() { return _color; }
public void SetColor(String color) { _color = color; }
public String GetManufacturer() { return _manufacturer; }
public void SetManufacturer(String manufacturer) { _manufacturer = manufacturer; }
public String GetModel() { return _model; }
public void SetModel(String model) { _model = model; }
public String GetUUID() { return _uniqueIdNr; }
public void SetUUID(String uuid) { _uniqueIdNr = uuid; }
public Integer GetDoorCount() { return _nrOfDoors; }
public void SetDoorCount(Integer count) { _nrOfDoors = count; }
public EngineType GetEngineType() { return _engineType; }
public void SetEngineType(EngineType et) { _engineType = et; }
public Integer GetLength() { return _length; }
public void SetLength(Integer length) { _length = length; }
public Integer GetSafteyLevel() { return _safetyLevel; }
public void SetSafteyLevel(Integer level) { _safteyLevel = level; }
public CarDataTransferObject() {}
public CarDataTransferObject(ICarDataTransferObject other) { ... }
public ReadOnlyCarDataTransferObject AsReadOnly() {
return ReadOnlyCarDataTransferObject (this);
}
}
}
public class ReadOnlyCarDataTransferObject Implements ICarDataTransferObject {
private ICarDataTransferObject _dto = null;
public Integer GetId() { return _dto.GetId(); }
public String GetColor() { return _dto.GetColor(); }
public String GetManufacturer() { return _dto.GetManufacturer(); }
public String GetModel() { return _dto.GetModel(); }
public String GetUUID() { return _dto.GetUUID(); }
public Integer GetDoorCount() { return _dto.GetDoorCount(); }
public EngineType GetEngineType() { return _dto.GetEngineType(); }
public Integer GetLength() { return _dto.GetLength(); }
public Integer GetSafteyLevel() { return _dto.GetSafteyLevel; }
public ReadOnlyCarDataTransferObject (ICarDataTransferObject other) {
_dto = other;
}
}
Now when you want class A to have a copy no one can modify, just use the copy constructor and only expose a ReadOnly version of that copy.
public class A {
ICarDataTransferObject _dto;
ReadOnlyCarDataTransferObject _readOnlyDTO;
public ICarDataTransferObject GetDTO() { return _readOnlyDTO; }
public A(ICarDataTransferObject dto) {
_dto = new CarDataTransferObject(dto);
_readOnlyDTO = new ReadOnlyCarDataTransferObject(_dto);
}
}
You commonly see this approach in .NET applications.
While it is debatable whether your static method is an anti-pattern or not, it surely won't scale for combinations of different attributes. Nonetheless, even if it's not an anti-pattern, I think there is a better way to accomplish what you need.
There's a variant of the traditional builder pattern that, instead of creating a new empty builder, accepts an already built object and creates an already initialized builder. Once you create the builder this way, you simply change the length attribute in the builder. Finally, build the object. In plain code (no Lombok, sorry) it could be like this:
public class CarDataTransferObj {
private Integer id;
private String color;
// other attributes omitted for brevity
private Integer length;
// Private constructor for builder
private CarDataTransferObj(Builder builder) {
this.id = builder.id;
this.color = builder.color;
this.length = builder.length;
}
// Traditional factory method to create and return builder
public static Builder builder() {
return new Builder();
}
// Factory method to create and return builder initialized from an instance
public static Builder builder(CarDataTransferObj car) {
Builder builder = builder();
builder.id = car.id;
builder.color = car.color;
builder.length = car.length;
return builder;
}
// getters
public static class Builder {
private Integer id;
private String color;
private Integer length;
private Builder() { }
public Builder withId(Integer id) { this.id = id; return this; }
public Builder withColor(String color) { this.color = color; return this; }
public Builder withLength(Integer length) { this.length = length; return this; }
public CarDataTransferObj build() {
return new CarDataTransferObj(this);
}
}
}
Now with all this infrastructure in place, you can do what you want as easy as:
CarDataTransferObj originalCar = ... // get the original car from somewhere
CarDataTransferObj newCar = CarDataTransferObj.builder(originalCar)
.withLength(newLength)
.build();
This approach has the advantage that it scales well (it can be used to change any combination of parameters). Maybe all this builder's code seems boilerplate, but I use an IntelliJ plugin to create the builder with two keystrokes (including the variant factory method that accepts a built instance to create an initialized builder).
I'm still new to java but..
I guess making a copy method which takes the CarDataTransferObj object variables and sets their values to another CarDataTransferObj object variables and changing the the length using it's setter method would be better idea
Example:
public class CarDataTransferObj {
private Integer id;
private String color;
private String manufacturer;
private String model;
private String uniqueIdNr;
private Integer nrOfDoors;
private EngineType engineType;
private Integer length;
private Integer safetyLevel;
public void Copy(CarDataTransferObj copy) { //Could add another parameter here to be the new length
copy.setId(id);
copy.set(color);
copy.setManufacturer(manufacturer);
copy.setModel(model);
copy.setUniqueIdNr(uniqueIdNr));
copy.setNrOfDoors(nrOfDoors));
copy.setEngineType(engineType));
copy.setLength(length);
copy.setSafetyLevel(safetyLevel));
}
}
public class SomeOtherClass {
CarDataTransferObj car1 = new CarDataTransferObj(); //Using this way made you able to use the constructor for a more useful thing
//You set the variables you want for car1 here
CarDataTransferObj car2 = new CarDataTransferObj();
car1.Copy(car2)
car2.setLength(newLength) //Set the new length here
}

How to pass different objects (having same parent) to a constructor and how to identify type of that object in constructor

I have a scenario where I'm sending different objects to a constructor and I have to identify the class of that object and set values accordingly.
Class ABC {
private long id;
private SomeClass obj;
private String xyzName;
private Date date;
private EnumType status;
// And Getters and Setters
}
Class A extends ABC {
private String someOtherId;
private String type;
private String model;
private String manufacturer;
//and some props and Getters and Setters
}
Class B extends ABC {
private String someOtherId;
private String equipName;
private String model;
private String serialNo;
//and some props and Getters and Setters
}
Class C extends ABC {
private String someOtherId;
private String materialName;
private String desc;
private String serialNo;
//and some props and Getters and Setters
}
Note: These are the entity classes
And In Controller, I'm doing ops like adding, editing, updating(mostly changing statuses) and etc.And every time I do I have to enter or log kind of msg into
History Class. something like
From AController
historyService.enterLogToHistory(new
History(Aobject, EnumType.somestatus));
From BController,
historyService.enterLogToHistory(new History(Bobject,
EnumType.somestatus));
From CController,
historyService.enterLogToHistory(new
History(Cobject,EnumType.somestatus));
Class History() {
private long id;
private Date date;
private String Status;
private String Activity; // or msg
// some other #Transient properties
History(Object obj) {
//set above values like by getting values form this obj(using getters)
}
History(Object obj, EnumType status) {
this(obj);
// set some other #Transient properties by getting values form this obj
// and set value for msg;
}
}
So, Now my problem is how to identify that object whether it is A obj,
B, obj or C obj because if know the type of object only I can the getters of that obj and I can set values in History constructor.
So, please anyone help me out in this
To get rid of instanceof mess, consider using oveloaded constructors:
class History {
History(A a) {
// initialize by `A` instance
}
History(B b) {
// initialize by `B` instance
}
//...
}
This will work if you know classes of all instances on compile time.
Another option is to switch to static factory methods:
public class History {
// private constructor to hide instance creation
private History(ABC abc) {
this.id = abc.getId();
this.date = new Date(abc.getDate().getTime());
// ... another common properties
}
public History setStatus(Status s) {
this.status = s;
return this;
}
// public static factory methods to create instances specified by input
public static History of(A a) {
History h = new History(a);
h.type = a.getType();
// ... properties specific for `A`
return h;
}
public static History of(A a, Status status) {
return of(a).setStatus(status);
}
public static History of(B b) {
History h = new History(b);
h.model = b.getModel();
// ... properties specific for `B`
return h;
}
// ...
}
Then, to create History instances, caller invokes:
History aHistory = History.of(a);
History bHistory = History.of(b, Status.ACTIVE);
The main advantage of such approach is that more stable API is introduced, while it remains flexible for internal refactoring. Imagine, you decide to implement various behavior for History of different types, e.g. VehicleHistory and VesselHistory. So you create those classes extending History, override some methods in them and refactor a few of() methods in History class (so that not new History(), but new VehicleHistory() is called). As far as you never call constructor externally, for outer code things remain unchanged -- it receives History object as before from the same History.of() method as before.

how to choose what type of object to instantiate based on form field?

i have a struts2 form that takes in a Maintenance object. there are different types of Maintenance - for the sake of brevity let's say there is RemovePart and InstallPart. this form includes fields for both, but the user only sees one - that is based on the user's choice in the first dropdown.
what is the correct (best?) way to determine which Maintenance class to instantiate once my Action receives the data? the best i've come up with so far is below, though i can't help thinking there is a better way to do it.
EDIT 6/24 14:18 GMT: the RemovedPart and InstalledPart classes have fields that don't correspond to each other.
public class Maintenance {
private String maintenanceType;
private String removedSerialNumber;
private String removedPartName;
private String removedPartDescription;
private String removedPartPosition;
private String installedSerialNumber;
private String installedPartName;
private String installedPartSource;
// getters and setters
}
public class RemovedPart {
private String serialNumber;
private String partName;
private String partDescription;
private String partPosition;
public static createRemovedPart(Maintenance maintenance) {
return new RemovedPart(maintenance.getRemovedSerialNumber(),
maintenance.getRemovedPartName(), maintenance.getRemovedPartDescription(),
maintenance.getRemovedPartPosition());
}
private RemovedPart() {
this.serialNumber = serialNumber;
this.PartName = partName;
this.partDescription = partDescription;
this.partPosition = partPosition;
}
// getters and setters
}
public class InstalledPart {
//similar to RemovedPart
}
public class MaintAction extends ActionSupport {
Maintenance maintenance;
public String execute() {
if (maintenance.getMaintenanceType().equals("remove")) {
RemovedPart removed = RemovedPart.createRemovedPart(maintenance);
} else {
// you get the idea
}
// more logic
return SUCCESS;
}
We can't know how much complex or big is your design, but from what has been shown, IF the Maintenance class is declaring duplicate fields (eg. serialnumber for both removed and installed) WITHOUT using both of them at the same time, and hence they're declared only to be filled by the chosen type of maintenance from the page... then you don't need 3 objects, nor duplicate fields:
declare a single Maintenance class, with single fields
post it to different actions, one for removal, one for installation.
The type alone will help you to determine which kind of Maintenance you are handling from a method run by both types. However, it would be better to turn it to an Enum:
public enum MaintenanceType {
INSTALLATION(1), REMOVAL(2);
private int type;
private MaintenanceType(int t) {
type = t;
}
public int getType() {
return type;
}
}
public class Maintenance {
private MaintenanceType type;
private String serialNumber;
private String partName;
// getters and setters
public boolean isInstallation(){
return type == MaintenanceType.INSTALLATION;
};
public boolean isRemoval(){
return type == MaintenanceType.REMOVAL;
};
}
If I understand your Problem correctly you want to have several kinds of Maintenance?
In this case you should think about inheritance
public abstract class Maintenance{
//code
}
public class Removal extends Maintenance{
//has everything Maintenance hase plus extras you can add here
}
public class Installation extends Maintenance{
//same as Removal
}
you could then define a Maintenance like this:
Mainenance m = new Removal();
you could also use interfaces,
public Interface Maintenance{
private String serialNumber;
...
public String getSerialNumber();
...
}
your classes could then implement the Interface and you could use them similar to the inherited version.

How to dynamically retrieve a constant in java?

I have several interfaces all with the same constants - ID and ROOT. I also have a method into which I pass an object that will be an implementation of one of these interfaces.
How can I dynamically retrieve the value of the constant depending on the class passed in - i.e. I want to do something like the following:
public void indexRootNode(Node node, Class rootNodeClass)
{
indexService.index(node, rootNodeClass.getConstant('ID'),
rootNodeClass.getConstant('ROOT'));
}
In PHP this is easy, but is this possible in Java? I've seen this problem solved using accessors on the constant, but I want to retrieve the constant directly. Annotations won't help me here either.
Thanks
This can be achieved using reflection (also see corresponding javadoc).
public void indexRootNode(Node node, Class rootNodeClass)
{
Field idField = rootNodeClass.getField("ID");
Object idValue = idField.get(null);
Field rootField = rootNodeClass.getField("ROOT");
Object rootValue = rootField.get(null);
indexService.index(node, idValue, rootValue);
}
Maybe you may additionaly have to cast the values to the corresponding type.
Please read chapter 19 use interfaces only to define types from Joshua Bloch's Effective Java (in fact, please read the entire book)
Constants do not belong in an interface!!! Constants should be tied to implementing classes, not interfaces.
Either use non-constant methods:
// the implementing classes can define these values
// and internally use constants if they wish to
public interface BaseInterface{
String id(); // or getId()
String root(); // or getRoot()
}
public interface MyInterface1 extends BaseInterface{
void myMethodA();
}
public interface MyInterface2 extends BaseInterface{
void myMethodB();
}
or use an enum to tie things together:
public enum Helper{
ITEM1(MyInterface1.class, "foo", "bar"),
ITEM2(MyInterface2.class, "foo2", "baz"),
;
public static String getId(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getId();
}
public static String getRoot(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getRoot();
}
private static Helper fromInterfaceClass(final Class<? extends BaseInterface> clazz){
Helper result = null;
for(final Helper candidate : values()){
if(candidate.clazz.isAssignableFrom(clazz)){
result = candidate;
}
}
return result;
}
private final Class<? extends BaseInterface> clazz;
private final String root;
private final String id;
private Helper(final Class<? extends BaseInterface> clazz,
final String root,
final String id){
this.clazz = clazz;
this.root = root;
this.id = id;
};
public String getId(){
return this.id;
}
public String getRoot(){
return this.root;
}
}
// use it like this
String root = Helper.fromInterfaceClass(MyInterface1.class).getRoot();

Categories