Create a generic method with generic signature - java

i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?

Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {

public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();

Related

How to get the class of the genereric parameter of a Interface from the interface

I have this Interface:
public interface Test<T> {
default Class<?> getT() {
return T.getClass(); < --error
}
}
next i have a class that implements it:
static class ItemService implements Test<Item>{
}
And i want to get the 'Item' class from the 'ItemService' class
static ItemService service = new ItemService();
private static void k() {
System.out.println(service.getT());
}
Now one way to do it is this:
public interface Test<T> {
default Class<?> getT() {
return Type.type;
}
class Type {
public static Class<?> type;
}
}
Service:
static class ItemService implements Test<Item> {
public ItemService() {
Type.type = Item.class;
}
}
And it works fine but there is a problem,
When another class implement the interface:
static class OrderService implements Test<Order> {
public OrderService() {
Type.type = Order.class;
}
}
And i try:
static ItemService service = new ItemService();
static OrderService orderservice = new OrderService();
private static void k() {
System.out.println(service.getT());
}
I get the Order class and not the Item class
How can i make it work?
Classes inside interfaces are static, You can remove the default from the function and every class will need to implement this. example:
public interface Test<T> {
public Class<T> getT();
}
static class ItemService implements Test<Item> {
public Class<Item> getT() {return Item.class;}
}
static class OrderService implements Test<Order>{
public Class<Order> getT() {return Order.class;}
}
An alternative could be an abstract class.
public interface Test<T> {
public Class<T> getT();
}
abstract class AbstractTest<T> implements Test<T> {
private final Class<T> type;
AbstractItemService(Class<T> type) { this.type = type }
public Class<T> getT() {return type;}
}
class ItemService extends AbstractTest<Item> {
ItemService() { super(Item.class); }
// implement other things
}
class OrderService extends AbstractTest<Order>{
OrderService() { super(Order.class); }
// implement other things
}
Here is another option, if your implementation has an instance of T.
interface Test<T>{
T getT();
default Class<?> getClassOfT(){
return getT().getClass();
}
}

Mock the isAssignableFrom()

I am having two java class as below,
public class Class1{
private Object actionObject;
public Object getActionObject() {
return actionObject;
}
public void setActionObject(Object actionObject) {
this.actionObject = actionObject;
}
}
Second class
public class Class2 {
private Long id;
private int idver;
private int valueDate;
}
There are two statement as below,
Class1 deserializedValue = (Class1) event.getDeserializedValue();
Class2.class.isAssignableFrom(deserializedValue.getActionObject().getClass());
I want to mock the second statement
Class2.class.isAssignableFrom(deserializedValue.getActionObject().getClass());
how can i do this?
For testing purposes you can use a strategy pattern. You just need an interface or an abstract class with two different implementations. One of them is the mock implementation, something like this:
public interface EventStrategy {
// More methods...
boolean isAssignableFrom(final Object object);
}
public class MyEvent implements EventStrategy {
public boolean isAssignableFrom(final Object object) {
return Class2.class.isAssignableFrom(object.getClass());
}
}
public class MockEvent implements EventStrategy {
public boolean isAssignableFrom(final Object object) {
return true;
}
}

How to instantiate an interface object?

I have an abstract class and several implementations.
Based on the implementation class, I'd like to execute a method and instantiate the implementation class itself with new constructor.
Of course the following won't work as the class is Abstract, and I cannot change this fact. But how could I pass the "logic" how to create each implementation object to the method prepareList()? Especially regarding design decisions.
abstract class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass {
}
class SecondClass extends AbstractClass {
}
class MyService {
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = new AbstractClass(); //does of course not work with abstract class
obj.setId();
obj.setName();
obj.setAge();
collection.add(obj);
}
return collection;
}
}
abstract class Fruit { String name; int weight; }
class Apple extends Fruit {}
class Orange extends Fruit {}
class FruitFactory() {
public Fruit create(Data data) {
if ("apple" == data.getFruitName()) return new Apple();
else if ("orange" == data.getFruitName()) return new Orange();
else throw new UnsupportedOperationException();
}
}
class FruitService {
private FruitFactory factory = new FruitFactory();
void execute(Data data) {
List<Fruit> list = prepareList(data);
}
List<Fruit> prepareList(Data data) {
List<Fruit> fruits = new ArrayList<>();
for (Some value : data) {
Fruit fruit = factory.create(data);
// set fields
fruits.add(fruit);
}
return fruits;
}
}
Okay I have a suggestion why don't you do like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Data{
}
class Myservice{
void execute(Data data) {
List<FirstClass> list = prepareList(data, new FirstClass());//notice change
//process list
}
List<AbstractClass> prepareList(Data data, AbstractClass abstractClassObj) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
/* AbstractClass obj = new AbstractClass();*/ //does of course not work with abstract class
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
BY this your object creation and logic will also remain at different places. It will also be helpful if in future you have another class extending abstract class
or you can have some factory and pass factory object to your method or service class and get instance in the method you want.
Sorry In a hurry I missed the loop thing with factory try some thing like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Factory{
public AbstractClass getInstance( Class<? extends AbstractClass> clazz){
if(clazz.getSimpleName().equals(FirstClass.class.getSimpleName())){
return new FirstClass();
}else {
return new SecondClass();
}
}
}
class Data{
}
class Myservice{
private final Factory factory;
public Myservice(Factory factory){
this.factory = factory;
}
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);//notice change
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = factory.getInstance(clazz);
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
Obviously you can modify example as per needs you can use enum sort of things. This is just basic example

Java Interface containing an empty Enum

I'm trying to prepare an interface i want to implement for Datamodel-Classes.Therefor i want to use an enum inside the interface so i know i need to implement it later.
Example:
public interface MyModelInterface {
public enum Field;
public Object get(Field field);
public void set(Field field, Object value);
}
The expected implementation:
public class MyModel implements MyModelInterface {
public enum Field {
ID("id"),
Name1("Name1"),
Name2("Name2");
private String field;
private Field(String field) {
this.field = field;
}
}
public Object get(Field field) {
//...
}
public void set(Field field, Object value){
//...
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(MyModel.Field.ID));
System.out.println(myModel.get(MyModel.Field.Name1));
}
}
Since I don't know which fields the model will contain until I implement it.
I did some research and figured that enum can't be extended, so i am aware of that.
is there any way to archive this or any kind of workaround?
i don't want to use String Parameters on the getter/setter Methods to avoid using wrong values.
Thanks in advance for any suggestion.
Update:
So this is what worked for me: Splitting the interface/class in three parts, including an abstract class:
Interface:
public interface MyModelInterface<E extends Enum<E>> {
public Object get(E field);
public void set(E field, Object value);
}
Abstract Class:
public abstract class MyAbstractModel<E extends Enum<E>> implements MyModelInterface<E>{
protected final EnumMap<E, Object> fields;
public MyAbstractModel(Class<E> enumKlazz) {
fields = new EnumMap<>(enumKlazz);
}
#Override
public Object get(E field) {
return fields.get(field);
}
#Override
public void set(E field, Object value) {
this.fields.put(field, value);
}
}
Class(where i actually archive my goal):
public class MyModel extends MyAbstractModel<MyModel.Field> {
public MyModel() {
super(MyModel.Field.class);
}
public enum Field {
ID("ID"),
Name1("NAME1"),
Name2("NAME2"),
Age("AGE"),
;
private final String field;
private Field(String field) {
this.field = field;
}
public String getName() {
return field;
}
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(Field.Name1));
}
}
Interface fields are static and final implicitly.
What you could do is to have an interface method returning Enum<?>, and your classes implementing it.
For instance:
interface Foo {
public Enum<?> getEnum();
}
class Bar implements Foo {
enum Blah {
INSTANCE;
}
public Enum<?> getEnum() {
return Blah.INSTANCE;
}
}
Edit
Not completely sure I understand your question update, but here's a solution that will de-couple returning a specific enum instance from an enum, by means of two interfaces.
The example is self-contained in a Main class.
public class Main {
public static void main(String[] args) {
System.out.println(new Bar().getEnumField().name());
}
static interface IHasEnum {
public Enum<? extends IMyEnum> getEnumField();
}
static interface IMyEnum {
public Enum<? extends IMyEnum> getField();
}
static class Bar implements IHasEnum {
enum Blah implements IMyEnum {
DEFAULT_INSTANCE,
THE_FIELD;
public Enum<? extends IMyEnum> getField() {
return THE_FIELD;
}
}
public Enum<? extends IMyEnum> getEnumField() {
return Blah.DEFAULT_INSTANCE.getField();
}
}
}
Output
THE_FIELD
Note
The trick here is to add a "default" instance to the enum (DEFAULT_INSTANCE), so the getField method is an instance method, hence overriding the one declared in the IMyEnum interface.
Again, not entirely sure this addresses your issue.
What you are describing is an EnumMap<E, T> - which functions like an array, with that same get-
public class MyModelBase<E extends Enum<E>> {
private final Class<E> enumKlazz;
private final EnumMap<E, Object> fields;
public MyModelBase(Class<E> enumKlazz) {
this.enumKlazz = enumKlazz;
fields = new EnumMpa<>(enumKlazz);
}
public Object get(E field) {
return fields.get(field);
}
public void set(E field, Object value) {
fields.put(field, value);
}
}
enum UserField { id, surname, name, age };
MyModelBase<UserField> userModel = new MyModelBase<>(UserField.class);
userModel.set(UserField.surname, "X");
Because of type erasure the enum map needs the class. Above the enum class is also stored as field, as some static Enum methods need the enum class. For iterating, and so on.
Java generics will be the best solution.
Lets assume, you don't know the contents of the Field as mentioned.
Create a generic interface like this:
public interface MyModelInterface<T> {
public T get();
}
Then create a class Field like this:
public class Field {
private String id;
private String name1;
private String name2;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
}
and then your model class will look like
public class MyModel implements MyModelInterface<Field> {
#Override
public Field get() {
Field field = new Field();
field.setId("ID");
field.setName1("Name1");
field.setName2("Name2");
return field;
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get().getId());
System.out.println(myModel.get().getName1());
System.out.println(myModel.get().getName2());
}
}

