I hava some problems with my code.
First of all I have an interface:
public interface Generator <T, R> {
public T next (R x);
}
Then, I have created the class "DemoClass"
public class DemoClass {
private int id;
public DemoClass (int id){
this.id = id;
}
}
And... Generic Class as well
public class GenericClass implements Generator <DemoClass, Integer> {
public DemoClass next(Integer x) {
return new DemoClass (x);
}
}
After, I have created Main Class and a generic static method that containts a method like Class . I would like to know, is there any opportunity to use such construction like Class ???
My MainClass
import java.util.*;
public class MainClass {
private static Random rand = new Random ();
public static <T> T [] arr (T [] a, Class <?> typeToken){
try{
Generator <?, ?> gen = (Generator <?, ?>)typeToken.newInstance(); // How can I pass two paramets to Generator <?, ?>???
for (int i=0; i!=a.length; i++){
a[i] = (T) gen.next(rand.nextInt(100)); // This line does not work!
}
} catch (Exception e){
throw new RuntimeException (e);
}
return a;
}
public static void main (String [] args){
DemoClass [] myarr = arr (new DemoClass[10], GenericClass.class);
}
}
If you want to make that line work, you could do this:
public static <T> T[] arr(T[] a, Class<? extends Generator<T, Integer>> typeToken) {
try {
Generator<T, Integer> gen = typeToken.newInstance();
for (int i = 0; i != a.length; i++) {
a[i] = gen.next(rand.nextInt(100));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return a;
}
Basically, the bound on Class makes it so that what is returned by newInstance is a Generator<T, Integer>.
How can I pass two paramets to Generator ???
There is no need to pass any type parameters. Since Java generics use erasure, the concrete generic type arguments are not needed at runtime.
If you are using Java 8, I would suggest using a Supplier instead of a Class, since it allows you to create an instance without having to deal with the exceptions:
public static <T> T[] arr(T[] a, Supplier<? extends Generator<T, Integer>> typeToken) {
Generator<T, Integer> gen = typeToken.get();
for (int i = 0; i != a.length; i++) {
a[i] = gen.next(rand.nextInt(100));
}
return a;
}
...
// passing reference to constructor of GenericClass
DemoClass[] myarr = arr(new DemoClass[10], GenericClass::new);
No.
Generics work at compile time only. At runtime, all of the instances of class are exactly the same, the information of the parametrized types gone.
This is known as type erasure and it was designed that way to ensure that Java 1.4 binaries were compatible with Java 5 VM.
You can get a lot of info about this by searching "type erasure java" in the search box; for example Avoiding Java Type Erasure
Related
I'm looking for a functional interface that satisfies the following two requirements:
Should accept and return the same type
The type should be inferred while calling the method on the FunctionalInterface
If the requirement had just been the first, I can create a simple FunctionalInterface as follows:
#FunctionalInterface
public interface MonoFunction<T> {
T apply (T arg);
}
But, this would require the type to be specified while using the interface. But, I want the type to be inferred. Something like the below pseudo-code:
class A {
int a;
}
class B {
int b;
}
public static void main (String[] args) {
A a;
B b;
MonoFunction foo = (obj) -> {
system.out.println (obj)
return obj;
};
a = foo.apply (new A());
b = foo.apply (new B());
}
How do I achieve something like this?
You could use the UnaryOperator<T> but you have to define beforehand what type you're expecting.
UnaryOperator<A> foo = a -> {
system.out.println(a);
return a;
};
Otherwise, just cast your result into the variable type :
a = (A) foo.apply (new A());
b = (B) foo.apply (new B());
Use a generic factory method returning the function:
static <T> UnaryOperator<T> getFooFunction() {
return obj -> {
System.out.println(obj);
return obj;
};
}
public static void main (String[] args) {
A a;
B b;
UnaryOperator<A> fooA = getFooFunction();
a = fooA.apply(new A());
UnaryOperator<B> fooB = getFooFunction();
b = fooB.apply(new B());
System.out.println(fooA==(Object)fooB);
}
Note that getFooFunction() does not only return the same function semantically, given the current implementation (HotSpot/OpenJDK), it will even be the same object, as you can test easily via fooA==(Object)fooB, so there is no reason to sacrifice the Generic’s type safety.
It’s the same thing that happens when you use UnaryOperator.identity().
The other answers already discuss how to use UnaryOperator<T>. While that approach provides the type safety of Java generics, you still have to specify the type upon creating the UnaryOperator. While I would recommend the UnaryOperator approach in most situations, you specifically asked (in the comments) how one might avoid specifying the type <T>, even if you had to give up type safety.
You can make a MonoFunction implementation as follows (unsafe and usually not recommended):
public class MonoFunction {
private UnaryOperator<Object> func;
#SuppressWarnings("unchecked")
public <T> MonoFunction(UnaryOperator<T> func) {
this.func = (UnaryOperator<Object>) func;
}
#SuppressWarnings("unchecked")
public <T> T apply(T obj) {
return (T) func.apply(obj);
}
}
Note that this is not a #FunctionalInterface, so you'll have to put your lambda expression inside a new MonoFunction(...) call, as follows:
public class MonoFunctionTest {
public static void main(String[] args) {
A a;
B b;
MonoFunction foo = new MonoFunction((obj) -> {
System.out.println(obj);
return obj;
});
a = foo.apply(new A()); // toString in A
b = foo.apply(new B()); // toString in B
MonoFunction bad = new MonoFunction((A obj) -> {
System.out.println(obj);
return obj;
});
a = bad.apply(a); // toString in A
b = bad.apply(b); // ClassCastException: B cannot be cast to A
}
}
class A {
public String toString() { return "toString in A"; }
}
class B {
public String toString() { return "toString in B"; }
}
I stress again that this is unsafe, and it is relatively easy to get a ClassCastException as demonstrated.
This is possible using a generic method within a functional interface:
#FunctionalInterface
interface Identity {
< T > T apply( T input );
}
Unfortunately an interface defined like this cannot be implemented using a lambda function. Instead it must be done the old way using a class, and most concisely with an anonymous class:
Identity id = new Identity() {
public < T > T apply( T anyInput ){
// do something
return anyInput;
}
};
This then works for any input:
class A {
int a = 1;
}
String outputString = id.apply( "one" );
int outputInteger = id.apply( 1 );
A outputClass = id.apply( new A() );
I was going through java source code for ArrayList i came across below code
#SuppressWarnings("unchecked")
private E[] newElementArray(int size) {
return (E[]) new Object[size];
}
Here we trying to cast object[] to any E which we use when we declare Array List.
So i wrote code to test this as below :
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
class A {
}
class CheckBox extends A {
}
public class Box<T> {
public T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> box = new Box<Integer>();
List<Integer> intList = new ArrayList<Integer>();
box.newElementArray(10);
Box[] a = (Box[]) new Object[10];
}
// prefer wild card as it does not allow to corrupt your data types
public void wildCard(Set<?> test) {
test.add(null);
}
private T[] newElementArray(int size) {
System.out.println(" casting object to t");
return (T[]) new Object[size];
}
}
Surprisingly line box.newElementArray(10); works fine but
Box[] a = (Box[]) new Object[10];
does not work , though both do same thing. Can anybody let me know what could be reason behind it or my understanding is wrong?
Because of type erasure, Java compiler replaces E with Object. So the method newElementArray(int size) becomes
private Object[] newElementArray(int size) {
return (Object[]) new Object[size];
}
which makes its invocation successful.
You can refer to http://docs.oracle.com/javase/tutorial/java/generics/genMethods.html for the details.
I want to have a method in an interface that returns a class whose type is not defined in the package. The implementing class will then return a specific type. I can see at least 3 methods how I can do this, shown below as fn1, fn2 and fn3. In all cases there is some form of unchecked cast. Is any of these methods preferred? or is there something better? (assume that the interface I1 and the method dostuff are in some other jar package and do not have access to the Test or the Integer class)
public class Myclass {
public interface I1
{
Object fn1();
<T> T fn2();
<T> T fn3();
}
public class Test implements I1
{
#Override
public Integer fn1() {
return new Integer(1);
}
#Override
public <T> T fn2() {
return (T) new Integer(2); //requires cast to T
}
#Override
public Integer fn3() { //automatic unchecked conversion to T in return value
return new Integer(3);
}
}
public static void main(String[] args) {
Myclass c = new Myclass();
I1 t = c.new Test();
Integer i = (Integer) t.fn1(); //cast required here since I1.fn1() returns Object
Integer j = t.fn2();
Integer k = t.fn3();
dostuff(t);
}
static void dostuff(I1 p)
{
Object i = p.fn1();
Object j = p.fn2();
Object k = p.fn3();
}
}
Can't you use generics with the Interface? Like
public interface I1<T> {
T fn1();
// etc
}
Then there's no casting required when you refer to T.
That's what I prefer, at least. You can then also of course specify what you want T to be using
<T extends myInterface>
I would do it this way
public interface I1<T> {
T fn1();
}
public class Test implements I1<Integer> {
#Override
public Integer fn1() {
return new Integer(1);
}
}
public static void main(String[] args) {
Myclass c = new Myclass();
I1<Integer> t = c.new Test();
Integer i = t.fn1(); <-- no cast
}
Sorry for the cryptic title, but this is difficult to explain. The general rule is that I need a lazy loader that will give me N instances of a bound wildcard type. I'm calling the lazy loader a storage unit.
import java.util.ArrayList;
import java.util.List;
public class StorageUnit<T extends MyInterface> implements Storable<T> {
private int count;
public StorageUnit(int count) {
this.count = count;
}
private List<T> storables = new ArrayList<T>();
public List<T> getInstances(Class<T> c) {
try {
if (storables.size() == 0) {
for (int i = 0; i < count; i++) {
storables.add(c.newInstance());
}
} else {
return storables;
}
}catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
} catch (InstantiationException instantiationException) {
instantiationException.printStackTrace();
}
return storables;
}
}
Elsewhere in my application I have another class that has a reference to several of these storage units. I need to get instances of the storage unit type, and then I will do something with that type.
import java.util.ArrayList;
import java.util.List;
public class MyStorageUnitContainer {
private List<StorageUnit<? extends MyInterface>> storageUnits;
public MyStorageUnitContainer(List<StorageUnit<? extends MyInterface>> storageUnits) {
this.storageUnits = storageUnits;
}
public List<StorageUnit<? extends MyInterface>> getInstances() {
List<StorageUnit<? extends MyInterface>> instances = new ArrayList<StorageUnit<? extends MyInterface>>();
for (StorageUnit<? extends MyInterface> storageUnit : storageUnits) {
storageUnit.getInstances(/* I can't get the bound wildcard... */);
// Now loop through those instances and do something with them...
}
return instances;
}
}
That code sucks, so the best analogy I can think of is an actual storage unit container. That storage unit container has several individual storage units (think boxes). Each one of those boxes contains items of a certain type (think baseball cards). I know that a box contains 100 baseball cards, but until I open the box I don't know anything about the details of each baseball card. I'm basically trying to treat each box as a lazy loader. Opening the box loads N implementations if they don't exist already.
Paulo is correct, and (also as per Paulo's answer), I often just pass a class object into a constructor to get around this problem. It allows the getInstances() method to appear as you would like it - ie without parameters. Internally, the instance keeps a reference to the generic class so it can call newInstance() on it.
This code illustrates this using your example. I have tested this an it executes OK.
import java.util.ArrayList;
import java.util.List;
public class Sandbox
{
static interface MyInterface
{
}
static interface Storable<T>
{
List<T> getInstances();
};
static abstract class MyStorableImpl implements MyInterface
{
#Override
public String toString()
{
return "I'm a " + getClass() + " with hashcode " + hashCode();
}
}
static class MyStorable1 extends MyStorableImpl
{
}
static class MyStorable2 extends MyStorableImpl
{
}
static class StorageUnit<T extends MyInterface> implements Storable<T>
{
private final int count;
private final Class<T> clazz;
public StorageUnit(Class<T> clazz, int count)
{
this.count = count;
this.clazz = clazz;
}
private List<T> storables = new ArrayList<T>();
public List<T> getInstances()
{
try
{
if (storables.size() == 0)
{
for (int i = 0; i < count; i++)
{
storables.add(clazz.newInstance());
}
}
else
{
return storables;
}
}
catch (IllegalAccessException illegalAccessException)
{
illegalAccessException.printStackTrace();
}
catch (InstantiationException instantiationException)
{
instantiationException.printStackTrace();
}
return storables;
}
}
static class MyStorageUnitContainer
{
private List<StorageUnit<? extends MyInterface>> storageUnits;
public MyStorageUnitContainer(List<StorageUnit<? extends MyInterface>> storageUnits)
{
this.storageUnits = storageUnits;
}
public List<MyInterface> getAllInstances()
{
List<MyInterface> instances = new ArrayList<MyInterface>();
for (StorageUnit<? extends MyInterface> storageUnit : storageUnits)
{
List<? extends MyInterface> list = storageUnit.getInstances();
instances.addAll(list);
}
return instances;
}
}
public static void main(String[] args)
{
StorageUnit<? extends MyInterface> box1 = new StorageUnit<MyStorable1>(MyStorable1.class, 2);
StorageUnit<? extends MyInterface> box2 = new StorageUnit<MyStorable2>(MyStorable2.class, 3);
List<StorageUnit<? extends MyInterface>> boxes = new ArrayList<Sandbox.StorageUnit<? extends MyInterface>>();
boxes.add(box1);
boxes.add(box2);
MyStorageUnitContainer container = new MyStorageUnitContainer(boxes);
List<MyInterface> allInstances = container.getAllInstances();
for (MyInterface myInterface : allInstances)
{
System.out.println(myInterface.toString());
}
}
}
With Java Generics you can't get from a type variable (or even less from a wildcard) to an actual class object.
The reason is the way generics are implemented: by type erasure. This means that actually on run-time your generic types are not there anymore, they are erased to raw types. Only the compiler checks that you are using the right types at the right place.
In your case, the StorageUnit<T> objects do not contain any information about the T used here, if you don't give them a class object of the right type. They also all have the same class object.
So, the best bet here would be to give the StorageUnit objects a class object of their parameter class in the constructor, then the getInstances() method would not need to take it. Of course, this only shifts the problem on having to have a class object to another location, but somewhere it is necessary.
I'm having a brain cramp: I have a public interface SomeInterface and a static private class SomeClass and am trying to return a List<SomeInterface> from one of my methods, but I get the error (on the return list; line below):
Type mismatch: cannot convert from List<GenericList1.SomeClass> to
List<GenericList1.SomeInterface>
How can I fix this without having to create a new list?
Clarification: I do not want the list to be created as List<SomeInterface> (perhaps the obvious solution) because privately I want to maintain a List<SomeClass> to allow future access to SomeClass's methods beyond the ones in the public interface. This isn't shown in the example case below, but in my real program I need this.
import java.util.ArrayList;
import java.util.List;
public class GenericList1 {
public interface SomeInterface
{
public int getX();
}
private static class SomeClass implements SomeInterface
{
final private int x;
#Override public int getX() {
return this.x;
}
public SomeClass(int x) { this.x = x; }
}
public static void main(String[] args) {
List<SomeInterface> list = createList(10);
printList(list);
}
private static void printList(List<SomeInterface> list) {
for (SomeInterface si : list)
System.out.println(si.getX());
}
private static List<SomeInterface> createList(int n) {
List<SomeClass> list = new ArrayList<SomeClass>();
for (int i = 0; i < n; ++i)
list.add(new SomeClass(i));
return list;
}
}
You should redefine your method as
private static List<? extends SomeInterface> createList(int n) { ...
and similarly, the other list declarations. This allows you to deal with generic lists polymorphically, as long as you only read values from them.
(Should you want to add new elements to a list, you should use List<? super SomeInterface> instead.)
This idiom is known by the abbreviation PECS - Producer: Extends / Consumer: Super, coined by Josh Bloch in Effective Java 2nd Edition, Item 28.
As others have noted, this idiom is needed because a List<SomeClass> is not a List<SomeInterface>, even when SomeClass implements SomeInterface. The reason for this is thoroughly explained in the referred document.
Contrary to popular belief, List<Derived> has absolutely no relation to List<Base>, even if Derived extends Base.
Just because the classes share a hierarchy doesn't mean that collections of them do. This is true for generics in general.
You could alter your code as follows:
private static List<SomeInterface> createList(int n) {
List<SomeInterface> list = new ArrayList<SomeInterface>();
for (int i = 0; i < n; ++i)
list.add(new SomeClass(i)); //add a SomeClass object - valid, because it has the interface
return list;
}
I would change the signatures of the methods like so:
private static void printList(List<? extends SomeInterface> list) {
for (SomeInterface si : list)
System.out.println(si.getX());
}
private static <T super SomeClass> List<T> createList(int n) {
List<T> list = new ArrayList<T>();
for (int i = 0; i < n; ++i)
list.add(new SomeClass(i));
return list;
}
Using a wildcard in a return type is often a bad idea, because it forces you to use wildcards in all calling methods. I made createList a generic method so that the return type can be as flexable as possible while still being as specific as possible.
private static List<SomeInterface> createList(int n) {
List<SomeInterface> list = new ArrayList<SomeInterface>();
for (int i = 0; i < n; ++i)
list.add(new SomeClass(i));
return list;
}