I have this class
public class Tree<T> {
//List of branches for this tree
private List<Tree<? super T>> branch = new ArrayList<Tree<? super T>>();
public Tree(T t){ this.t = t; }
public void addBranch(Tree< ? super T> src){ branch.add(src); }
public Tree<? extends T> getBranch(int branchNum){
return (Tree<? extends T>) branch.get(branchNum);
}
private T t;
}
And I am trying to create a variable out of this class using this
public static void main(String[] args){
Tree<? super Number> num2 = new Tree<? super Number>(2);
}
and it is giving me this error
Cannot instantiate the type Tree<? super Number>
While instantiating generics should be replaced with corresponding objects.
Ex:
Tree<Integer> num2 = new Tree<Integer>(2);
Wildcards ? cannot be used when creating new instances. You should change your code to something like that
import java.util.ArrayList;
import java.util.List;
public class Test1 {
public static void main(String[] args){
Tree<? super Number> num2 = new Tree<Number>(2);
num2.addBranch(new Tree<Number>(1));
Tree<? super Number> num3 = (Tree<? super Number>) num2.getBranch(0);
System.out.println(num3);
}
}
class Tree<T> {
//List of branches for this tree
private List<Tree<? super T>> branch = new ArrayList<Tree<? super T>>();
public Tree(T t){ this.t = t; }
public void addBranch(Tree<Number> src){ branch.add((Tree<? super T>) src); }
public Tree<? extends T> getBranch(int branchNum){
return (Tree<? extends T>) branch.get(branchNum);
}
public String toString(){
return String.valueOf(t);
}
private T t;
}
Related
I have a "Schema" and "Field" model in which a Field represents a data type and has methods on how to parse it, and the schema is a collection of fields. I am trying to implement generic comparison, however, I can't get the code to compile and I can't figure out the proper generic scopes. How can I get this to work?
class Field<T extends Comparable<? super T>> {
T parse(String val) {
...
}
}
public class Schema {
Map<Integer, Field<?>> fields;
Field<?> getField(int index){ ... }
}
public class Comparison {
public static <T extends Comparable<? super T>> boolean greaterThan(Field<T> f, String val1, String val2) {
// compiles as expected
return f.parse(val1).compareTo(f.parse(val2)) > 0;
}
public static boolean greaterThan2(Field<?> f, String val1, String val2) {
// does not compile -> required capture of ? super capture of ?, provided capture of ?
return f.parse(val2).compareTo(f.parse(val2));
}
}
public class App {
public static void main(String[] args) {
Schema s = ...
// does not compile, required type Field<T>, provided type Field<capture of ?>
Comparison.greaterThan(s.getField(0), "val1", "val2");
// compiles
Comparison.greaterThan2(s.getField(0), "val1","val2");
}
}
Below code compiles in 1.8
import java.util.Map;
class Field<T extends Comparable<? super T>> {
T parse(String val) {
return null;
}
}
class Schema {
Map<Integer, Field<?>> fields;
Field<?> getField(int index){ return null; }
}
class Comparison {
public static <T extends Comparable<? super T>> boolean greaterThan(Field<T> f, String val1, String val2) {
// compiles as expected
return f.parse(val1).compareTo(f.parse(val2)) > 0;
}
}
public class App {
public static void main(String[] args) {
Schema s = new Schema();
//compiles ok
Comparison.greaterThan(s.getField(0), "val1", "val2");
}
}
I want to define the following Java class:
public class DummyTemplate<S, D extends DummyTemplate<S,D>> {
S value;
D next;
public DummyTemplate(S value, D next) {
super();
this.value = value;
this.next = next;
}
public static DummyTemplate<String, DummyTemplate> factory(){
return new DummyTemplate<String, DummyTemplate>("wohoo", null);
}
}
created so i can subclass:
public class DummyTemplateSubclass<S, D extends DummyTemplateSubclass<S,D>> extends DummyTemplate<S, D>
(and the factoty of subclass returns DummyTemplateSubclass).
But the definition creates compile error:
Bound mismatch: The type DummyTemplate is not a valid substitute for the bounded parameter <D extends DummyTemplate<S,D>> of the type DummyTemplate<S,D>
Probably because the DummyTemplate must have parameters, how to define it then?
i get the error
it compiles howewer only :
public static<D extends DummyTemplate<String,D>> D factory()
but then i got trouble on subclass:
public static<D extends DummyTemplateSubclass<String,D>> D factory(){
Name clash: The method factory() of type DummyTemplateSubclass has the same erasure as factory() of type DummyTemplate but does not hide it
When you make a self-referencing template parameter like that, you can't use the template directly, because it's ever-expanding:
DummyTemplate<String, DummyTemplate<String, DummyTemplate<String, ...>>>
To use it, you must create a subclass:
public class DummyTemplate<S, D extends DummyTemplate<S,D>> {
S value;
D next;
public DummyTemplate(S value, D next) {
this.value = value;
this.next = next;
}
}
public class StringTemplate extends DummyTemplate<String, StringTemplate> {
public StringTemplate(String value, StringTemplate next) {
super(value, next);
}
public static StringTemplate factory() {
return new StringTemplate("wohoo", null);
}
}
Because the factory method is static and the second parameter of DummyTemplate is D extends DummyTemplate<S, D>, you need to declare a new generic type, as follows:
public static <T extends DummyTemplate<String, T>> DummyTemplate<String, T> factory() {
return new DummyTemplate<String, T>("wohoo", null);
}
Then the subclass compiles just fine:
public class DummyTemplateSubclass<S, D extends DummyTemplateSubclass<S, D>> extends DummyTemplate<S, D> {
public DummyTemplateSubclass(S value, D next) {
super(value, next);
}
public static <T extends DummyTemplateSubclass<String, T>> DummyTemplateSubclass<String, T> factorySubclass() {
return new DummyTemplateSubclass<String, T>("wohoo", null);
}
}
If you want to remove the static keyword from factory, then the code simplifies:
public class DummyTemplate<S, D extends DummyTemplate<S, D>> {
S value;
D next;
public DummyTemplate(S value, D next) {
this.value = value;
this.next = next;
}
public DummyTemplate<String, D> factory() {
return new DummyTemplate<String, D>("wohoo", null);
}
}
public class DummyTemplateSubclass<S, D extends DummyTemplateSubclass<S, D>> extends DummyTemplate<S, D> {
public DummyTemplateSubclass(S value, D next) {
super(value, next);
}
#Override
public DummyTemplateSubclass<String, D> factory() {
return new DummyTemplateSubclass<String, D>("wohoo", null);
}
}
Given the following class:
import java.util.ArrayList;
import java.util.Collection;
public class Main {
private static class A {
}
private static class B<T> {
private void thenReturn(T value) {
}
}
private static <T> B<T> when(T methodCall) {
return new B<T>();
}
private static Collection<? extends A> method() {
return new ArrayList<>();
}
public static void main(String[] args) {
Collection<? extends A> result = new ArrayList<>();
// Does not compile.
when(method()).thenReturn(result);
}
}
I get the compilation error The method thenReturn(Collection<capture#1-of ? extends Main.A>) in the type Main.B<Collection<capture#1-of ? extends Main.A>> is not applicable for the arguments (Collection<capture#3-of ? extends Main.A>)
What have I to change in the main method in order that it will compile? Is there a better solution than
public static void main(String[] args) {
Collection result = new ArrayList<>();
when(method()).thenReturn(result);
}
This works to get around it - it looks like the capture rules get a bit stretched for long expressions.
Collection<? extends A> result = new ArrayList<>();
B<Collection<? extends A>> when = when(method());
when.thenReturn(result);
Why java compiler is giving me "the type parameter T is hiding the type T" in the "translate" method ?
public static interface Translator<T, E> {
E call(T t);
}
public static <T, E> List<E> translate(List<T> l, Translator<T, E> t) {
..
}
If i remove the type parameter T
public static <E> List<E> translate(List<T> l, Translator<T, E> t)
the warning disappeared but now i cannot do
List<Long> l = new ArrayList<>();
List<String> r = translate(l, new Translator<Long, String>() { .. })
cause it give me this error
The method translate(List<T>, GFn.Translator<T,E>)
in the type GList is not applicable for the arguments
(List<Long>, new GFn.Translator<Long,String>(){})
I'm using the following code and don't get any warning messages:
public class Main {
public static interface Translator<T, E> {
E call(T t);
}
public static <T, E> List<E> translate(List<T> l, Translator<T, E> t) {
List<E> result = new ArrayList<E>();
for (T item: l) {
result.add(t.call(item));
}
return result;
}
public static class TranslatorImpl implements Translator<Long, String> {
#Override
public String call(Long aLong) {
return String.valueOf(aLong);
}
}
public static void main(String[] args) throws IOException {
List<Long> items = new ArrayList<Long>();
items.add(10L);
items.add(20L);
items.add(30L);
System.out.println(translate(items, new TranslatorImpl()));
}
}
I used JDK 1.7 and the following code just works:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
interface Translator<T, E>
{
E call(T t);
}
class LongToStringTranslator implements Translator<Long, String>
{
#Override
public String call(Long t)
{
return t.toString();
}
}
public class Main
{
public static <T, E> List<E> translate(List<T> l, Translator<T, E> t)
{
List<E> e = new ArrayList<>();
for (T item : l) {
e.add(t.call(item));
}
return e;
}
public static void main(String[] args)
{
List<Long> l = Arrays.asList(1L, 2L);
List<String> s = translate(l, new LongToStringTranslator());
System.out.println(s);
}
}
Sorry but was a mistake of mine, the problem was in a function after that one that was wrong:
public static void walk(Iterable<T> list, Walker<T> walker)
This mas missing the T type parameter, if i correct it
public static <T> void walk(Iterable<T> list, Walker<T> walker)
All the warnings disappears in all other methods in my class.
Thanks and sorry to all.
What signature should I have on my insert-method? I'm struggling with the generics. In a way, I want both Comparable<T> and T and I have tried with <Comparable<T> extends T>.
public class Node<T> {
private Comparable<T> value;
public Node(Comparable<T> val) {
this.value = val;
}
// WRONG signature - compareTo need an argument of type T
public void insert(Comparable<T> val) {
if(value.compareTo(val) > 0) {
new Node<T>(val);
}
}
public static void main(String[] args) {
Integer i4 = new Integer(4);
Integer i7 = new Integer(7);
Node<Integer> n4 = new Node<>(i4);
n4.insert(i7);
}
}
Not sure what you are trying to achieve, but should you not include that in the declaration of the class?
public static class Node<T extends Comparable<T>> { //HERE
private T value;
public Node(T val) {
this.value = val;
}
public void insert(T val) {
if (value.compareTo(val) > 0) {
new Node<T>(val);
}
}
}
Note: it is good practice to use <T extends Comparable<? super T>> instead of <T extends Comparable<T>>