Java, how to stop inheriting classes from calling a particular abstract class constructor, apart from one of them?

I have an abstract class and several concrete classes which extend it.
The abstract class has two constructors. I want one of the constructors to only be callable in one particular concrete class.
(I do know about the enum pattern for Java state machines, but two levels of subclassing (and immutable POJOs) work better for the problem I'm solving.)
public abstract class SuperState {
public final long mValue;
protected SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
}
public class FirstState extends SuperState {
public FirstState() { super(0); }
...
}
public class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
...
}
public class ThirdState extends SuperState {
public ThirdState(SuperState last) { super(last); }
...
}
I want to make it a compile-time (or at least runtime) error for any subclass (apart from FirstState) to call the SuperState(long value) constructor.
Could I find out the type of the concrete class being constructed in the SuperState constructor, and throw a runtime exception if it's not as expected?
Is there a was of having a "preferred" concrete class for an abstract class, such that it has some form of extra access?
I think you don't know clearly what you're doing.
You're saying that SuperState has a constructor which is only callable from one specific implementation. Why? Is that subclass special? Why shouldn't other implementation call that?
If FirstState is so special, maybe you want to have it as an internal class:
public abstract class SuperState {
public final long mValue;
private SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
public static class FirstState {
//Can call SuperState(long) from here
}
}
If this doesn't seem appropriate to you, then probably you should leave both constructors open.
If, as it seems to me, you're making a chain-like structure, then you probably don't even want to have FirstState as an accessible class:
public abstract class SuperState {
public final long mValue;
private SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
private static class FirstState extends SuperState {
private FirstState() { super(0); }
}
public static SuperState getFirstState() { return new FirstState(); }
}
One way I can think of, though I find it ugly :
protected SuperState(long value)
{
if (!this.getClass().getName().equals("SomeConcreteClassName"))
throw new SomeException ();
mValue = value;
}
Though Tom's comment about putting the FirstState class in the same package as SuperState and using package private access sounds better.
I think the only way to achieve it is to use analog of "friend". The trick is to have private Value class in the FirstState which is possible to construct only by FirstState. Other classes can see the FirstState.Value class, but cannot instantiate it.
abstract class SuperState {
public final long mValue;
protected SuperState(FirstState.Value value) { mValue = value.value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
}
class FirstState extends SuperState {
public static class Value { private Value() {} }
private static Value value = new Value();
public FirstState() { super(value); }
}
class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
}
You can do it with default access modifier like this:
package a;
public abstract class SuperState {
public final long mValue;
SuperState(long value) { mValue = value; } // constructor has default access modifier
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
}
package a;
public class FirstState extends SuperState {
public FirstState() { super(0); }
...
}
package b;
// is not able to access constructor SuperState(long) ie. calling contructor
// SuperState(long) will result in compile time error
public class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
...
}

Categories