i have made a class like this
public class Item<IdType> {
public IdType id;
public String name;
}
public class Dealer<IdType> {
public IdType id;
public String name;
}
and a function in other class like this :
public <T> boolean deleteById(Class<Class<T>> modelClass, T id) {
daooperation();
return true;
}
what i want to do is when i call the function deleteById with parameter 1 is Item<Long> then parameter 2(id) should use Long datatype too
other example is deleteById with parameter 1 is Dealer<String> then parameter 2(id) should use String datatype too. how to parse parameter 1(modelClass) to function deleteById or shoud i change the parameter 1(modelClass) in deleteById?
please someone help me, show me how can i do that.
I think your methods should look more like this.
public static <I extends Item<T>, T> boolean deleteById(I item, T id) {
doSomething();
return true;
}
public static <D extends Dealer<T>, T> boolean deleteById(D dealer, T id) {
doSomething();
return true;
}
Object.Class method is your solution I guess
Due to the way type erasure and Java generics work, the best you can do is:
public class Test {
public static <T extends WithId<B>, B> boolean foo(T obj, B id) {
obj.id = id;
return true;
}
public static void main(String[] args) {
Bla<String> bar = new Bla<String>();
foo(bar, "123"); // Works
foo(bar, 123 ); // Fails
}
}
abstract class WithId<T> {
T id;
}
class Bla<T> extends WithId<T> {
// ...
}
Related
If I change (Inventory) to (T) it does not recognize getId().
public static <T> T getSelectedRow(Table table) {
T selectedItems = (T) table.getValue();
if (selectedItems != null) {
System.out.println("getSelectedRow id:"+ ((Inventory) selectedItems).getId());
return selectedItems;
}
How can I make it work as ((T) selectedItems).getId()
Table is vaadin7 and I use java 8.
I do not want to use Inventory, it should be generic so I could use different objects. Inventory is just one of them, some have getId() some not!
Because T is a placeholder for a type and as far as the compiler is concerned T does not have getId() or any other methods which are not part of Object. You can not do that.
However you could constraint T to <T extends Inventory>
If you indeed need getId:
public interface HasId {
long getId();
}
public class Inventory implements HasId {
#Override
public long getId() { return id; }
}
public static <T extends HasId> T getSelectedRow(Table table) {
T selectedItems = (T) table.getValue();
if (selectedItems != null) {
System.out.println("getSelectedRow id:"+ selectedItems.getId());
return selectedItems;
}
...
Or (without interface) a bit more ugly, breakable - when only getId is needed:
public static <T> T getSelectedRow(Table table, ToLongFunction<T> idGetter) {
T selectedItems = (T) table.getValue();
if (selectedItems != null) {
System.out.println("getSelectedRow id:"+ idGettter.apply(selectedItems));
return selectedItems;
}
...
Inventory inventory = getSelectedRow(table, Inventory::getId);
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;
}
}
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());
}
}
I have a generic class as follows:
public MyClass<T>{
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
}
I instantiate it as follows:
MyClass<String> myClass = new MyClass<String>();
When looking the getId() method through reflection (i == the index of the getId method):
myClass.getClass().getMethods()[i].getReturnType();
It will say that the return type is java.lang.Object.
I'm guessing I'm asking the impossible here, but, would it somehow be possible for the class to actually say java.lang.String in this case?
The reason I'm asking this is because I'm using App engine and it's Datastore. A simplified scenario: I got all my classes inheriting from MyClass and therefore they get a id with the type T, where T is either Long, String or Key. But the datastore thinks no matter what that the id field is an java.lang.Object, which is prohibited. Do I need to make classes like MyClassString, MyClassLong etc, or is there some way i can bypass this?
Thank you!
EDIT: After searching for another issue I had after "solving" this. I found this question actually mentioning my exact problem.
The type arguments for the parameterized type are lost at runtime through a process known as type erasure. At runtime there is no way to determine the method returns a String, since the actual type arguments used are not available.
Generic Faq
One way to work around this would be implement a generic interface, which would allow the objects to be used in a polymorphic manner:
Identifiable.java
public interface Identifiable<T> {
T getId();
void setId(T t);
}
Person.java
public class Person implements Identifiable<String> {
private String id;
#Override
public String getId() {
return id;
}
#Override
public void setId(String t) {
this.id = t;
}
public static void main(String[] args) {
Person person = new Person();
Method method = person.getClass().getMethods()[1]; //prints getId
System.out.println(method.getName());
System.out.println(method.getGenericReturnType()); //prints String
}
}
You could do this by storing a class variable within and returning this on request.
i.e.
public MyClass<T>{
Class<T> clazz;
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
MyClass(Class<T> clazz) {
this.clazz=clazz
}
public Class<T> getIdClass() { return clazz; }
}
Now to find out what type your class is you can just call getIdClass() on it and use that returned type. Generics will enforce that the type is set correctly when an instance of MyClass is created.
A little modification can be added to Tim B's solution, if you do not want parametrized constructor.
public class MyClass<T>{
Class<T> clazz;
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
public Class<?> getIdClass() {
if (id != null) {
return id.getClass();
} else {
return Object.class;
}
}
}
You can check it by
MyClass<String> myClass = new MyClass<String>();
myClass.setId("abc");
System.out.println(myClass.getIdClass());
I'm having some trouble understanding the following scenario.
I have a "generified" interface that is implemented by an abstract class and a concrete class that extends the abstract class.
The problem is that all the methods in the abstract class returning parametrized lists have lost their type so I'm getting a compilation error telling me that it cannot convert from object to the original List type.
Could anyone provide some insight?.
In the end what I would like is to have the a getId and setId method on the abstract class having a return type of java.lang.object or <T extends Object> and the concrete classes implementing their return type to whatever they want.
Here is the code for my different objects :
A generic interface
public interface MyInterface<T>{
public T getId();
public void setId(T id);
}
An abstract class implementing the interface
public abstract class MyAbstractClass<T> implements MyInterface<T>{
private List<String> texts;
private List<Integer> notes;
public List<String> getTexts(){
return texts;
}
public List<Integer> getNotes(){
return notes;
}
}
A Concrete class implementing the abstract class
public class MyConcreteClass implements MyAbstractClass<Integer>{
private Integer id;
public Integer getId(){
return this.id;
}
public void setId(Integer id){
this.id = id;
}
}
Some other class :
public class SomeOtherClass{
public void process(List<T extends MyAbstractClass> myClassList){
// Compilation error ->
// Type mismatch: cannot convert from element type Object to String
for(MyAbstractClass myObj : myClassList){
System.out.println("object Id : " + myObj.getId());
// Compilation error ->
// Type mismatch: cannot convert from element type Object to String
for(String txt : myObj.getTexts()){
}
}
}
}
When you use generic type MyAbstractClass<T> as raw type (MyAbstractClass), all generic-related stuff in declarations of its members is disabled (i.e. List<String> turns into List).
Therefore you need to declare an argument of your method as parameterized type. If you don't care about actual type parameter, use wildcard:
public void process(MyAbstractClass<?> myClass) { ... }
I think you need another interface. See here with MyAbstractClass implementing two interfaces MyInterface<T>, MyOtherInterface.
public static interface MyInterface<T> {
public T getId();
public void setId(T id);
}
public static interface MyOtherInterface {
public List<String> getTexts();
public List<Integer> getNotes();
}
public abstract class MyAbstractClass<T> implements MyInterface<T>, MyOtherInterface {
private List<String> texts;
private List<Integer> notes;
public List<String> getTexts() {
return texts;
}
public List<Integer> getNotes() {
return notes;
}
}
public static class MyConcreteClass extends MyAbstractClass<Integer> {
private Integer id;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
}
public class SomeOtherClass {
public void process(MyOtherInterface myClass) {
// NO Compilation error
for (String str : myClass.getTexts()) {
// some processing
}
}
}