I'm working with som generated classes which I need to set the member data of at creation. The generated classes only have a default constructor, and no setters for the member data. It doesn't make sence to modify the classes, as the modification will be overwritten, when I regenerate the classes again (It's a shared project, so somebady else might also overwrite the generated classes).
Is it possible to do something like this.
Example:
public class A{
private int value;
}
public class B{
private A a;
public void initA()
{
a = new A(){
value = 9;
};
}
}
Something like this will allow you to set the value of the private field A.value:
class A {
private int value;
#Override
public String toString() {
return "Value of my private field: " + value;
}
}
class MutableA {
public A a;
private Field value;
public MutableA(A a) {
this.a = a;
try {
this.value = A.class.getDeclaredField("value");
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
this.value.setAccessible(true);
}
void setValue(int value) {
try {
this.value.set(a, value);
} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
You can use it like this:
public class Test{
public static void main(String[] args) {
A a = new A();
System.out.println("before mutation:" + a);
MutableA mutableA = new MutableA(a);
mutableA.setValue(1);
System.out.println("before mutation: " + a);
}
}
Output:
before mutation: Value of my private field: 0
before mutation: Value of my private field: 1
If you only have no argument constructors you will have to use setters to set private members.
public class A{
private int value;
static{
value=10;
}
}
public class B{
private A a;
public void initA()
{
a = new A();
}
}
Related
I will give the example java code for this circumstances:
// StateEntity interface define:
public interface StateEntity extends IDEntity { // the IDEntity define getId & setId
static int processBitState(int state, boolean op, int pos) {
if (op) {
state = Bits.set(state, pos);
} else {
state = Bits.clear(state, pos);
}
return state;
}
static <E extends Enum<E>, T extends StateEntity> int gatherState(Class<E> enumType, int state, #NotNull T data) {
try {
Method getJsonFieldName = enumType.getMethod("getJsonFieldName");
Method getPosition = enumType.getMethod("getPosition");
BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (E bitSet : EnumSet.allOf(enumType)) {
String fieldName = (String) getJsonFieldName.invoke(bitSet);
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getName().equals(fieldName)) {
Method reader = propertyDescriptor.getReadMethod();
Boolean value = (Boolean) reader.invoke(data);
state = processBitState(state, value, (Integer) getPosition.invoke(bitSet));
break;
}
}
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | IntrospectionException e) {
e.printStackTrace();
}
return state;
}
<E extends Enum<E>> Class<E> getStateType();
Integer getState();
void setState(Integer state);
}
// Impl class:
public class StateEntityClass implements StateEntity {
Long id;
Integer state;
#Override
public Long getId() {
return id;
}
#Override
public void setId(Long id) {
this.id = id;
}
#Override
public <E extends Enum<E>> Class<E> getStateType() {
return (Class<E>) (BitSet.class);
}
#Override
public Integer getState() {
return state;
}
#Override
public void setState(Integer state) {
this.state = state;
}
public enum BitSet {
ACTIVATION(0),
FREEZE(1),
UPDATE(2);
private final int position;
BitSet(int v) {
position = v;
}
#NotNull
public String getName() {
return name().toLowerCase().replaceAll("_", "-");
}
#NotNull
public String getJsonFieldName() {
return NameConverter.snakeCaseToCamelCase("is_" + name().toLowerCase());
}
public int getPosition() {
return position;
}
}
}
// used:
public class Main {
public static void main(String[] args) {
StateEntityClass e = new StateEntityClass();
// first method, this statement error:
e.setState(StateEntity.gatherState(e.getStateType(), e.getState() == null ? 0 : e.getState(), e));
// second method, but this statement ok:
e.setState(StateEntity.gatherState(StateEntityClass.BitSet.class, e.getState() == null ? 0 : e.getState(), e));
// why?? how change the first method
}
}
I have some class implements StateEntity, so I must use the first method for generic.
How do I change my code to use the first method?
What is the Java way to process these circumstances problems?
The Enum content is unrelated, the StateEntity implements class has self Enum for the state.
The problem I hope to solve is how to deal with an Enum uniformly in Java. This Enum has a unified structure and a unified interface, but the Enumerator contained is different. See the above question for the specific situation. After #tgdavies' prompt, I moved the type parameter from the method definition to the interface definition, which solved the problem. Later, under the reminder of #Guillaume F., I further optimized the use of Enum. Thank you all for participating
I'm trying to create a "bank account" with its operations. Some of them are:
bank addition : class Ajout
bank withdrawal : class Retrait
There are the bank balance variable named solde and amount named montant
The AjoutOuRetrait class is the mother class (means AdditionOrWithdrawal)
Now what I expect in my main class is the following:
c1.operation(new Ajout(750, new Date(01,01,2017)));
c1.operation(new Retrait(50, new Date(05,03,2017)));
System.out.println(c1.getSolde()); // result -> 700
public class AjoutOuRetrait {
public int montant;
public Date date;
public AjoutOuRetrait(int montant, Date d) {
this.montant = montant;
this.date = d;
}
public class CompteBancaire {
private String id;
private Banque banque;
private int solde;
public CompteBancaire(String id, Banque b) {
this.id = id;
this.banque = b;
}
public void operation(AjoutOuRetrait aor){
this.solde = aor.montant;
}
more the getters and setters that I omitted.
public class Retrait extends AjoutOuRetrait {
public Retrait(int montant, Date d) {
super(montant, d);
}
}
public class Ajout extends AjoutOuRetrait{
public Ajout(int montant, Date d) {
super(montant, d);
}
I was thinking on a way to differentiate (with conditional statement) which child class I call in argument of operation() method , whether it is Retrait (WithDrawal) -- or Ajout(Additional) ++
You might check the child type in operation like.
public void operation(AjoutOuRetrait aor){
if(aor instanceof Ajout) {
this.solde += aor.montant;
} else if (aor instanceof Retrait) {
this.solde -= aor.montant;
}
}
or split them
public void operation(Ajout a){
this.solde += a.montant;
}
public void operation(Retrait r){
this.solde -= r.montant;
}
Also you might get the value used as right operand of your operation like
public class AjoutOuRetrait {
public int getValue() {
return this.montant;
}
}
public class Retrait {
#Override
public int getValue() {
return -this.montant;
}
}
public void operation(AjoutOrRetrait aor) {
this.solde += aor.getValue();
}
Say I have class AccountPojo and GetAccountPojo with its setter and getter methods as below.
public class AccountPojo {
private String dataList;
private String dataSet;
public String getDataList() {
return dataList;
}
public void setDataList(String dataList) {
this.dataList = dataList;
}
public String getDataSet() {
return dataSet;
}
public void setDataSet(String dataSet) {
this.dataSet = dataSet;
}
}
public class GetAccountsPojo {
private String accountId;
private int noOfAccounts;
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public int getNoOfAccounts() {
return noOfAccounts;
}
public void setNoOfAccounts(int noOfAccounts) {
this.noOfAccounts = noOfAccounts;
}
}
Now I have class Test as below
public Class Test {
public static void main(String[] args) {
Class cls = Class.forName("com.org.temp."+ClassName); // ClassName(AccountPojo/GetAccountPojo) here I know already which class is getting called.
Object clsInstance = (Object) cls.newInstance();
System.out.println("The cls is==" + cls+" and classInstance is=="+clsInstance);
// Here I want to access getter and setter methods of AccountPojo and GetAcoountPojo dynamically, no hard coding
}
}
Have you tried getting all the methods of the invoked class and filtering out only the getter methods by name and invoking them?
Method[] methods = cls.getClass().getDeclaredMethods();
for (Method m: methods) {
if(m.getName().startsWith("get")) {
m.invoke(clsInstance);
}
}
This solves our half problem, as getters are invoked without any arguments. But if you need to invoke a setter method you need to specify arguments. Ex, To invoke a setter which accepts string argument method as below:
m.invoke(clsInstance, "some string argument");
One solution to could be make all the setters accept an object type value and typecast them while assigning it to actual class variables.
Now your pojo classes will look as below:
public class AccountPojo {
private String dataList;
private String dataSet;
public String getDataList() {
return dataList;
}
public void setDataList(Object dataList) {
this.dataList = (String) dataList;
}
public String getDataSet() {
return dataSet;
}
public void setDataSet(Object dataSet) {
this.dataSet = (String)dataSet;
}
}
public class GetAccountsPojo {
private String accountId;
private int noOfAccounts;
public String getAccountId() {
return accountId;
}
public void setAccountId(Object accountId) {
this.accountId = (String) accountId;
}
public int getNoOfAccounts() {
return noOfAccounts;
}
public void setNoOfAccounts(Object noOfAccounts) {
this.noOfAccounts = (int) noOfAccounts;
}
}
Add below code to your main method:
for (Method m: methods) {
if(m.getName().startsWith("get")) {
m.invoke(clsInstance);
}
if(m.getName().startsWith("set")) {
m.invoke(clsInstance, "any argument to be passed here");
}
}
Don't use raw class. If you know which class is called already, use typed class.
try {
AccountPojo obj = AccountPojo.class.newInstance();
Method setDataList = AccountPojo.class.getMethod("setDataList");
setDataList.setAccessible(true); // This is important if you want to access protected or private method. For public method you can skip
setDataList.invoke(obj, "123");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
Currently, I'm receiving this JSON input, which I have no control whatsoever:
{
"A" : {
"B" : {
"B" : [{
"Whatever" : "String",
"Number": 123
}
],
"SiblingObject" : true
}
}
}
Basically, I want to deserialize the B array that's inside the B object directly into the A class without having to create another extra class to wrap the B object. Something like this:
public class A {
private List<B> bList;
public List<B> getB() {
return bList;
}
#JsonProperty("B")
public void setB(List<B> bList) {
this.bList = bList;
}
}
I've tried doing
public class A {
private List<B> bList;
public List<B> getB() {
return bList;
}
#JsonProperty("B")
public void setB(Map<String, Object> bList) {
this.bList = (List<B>) bList.get("B");
}
}
but to no avail.
Any ideas?
There is one way of doing it. However, it will require traversing the input JSON twice.
In first pass, you create the normal A instance without the List.
In second pass, you use Jackson's node traversal to reach the correct B object and parse from there.
See the code below:
public class WrapperJsonTest {
public static void main(String[] args) {
ObjectMapper om = new ObjectMapper();
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("wrapper.json");
A a = null;
try {
a = om.readValue(in, A.class);
} catch (Exception e){
e.printStackTrace();
}
in = Thread.currentThread().getContextClassLoader().getResourceAsStream("wrapper.json");
try {
JsonNode node = om.readValue(in, JsonNode.class).get("B").get("B");
JsonParser parser = node.traverse();
List<B> bList = om.readValue(parser, List.class);
a.setB(bList);
System.out.println(a.isSibling());
System.out.println(a.getB());
} catch (Exception e){
e.printStackTrace();
}
}
#JsonIgnoreProperties
public static class A {
#JsonIgnore
private List<B> bList;
private boolean sibling;
public List<B> getB() {
return bList;
}
public void setB(List<B> bList) {
this.bList = bList;
}
public boolean isSibling() {
return sibling;
}
public void setSibling(boolean sibling) {
this.sibling = sibling;
}
}
public static class B {
private String whatever;
public String getWhatever() {
return whatever;
}
public void setWhatever(String whatever) {
this.whatever = whatever;
}
#Override
public String toString() {
return whatever;
}
}
}
Given
class A {
public static A newInstance(int x) { ... }
}
And several classes containing static fields of type A
class B1 {
public static A MIN = A.newInstance(10);
}
class B2 {
public static A MIN = A.newInstance(15);
}
I would like to parameterize a class with B1 or B2 to get MIN field of type A from class B in the class C:
class C <T, P> {
private T t = ???;
}
When C<A, B1> c = new C(); what should be placed instead ??? to get B1.MIN?
Is it possible?
EDIT:
Thank you for the answers, I have upvoted both.
I have arrived simply at
class C <T, P> {
private T t;
public C(T min) {
this.t = min;
}
}
This will be just C<A, B1> c = new C<A, B1>(B1.MIN); because as you can see it is hard to avoid a constructor for C taking an instance of B1 or smth like that. But in this case B1 at least not instantiated.
You can use an interface to achieve this behavior:
class A {
public static A newInstance() { return new A(); }
}
interface HasMin {
public static A MIN = null;
}
class B1 implements HasMin {
public static A MIN = A.newInstance();
}
class B2 implements HasMin {
public static A MIN = A.newInstance();
}
class C<T extends HasMin> {
private A t = T.MIN;
}
Then you can create: C<B1> and C<B2> and use both.
As Tom suggested in the comments below, this approach is limited to use static fields. An even better approach would be:
public class Play {
public static void main(String[] args) {
B1 b1 = new B1();
C<B1> c = new C<>(b1);
System.out.println(c.getA()); // prints: A{ x=10 }
B2 b2 = new B2();
C<B2> c2 = new C<>(b2);
System.out.println(c2.getA()); // prints: A{ x=20 }
}
}
class A {
private int x;
public A(int x) {
this.x = x;
}
#Override
public String toString() {
return "A{ x=" + x + " }";
}
public static A newInstance(int x) {
return new A(x);
}
}
interface GetMin {
public A getMin();
}
class B1 implements GetMin {
public A MIN = A.newInstance(10);
#Override
public A getMin() {
return MIN;
}
}
class B2 implements GetMin {
public A MIN = A.newInstance(20);
#Override
public A getMin() {
return MIN;
}
}
class C<T extends GetMin> {
private A a = null;
public C(T t) {
a = t.getMin();
}
public A getA() {
return a;
}
}
I would forget static and have a concrete instance of an interface:
public interface Bounds<T> {
T min();
}
The concrete instance could be singleton, so next best thing to a static:
public enum B implements Bounds<A> {
INSTANCE;
private final A min = A.newInstance(10);
#Override
public A min() {
return min;
}
}
C then defined like so:
public class C<T, P extends Bounds<T>> {
private T min;
public C(P bounds) {
min = bounds.min();
}
public T getMin() {
return min;
}
}
Usage:
C<A, B> c = new C(B.INSTANCE);
Self describing
Maybe you don't want this meta data type (B), maybe you want types to describe themselves. So C could be defined for types that can describe their own bounds:
public class C<T extends Bounds<T>> {
private T min;
public C(T anyT) {
min = anyT.min();
}
public T getMin() {
return min;
}
}
Usage:
C<A> c = new C(A.zero); //any A will do
Where A is:
public class A implements Bounds<A>{
public final static A zero = A.newInstance(0);
private final static A min = A.newInstance(10);
public static A newInstance(int x) {
return new A(x);
}
private int x;
public A(int x) {
this.x = x;
}
#Override
public A min() {
return min;
}
}