So heres my problem. I have two classes...SingularEntity and a ListEntity. As the name suggests, SingularEntity represents an Entity and a ListEntity represents a List of Singular Entities....the list obviously has more common properties than the SingularEntity itself. So I have an AuthorizationEntity which extends the SingularEntity class
public class SingularEntity{
}
public class AuthorizationEntity extends SingularEntity{
}
Now I have a single ListEntity which represents a List of any SingularEntities
public class ListEntity{
public List<? extends SingularEntity> data;
public ListEntity(List<? extends SingularEntity> data){
this.data = data;
}
}
Now, I want to use reflection to populate a list always....and I always run into an error in the results.add method. Says that method List.add(CAP#1) is not applicable. Any help is gladly appreciated
public List<? extends SingularEntity> build() {
List<? extends SingularEntity> results = new ArrayList<SingularEntity>();
try {
Constructor javaBeanClassConstructor =
(Constructor) DTOClass.getDeclaredConstructors()[0];
Class<?>[] constructorParameterTypes =
javaBeanClassConstructor.getParameterTypes();
for (Object[] columns : lstInput) {
Object[] constructorArgs = new Object[constructorParameterTypes.length];
for (int j = 0; j < columns.length; j++) {
Object columnValue = columns[j];
Class<?> parameterType = constructorParameterTypes[j];
// convert the column value to the correct type--if possible
constructorArgs[j] = ConversionManager.getDefaultManager()
.convertObject(columnValue, parameterType);
}
*results.add(javaBeanClassConstructor.newInstance(constructorArgs));*
}
}catch(Exception ex){
}
return results;
}
You should parameterize your ListEntity class
public class ListEntity<T extends SingularEntity>{
public List<T> data;
public ListEntity(List<T> data){
this.data = data;
}
}
The problem here is that you've defined a List<? extends SingularEntity>, so you cannot add to this List. Why not? Because to the compiler, this List could be of anything that extends SingularEntity, say a new MultipleEntity class. Java cannot allow you to add any arbitrary SingularEntity to any List of any possible subclass of SingularEntity.
To add to the List, just use a List<SingularEntity>.
Related
I have a problem with Java's Generic System.
In my program is a wrapper for lists, that should have a method to return it's inner list:
public class Wrapper<T, S extends List<T>> {
private S list;
public Wrapper(S list) {
this.list = list;
}
public S get() {
return list;
}
}
Then there is a Context that holds a Map with different Wrappers and a method that returns the list of the wrapper associated with the id:
public class Context {
private Map<String, Wrapper> map;
public Wrappers() {
map.put("a", new Wrapper(ArrayList<String>());
map.put("b", new Wrapper(LinkedList<Integer>());
}
public <T, S extends List<T>> S getList(String id) {
return map.get(id).get();
}
}
Now when I call getList() I want to have a compiler warning or at least a way to realise an error before a ClassCastException gets thrown.
public class Receiver {
public doSomething() {
Context c = new Context();
c.createWrappers();
// Ok
ArrayList<String> list1 = c.getList("a");
LinkedList<Integer> list2 = c.getList("b");
// Compiler error or some way do check in getList().
ArrayList<Integer> list3 = c.getList("a");
LinkedList<String> list4 = c.getList("b");
}
}
I've actually tried a lot of things like changing the Wrapper definition to:
public class Wrapper<T, S extends List>
But when I want to implement the get() function I run into a problem I can either define the function like this:
public List<T> get() {
return list;
}
or like this
public S get() {
return list;
}
In the first example it would still be possible to do this.
public doSomething() {
//...
LinkedList<String> list = c.getList("a");
}
and in the second example it would be possible to do this.
public doSomething() {
//...
ArrayList<Integer> list = c.getList("a");
}
Is there any way to define the get method in a way like this?
public S<T> get() {
return list;
}
It seems to me like there is no way to check both the type of the list and the type of the elements at the same time.
The compiler has no way of knowing what return type is associated with the particular string you passed (strings cannot be made type-safe).
However, you could replace strings with type-safe marker objects:
class ListId<T> {
public ListId(string name) { ... }
public static final ListId<ArrayList<String>> A = new ListId<>("a");
public static final ListId<LinkedList<Integer>> B = new ListId<>("b");
}
public T getList<T>(ListId<T> id)
At first glance, I would have expected to be able to cast
ArrayList<Class<? extends Interface1>>
to
ArrayList<Class<?>>
since the second is clearly a less restrictive version of the first. However, the following code does not compile:
import java.util.ArrayList;
public class TypeInvocationConversionTest
{
private static ArrayList<Class<? extends Interface1>> classList;
private static ArrayList<Class<?>> lessRestrictiveClassList;
public static void main(String[] args)
{
classList = new ArrayList<Class<? extends Interface1>>();
lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
}
private interface Interface1 {}
}
but produces the error
TypeInvocationConversionTest.java:12: inconvertible types
found : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList<java.lang.Class<?>>
lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
^
I don't think it's unreasonable to want to convert these two types: for motivation, here's a short program that's closer to what I'm actually dealing with (this code does not compile):
import java.util.ArrayList;
public class Mammal
{
public void produceMilk() {}
}
public class Reptile
{
public void layEggs() {}
}
public interface Species
{
String getSpeciesName();
}
public class Dog extends Mammal
implements Species
{
#Override
public String getSpeciesName()
{
return "Canis lupus familiaris";
}
}
public class Cat extends Mammal
implements Species
{
#Override
public String getSpeciesName()
{
return "Feles catus";
}
}
public class Boa extends Reptile
implements Species
{
#Override
public String getSpeciesName()
{
return "Boa constrictor";
}
}
public class Panel3 extends Reptile
implements Species
{
#Override
public String getSpeciesName()
{
return "Dromiceiomimus brevitertius";
}
}
public class AnimalFunTime
{
public static void main(String[] args)
{
ArrayList<Class<? extends Mammal>> listOfMammals;
ArrayList<Class<? extends Reptile>> listOfReptiles;
ArrayList<ArrayList<Class<?>>> matrixOfAnimals;
listOfMammals.add(Dog.class);
listOfMammals.add(Cat.class);
listOfReptiles.add(Boa.class);
listOfReptiles.add(Panel3.class);
///////////////////////////////////////////////////////////////////////////
// The following two lines cause an error. //
///////////////////////////////////////////////////////////////////////////
matrixOfAnimals.add( (ArrayList<Class<?>>) listOfMammals);
matrixOfAnimals.add( (ArrayList<Class<?>>) listOfReptiles);
// Get milk.
for (int i = 0 ; i < listOfMammals.size() ; i++) {
listOfMammals.get(i).produceMilk();
}
// Get eggs.
for (int i = 0 ; i < listOfReptiles.size() ; i++) {
listOfReptiles.get(i).layEggs();
}
// Display all the animals' names.
for (int j = 0 ; j < matrixOfAnimals.size() ; j++) {
ArrayList<Class<?>> currentFamily = matrixOfAnimals.get(j);
for (int i = 0 ; i < currentFamily.size() ; i++) {
Class<?> currentAnimal = currentFamily.get(i);
if (Species.isAssignableFrom(currentAnimal) {
System.out.println(currentAnimal.getSpeciesName());
}
else
{
throw new SpeciesNotImplementedException("Please tell us the animal's name!");
}
}
}
}
}
As the comment says, this code doesn't compile because I am unable to make a list that contains both ArrayList<Class<? extends Mammal>> and ArrayList<Class<? extends reptile>> objects. If I could cast those both to ArrayList<Class<?>>s, then that would be fine. Is there a way to do the cast so this sort of thing works?
One of the reasons this doesn't (and shouldn't) work is that lessRestrictiveClassList would reference the same list object as classList. So, if you add an object of type Class<?> (where ? does not extend Interface1) to that list, suddenly the contract of classList is broken:
ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();
// assume this is allowed:
ArrayList<Class<?>> lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
// now add an element to the less restrictive list
lessRestrictiveClassList.add(String.class);
// and obtain it from the original list
// this code will crash, because String does not implement Interface1
Class<? extends Interface1> cls = classList.get(0);
The last line will get you in big problems, because it can lead to unexpected failure of code.
Instead of referencing the array list twice, you should make a copy to the less restrictive list:
ArrayList<Class<? extends Interface1>> classList = new ArrayList<>();
ArrayList<Class<?>> lessRestrictiveClassList = new ArrayList<>();
lessRestrictiveClassList.addAll(classList);
Forget the generics and cast to raw type ArrayList.
ArrayList<ArrayList> matrixOfAnimals = new ArrayList<>();
matrixOfAnimals.add(listOfMammals);
since the second is clearly a less restrictive version of the first.
It is not. List<A> is not a subtype of List<B> even if A is a subtype of B. Heuster demonstrated why it's unsafe.
If you don't need to add elements using the second list reference, you should use ArrayList<? extends Class<?>> instead. You can convert ArrayList<Class<? extends Interface1>> to that.
You can do the cast you want by doing two cast in a row:
lessRestrictiveClassList = (ArrayList<Class<?>>) (ArrayList<?>) classList;
This compiles.
I have a class for example
public class Example<T> {...}
I would like to instantiate class Example with a specific type class which I know. Pseudocode would look something like that
public Example<T> createTypedExample(Class exampleClass, Class typeClass) {
exampleClass.newInstance(typeClass); // made-up
}
So that this would give me same result
Example<String> ex = new Example<String>();
ex = createTypedExample(Example.class, String.class);
Is it possible in Java?
Since, the return type i.e. the class of the new instance is fixed; there's no need to pass it to the method. Instead, add a static factory method to your Example class as
public class Example<T> {
private T data;
static <T> Example<T> newTypedExample(Class<T> type) {
return new Example<T>();
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Now, here's how you would create generic Example instances.
// String
Example<String> strTypedExample = Example.newTypedExample(String.class);
strTypedExample.setData("String Data");
System.out.println(strTypedExample.getData()); // String Data
// Integer
Example<Integer> intTypedExample = Example.newTypedExample(Integer.class);
intTypedExample.setData(123);
System.out.println(intTypedExample.getData()); // 123
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java Generics: Cannot cast List<SubClass> to List<SuperClass>?
I want to create function on some base class, that create it inheritance classes.
I have try this:
class BaseFormat
{
// Some variables
public BaseFormat(string txt)
{
// Do something
}
public static <T> ArrayList<T extends BaseFormat> getTextFormat(String[] txt)
{
ArrayList<T> list = new ArrayList<T>();
for (int i = 0; i < txt.length; i++)
{
list.add(new T(txt[i])); // ERROR
}
return list;
}
}
class FooFormat extends BaseFormat
{
// Some variables
public FooFormat (string txt)
{
// Do something
}
}
And this:
class BaseFormat
{
// Some variables
public BaseFormat(string txt)
{
// Do something
}
public static ArrayList<BaseFormat> getTextFormat(String[] txt)
{
ArrayList<T> list = new ArrayList<T>();
for (int i = 0; i < txt.length; i++)
{
list.add(new BaseFormat(txt[i]));
}
return list;
}
}
But when I try to cast the array I receive an error. This is my code:
String[] txts = ...; // Some texts
ArrayList<FooFormat> list = (ArrayList<FooFormat>) BaseFormat.getTextFormat(txts); // Casting ERROR
So how can I do it, but still keep it generic?
You would have to pass the type in as a parameter to the static method, and then probably use reflection to invoke Class.newInstance. Type erasure means you will not have a concrete type T after compilation, so that is why you can't compile new T(...)
try doing
ArrayList<BaseFormat> list = (ArrayList<BaseFormat>) BaseFormat.getTextFormat(txts);
Then on iterating you can down cast the items to FooFormat with check of instanceOf operator
So, you are mixing generics, which allow dynamic typing, with inheritance, which allows overriding methods. What you really want is to separate creating the wrapped string from creating the list.
class BaseFormat
{
// derived classes override this method to provide their own implementations
public abstract BaseFormat wrapText(String[] txt);
public ArrayList<? extends BaseFormat> getTextFormat(String[] txt)
{
ArrayList<? extends BaseFormat> list = new ArrayList<BaseFormat>();
for (int i = 0; i < txt.length; i++)
{
list.add(wrapText(txt);
}
return list;
}
}
Are you trying to do something as follows
class BaseFormat { }
class FooFormat extends BaseFormat { }
class FormatUtils {
public static <T extends BaseFormat> List<T> getTextFormat(String[] txt, Class<T> clazz) {
List<T> list = new ArrayList<T>();
//...
T t = clazz.newInstance(); //create instance using reflection
//...
return list;
}
}
And do
List<FooFormat> list = FormatUtils.getTextFormat(new String[]{}, FooFormat.class);
The following code obviously doesn't work because List<E> is abstract:
public class MyList {
private List<E> list;
public MyList() {
this.list = new List<E>();
}
}
How can I initialize MyList class with an empty constructor if I need the list variable to be a LinkedList or a ArrayList depending on my needs?
I'm not sure whether this is what you're asking...
public class MyList {
private List<E> list;
public MyList() {
if (myNeeds)
this.list = new LinkedList<E>();
else
this.list = new ArrayList<E>();
}
}
There are better alternatives for what you are trying to achieve:
Create a base class (abstract?) and override it twice, once for ArrayList and one for LinkedList
Inject the appropriate list to your class (dependency injection)
Why not use a protected (and possibly abstract method) like:
public abstract class MyList<T> {
protected final List<T> list;
public MyList() {
list = createList();
}
public MyList(boolean preferLinked) {
list = preferLinked? new LinkedList<T>() : new ArrayList<T>();
}
// Allows client code which subclasses from MyList to override the
// default behaviour
protected List<T> createList() {
return new ArrayList<T>();
}
}
boolean shouldThisBeAnArrayList=true; // Set to false to use LinkedList
if(shouldThisBeAnArrayList) {
this.list = new ArrayList<E>();
}
else {
this.list=new LinkedList<E>();
}
You need to determine what "your needs" are in the default case - LinkedList or ArrayList. If you can't - say, if the need changes depending on something that happens over the object's lifetime, then the list needs to change, too.
List is an interface and as such, cannot be constructed. Only implementations of said interface can be constructed (e.g. ArrayList). Also, you need to know the type (E) at construction.
This should work:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class MyList<E> {
private List<E> list;
public MyList(boolean linked) {
if (linked) {
list = new LinkedList<E>();
} else {
list = new ArrayList<E>();
}
}
}
I would think you could do the following:
public class MyList<T> {
private List<T> list;
public MyList() {
this.list = new ArrayList<T>();
}
}
As I understand, you cannot use just a empty constructor, because you have a decision node in your model, when you need to choose between the type of the list, so, you will have to tell the program any way what kind of list will be.
This seems to be the best solution in my opinion:
public class MyList {
private List<E> list;
public MyList() {
this.list = new LinkedList<E>();
}
//an overload for another type,
public MyList(bool INeedArray) {
if (INeedArray)
this.list = new ArrayList<E>();
}
}
public class MyList<T> {
private List<T> list = new ArrayList<T>();
}
This is what I use in classes.. I have for a long initialized what I could when defining the private variable it self.