Using Eclipse
For any Class we can automatically
Generate Setters an Getters
Generate Delegate Methods
Generate hashCode() and equals()
Generate toString()
Generate Constructor using Fields
Generate Constructor From Superclass
Like that
Any way to generate
Fully initialized Constructor
(Constructor without any parameters that initialized all non-primitive fields)
For example
If my class as that
public class MyClass {
private String id;
private String code;
private MyClass1 myClass1;
private MyClass2 myClass2;
}
Generated Fully initialized Constructor will be
public class MyClass {
private String id;
private String code;
private MyClass1 myClass1;
private MyClass2 myClass2;
// Fully initialized Constructor
public FlightScheduleRequest() {
this.myClass1 = new MyClass1();
this.myClass2 = new MyClass2();
}
}
Its invalid requirement
Thanks to #Jayan note
If MyClass1 or MyClass2 does not have the default constructor,
but takes arguments for its constructor
So the initialization of them will be invalid
this.myClass1 = new MyClass1(); // The constructor MyClass1() is undefined
this.myClass2 = new MyClass2(); // The constructor MyClass2() is undefined
There is an option there to generate constructor using fields.
Select the fields which you want the initialization for and you are done.
Related
I'm creating a new class which is vehicle. I'm expecting the only protected variables inherit to subclasses. But when I try to create Constructor with IDE, it is also using superclasses private variables? -Which is private String vehicleName- I'm not clearly understanding this situation. Shouldn't I use auto Concstructor?
public class Vehicle {
protected int capacityOfPassengers;
protected String mapOfRoute;
private String vehicleName;
public Vehicle(int capacityOfPassengers, String mapOfRoute,
String vehicleName) {
this.capacityOfPassengers = capacityOfPassengers;
this.mapOfRoute = mapOfRoute;
this.vehicleName = vehicleName;
}
}
public class LandVehicle extends Vehicle {
private String brand;
private int priceModel;
public LandVehicle(int capacityOfPassengers, String mapOfRoute,
String vehicleName, String brand, int priceModel) {
super(capacityOfPassengers, mapOfRoute, vehicleName);
this.brand = brand;
this.priceModel = priceModel;
}
}
Generally, a class has a default constructor, taking no arguments, IF no constructor has been provided by you.
When you subclass Vehicle with your LandVehicle, your LandVehicle is a type of Vehicle. This means that it inherits methods and field from its superclass, even if they are private. For the class LandVehicle these members are just not visible, but they are still present - otherwise it couldn't function properly. The private keyword is an access modifier, that changes visibility to the caller.
As a result, to instantiate a LandVehicle, you also must provide the required attributes of its superclass Vehicle (since there is no default, no-arg constructor in Vehicle). In your example, a LandVehicle without a name (from Vehicle) wouldn't make sense, since a LandVehicle is a Vehicle, which requires a name.
You cannot access vehicleName from LandVehicle. You just pass some string parameter to super constructor, and the super constructor sets the vehicleName. For example, you can't initialize this field inside LandVehicle class as this.vehicleName = vehicleName.
When I try to get the constructor to create an int it throws a: java.lang.NoSuchMethodException: int.<init>(int)
A very simplified version of what I'm trying to do is below:
Class myClass = int.class;
Constructor ctor = myClass.getConstructor(int.class);
I've tried the following as well:
Constructor ctor = myClass.getConstructor(Integer.TYPE);
Constructor ctor = myClass.getConstructor(Integer.class);
to end up with the same exception. What could be causing this?
EDIT:
Thanks for all the replies. I'm including the extended example below.
I'm trying to do the above while trying to invoke an unknown setter of an object, where I only have the value to pass to the setter as a String.
EDIT AFTER RESOLUTION
Please note that below code is only for clarity/context, and edited for brevity.
Thanks for the replies. What I really eventually needed was if there was a way to create a primitive (e.g. int) with methods related to reflection. The chosen answer provides a way using the corresponding wrapper class.
public class MyClass {
int field;
public void setField(int field) {
this.field = field;
}
}
public class Test {
public static void main(String... args) {
String value = "3"; // String of the the int value I want to pass to my setter as an argument when I invoke it via reflection
MyClass myObject = new MyClass();
Class objClass = myObject.getClass();
Method method = ... // Resolve the setter method using objClass.getMethods(); omitted here for brevity
Class[] paramTypes = method.getParameterTypes();
Class paramType = paramTypes[0]; // My setter method takes only one argument; so pick the first one
if (paramType.getName().equals("int")) {
Constructor ctor = paramType.getConstructor(int.class); // CAUSES EXCEPTION
Object instance = ctor.newInstance(value);
method.invoke(myObj, instance);
}
}
}
int is a primitive type and unlikely has the same kind of initialisation as reference types do (with a constructor). I don't think it has either int.<init>(int) or int.<int>() declared and available via Reflection API.
That said, you can do the trick with its wrapper class Integer because it has a constructor Integer(int) defined.
Constructor<Integer> constructor = Integer.class.getConstructor(int.class);
Integer integer = constructor.newInstance(3);
System.out.println(integer); // prints out 3
Let MyClass be the class represented by this java code:
public MyClass
{
private String foo;
private Integer bar;
public MyClass(byte[] contents) { ... }
}
Let myConstructor be the following Constructor instance:
Constructor myConstructor = MyClass.class.getDeclaredConstructor(byte[].class);
My question is the following
Does this code use reflection?
byte[] contents = new byte[]{0,1,2};
MyClass myInstance = myConstructor.newInstance(contents);
or is equivalent, once that myConstructor is instantiated, to the following code?
byte[] contents = new byte[]{0,1,2};
MyClass myInstance = new MyClass(contents);
The equivalence relation I'm thinking about is that .newInstance(byte[] contents) access directly to the constructor in the same way as the new and the only reflection operation is finding the constructor.
Kind regards
TLDR: Is there a way to force to a subclass to have an empty constructor when the super does not?
I need to be to initialize a non-serializable class, TravelTimeDataArray, from a serialized data container. The TravelTimeDataArray cannot be serialized because it does not implement the Serializable interface, lacks an empty constructor, and uses a non-serializable field of type Link.
public class TravelTimeDataArray implements TravelTimeData {
private final double[] timeSum;
private final int[] timeCnt;
private final double[] travelTimes;
private final Link link; //I'm not serializable
public TravelTimeDataArray(final Link link, final int numSlots) {
this.timeSum = new double[numSlots];
this.timeCnt = new int[numSlots];
this.travelTimes = new double[numSlots];
this.link = link;
resetTravelTimes();
}
//getters and setters
}
My first thought was to extend this as a serializable class. Instead of using a Link, I can use a serializable String of it's ID attribute and add the empty constructor.
public class SerialTravelTimeDataArray extends TravelTimeDataArray implements java.io.Serializable{
private final String linkId = null; // I am serializable
public SerialTravelTimeDataArray(){ }
public SerialTravelTimeDataArray(TravelTimeDataArray ttDA){
// intialize me using ttDA's data
}
// Methods to serialize the fields.
// Methods to populate super's fields from the deserialized data containers
}
Since the super does not have an empty constructor, I get an error with the subclass's empty constructor. Is there a way to force to a subclass to have an empty constructor when the super does not?
According to The Serializable Interface:
A Serializable class must do the following:
Implement the java.io.Serializable interface
Identify the fields that should be serializable (Use the serialPersistentFields member to explicitly declare them serializable
or use the transient keyword to denote nonserializable fields.)
Have access to the no-arg constructor of its first nonserializable superclass
A no-arg constructor of a object's first nonserializable superclass is need to have access because it will be called while deserializing the object. Otherwise, an exception will be thrown. Note that serializing a object do not call its superclass's default constructor and no exception will be thrown.
If extending a class is not a must, you can consider using encapsulation like follows:
public class Foo implements Serializable {
private final double[] timeSum;
private final int[] timeCnt;
private final double[] travelTimes;
private final String linkId;
private final transient TravelTimeDataArray ttDA;
public Foo(TravelTimeDataArray ttDA) {
this.ttDA = ttDA;
this.timeSum = ttDA.getTimeSum();
this.timeCnt = ttDA.getTimeCnt();
this.travelTimes = ttDA.getTravelTimes();
this.linkId = ttDA.getLink().getId();
}
// Methods
}
If you do not need to access TravelTimeDataArray in your class, you can skip the field transient TravelTimeDataArray ttDA. Hope this can help.
Enum constructors must be either private or package default, and protected or public access modifier is not allowed. Why so
Because an enum, by definition, has a fixed set of instances which are declared and constructed in the enum itself. Using the constructor from outside of the enum class itself thus doesn't make sense.
And AFAIK, an enum constructor is always, explicitely or implicitely, private.
From the Java tutorial:
The constructor for an enum type must be package-private or private access. It automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself.
It doesn't make sense to be able to create new instances of an enum, so the language prevents you from doing so!
Enum is not meant to be instantiated (by you).
http://docs.oracle.com/javase/tutorial/reflect/special/enumTrouble.html :
Tip: It is a compile-time error to attempt to explicitly instantiate an enum because that would prevent the defined enum
constants from being unique. This restriction is also enforced in
reflective code. Code which attempts to instantiate classes using
their default constructors should invoke Class.isEnum() first to
determine if the class is an enum.
The reason you can't dynamically extend an enum is that the instantiated values are compiled into the bytecode for the Class object:
public T[] getEnumConstants()
Returns the elements of this enum class or null if this Class object does not
represent an enum type.
As a result, any attempt to construct a new instance would not be able to passed onto the actual Class, since Class objects cannot be changed. If you want this behavior, you'll have to simulate it yourself, and give it some kind of unique value to represent each one, then have an ordinal counter, and finally a static map (or some other structure) to hold all the values.
public class MyEnum {
private static AtomicInteger nextOrdinal = new AtomicInteger(0);
private static Map<Integer, MyEnum> instances =
new HashMap<Integer, MyEnum>();
private int ordinal;
private String name;
public MyEnum(String name) {
super();
this.ordinal = nextOrdinal.incrementAndGet();
this.name = name;
instances.put(Integer.valueOf(this.ordinal), this);
}
public String name() {
return name;
}
public int ordinal() {
return ordinal;
}
public static Set<MyEnum> getEnumConstants() {
return Collections.unmodifiableSet(instances.values());
}
public static MyEnum fromInt(int ordinal) {
return instances.get(Integer.valueOf(ordinal));
}
public static MyEnum fromString(String name) {
for (MyEnum val : instances.values()) {
if (val.name().equals(name)) {
return val;
}
}
return null;
}
}
You'll probably also want a .equals and .hashcode method, as well as preventing the same name from being used more than once (which you could do in the constructor and throw an IllegalStateException or something if you have a duplicate name).