I have an interface Value and a class Record
public interface Value<T> {
T getRawValue();
}
public class Record<Value<T>> {
private Value<T> value;
T getRecordRawValue() {
return value.getRawValue();
}
}
Java will not compile this and complains about the Generics declaration > . Could someone enlighten me as to why this is invalid syntax?
You need bound your generic type to indicate the requirement of it being a Value<T>, and you also need to preserve the type that value Value<T> is providing, therefore your Record class requires two generic types: T: The type of the values returned and U: the type that represents a Value<T>
public class Record<T, U extends Value<T>>
Here you have a full example of this:
public interface Value<T> {
T getRawValue();
}
public class Record<T, U extends Value<T>> {
public Record(U value) {
this.value = value;
}
private U value;
T getRecordRawValue() {
return value.getRawValue();
}
}
public class StringValue implements Value<String> {
#Override
public String getRawValue() {
return "raw";
}
}
public class StrongValue implements Value<String> {
#Override
public String getRawValue() {
return "Rrrrraaawww";
}
}
public class StringRecord extends Record<String, StringValue> {
public StringRecord(StringValue valueProvider) {
super(valueProvider);
}
public String report() {
return super.getRecordRawValue();
}
}
The code public class Record<Value<T>> attempts to declare a generic type parameter for the class called Value<T>, but when declaring a generic type parameter, it should be a simple identifier such as T.
Try
public class Record<T>
Your Record class is wrongly declared. It should be
public class Record<T> {
//contents...
}
Related
Consider the following abstract class
public abstract class AbstractAssembler {
public abstract <T extends AbstractValue> void transform(T value);
}
and the following extension:
public class MyAssembler extends AbstractAssembler {
#Override
public void transform(MyValue value) {
// ...
}
}
With MyValue
public class MyValue extends AbstractValue {
// ...
}
Eclipse tells me:
The method transform(MyValue) of type MyAssembler must override or implement a supertype method
Why does this not work?
Your transform() method must override the generic abstract transform() method in the super class, i.e. you should have something like:
public class MyAssembler extends AbstractAssembler {
#Override
public <T extends AbstractValue> void transform(T value) {
}
}
If you want to invoke it with an actual type (e.g. MyValue) you should do:
MyValue value = new MyValue();
new MyAssembler().transfer(value);
where explicitly specifying the type-parameter (new MyAssembler().<MyValue>transfer(value);) is optional, as it will be inferred by the compiler.
If you however wish MyAssember's transform method to work only with MyValue, then you should do:
public class MyAssembler extends AbstractAssembler<MyValue> {
#Override
public void transform(MyValue value) {
}
}
I have the following situation
public interface MyCriteria<T extends Comparable<T>>{
public T getValue();
}
public abstract class AbstractMyCriteria<T extends Comparable<T>> implements MyCriteria<T>{
private String code;
public AbtsractMyCriteria(String code){
this.code=code;
}
}
I have a number of classes such as the following for different types (Date, String, Integer etc.)
public DateEqualsMyCriteria extends AbstractMyCriteria<Date>{
private Date value;
public DateEqualsMyCriteria(String code,Date value){
super(code);
this.value=value;
}
#Override
public Date getValue(){
return value;
}
}
I need to write another class that can handle Enumerations as the type instead of Date, Integer, String etc., but everything I try leads to compilation errors.
For example say I have the following enumerations
public enum Type {
Attribute,
Entity
}
public enum Operation {
Equal,
GreaterThan,
GreaterThanOrEqualTo,
LessThan,
LessThanOrEqualTo,
NotNull,
Null,
Wildcard
}
I need to be able to something such as
EnumEqualsMyCriteria enumEqualsMyCriteria=new EnumEqualsMyCriteria("Name",Type.Entity);
Any suggestions would be greatly appreciated.
UPDATE
What I have tried is
public class AttributeEnumEqualsFlexxCriteria extends AbstractFlexxCriteria<Enum> implements Comparable<Enum>
but that gives the error java.land.Enum is not within it's bounds must implement Comparable even though I have implemented compareTo within the class.
This compiles and does what you want, I think:
public class EnumEqualsMyCriteria<T extends Enum<T>> extends AbstractMyCriteria<T>{
private T value;
public EnumEqualsMyCriteria(String code,T value) {
super(code);
this.value=value;
}
#Override
public T getValue() {
return value;
}
public static void main(String[] args) {
EnumEqualsMyCriteria<Type> ec=new EnumEqualsMyCriteria<Type>("Name", Type.Entity);
}
}
You can of course have a specific class for the Type enum, if you wish.
I have a class that should accept different datatypes as the second constructor parameter:
public abstract class QueryMatch {
String key;
Object input;
public <T> QueryMatch(String key, T o) {
this.key = key;
input = o;
}
public String getKey() {
return key;
}
public Object getValue() {
return input;
}
}
I don't want to use type parameters, like
public abstract class QueryMatch<T>{
String key;
T input;
...
As this way I'm getting raw types warnings when declaring retrieving QueryMatch as a generic (as I don't know the datatype it contains). But the problem is that I need to return the value and I'm not totally comfortable by returning an Object (is that just me, but it doesn't seem like a good practice?).
Additionally, another class inherits from it:
public class QueryMatchOr extends QueryMatch {
public QueryMatchOr() {
super("title", new ArrayList<String>());
}
public void addMatch(String match) {
((ArrayList<String>) input).add(match);
}
}
And of course I'm getting a Unchecked cast warning (which I can avoid with #SuppressWarnings(“unchecked”)).
So, my question is... is there a better way to achieve what I'm trying to do? An abstract class that contains an object (which could be bounded), and returning the datatype it contains (instead of an Object) without using a type parameter in the class declaration?
What you are doing is not a good design. You are using an Object type field from the superclass while you only can know it's actual (needed) type in the subclass. If you only know that in the subclass, declare that variable in the subclass. Not even to mention that your fields are not private.
How about:
public abstract class QueryMatch {
private String key;
public QueryMatch(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public abstract void addMatch(String match);
}
public class QueryMatchOr extends QueryMatch {
private ArrayList<String> input;
public QueryMatchOr() {
super("title");
input = new ArrayList<String>();
}
public void addMatch(String match) {
input.add(match);
}
}
If you need the getValue() method in the superclass, you really should make it generic:
public abstract class QueryMatch<T> {
private String key;
public QueryMatch(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public abstract void addMatch(String match);
public abstract T getValue();
}
public class QueryMatchOr extends QueryMatch<ArrayList<String>> {
private ArrayList<String> input;
public QueryMatchOr() {
super("title");
input = new ArrayList<String>();
}
public void addMatch(String match) {
input.add(match);
}
public ArrayList<String> getValue(String match) {
input;
}
}
So first, I think the best answer is to make your class generic. But if you really don't want to do this you could do something like this:
public <T> T getValue(Class<T> type) {
return (T)input;
}
In some way you need to provide the expected type for the return value to the class. This can either be done my making that class generic or the method generic.
So, my question is... is there a better way to achieve what I'm trying to do?
No, there isn't.
I think you should use generics instead of #SuppressWarnings(“unchecked”))
I'm studying Java Generic type.
I have the abstract class AbstractInputdata.
public abstract class AbstractInputData {
....
}
Some class that extend AbstractInputData
public class Email extends AbstractInputData{
...
}
public class Mobile extends AbstractInputData{
...
}
......
A.
public class ProcessorA {
public static boolean isCustomData(AbstractInputData abstractInputData) {
....
}
}
B.
public class ProcessorB {
public static <T extends AbstractInputData> boolean isCustomData(T t) {
...
}
}
Is there any difference between A and B?
The only difference is that the second method with appear as a generic typed method via Reflections. It's behaviour will be the same except in odd cases like this
processorB.<MyType>isCustomData(t); // won't compile unless t is a MyType
You would have to tell it what type you expect it to match, which isn't that useful IMHO.
Since your methods only produce a boolean, there is no difference. But in case you want to return the input you can use B to preserve the generic type:
public class ProcessorB {
public static <T extends AbstractInputData> boolean isCustomData(T t) {
...
}
public static <T extends AbstractInputData> T copyCustomData(T t) {
...
}
}
ProcessorA could only return an object of type AbstractInputData while processorB returns Email or Mobile depending on the parameter type.
What should be the signature of a method that takes a generic object and returns another generic object, one that either is the same or a sub class of the original class? That is, if the method takes some generic class A, the returned object is guaranteed to be either A or B such that B extends A (directly or indirectly)?
The code below exemplifies what I'm trying to do, in the function getList():
package com.company;
import java.util.ArrayList;
public class Main {
private Main(){
List<String> stringList = new GenericMessageListCreator.getList(StringGenericMessage.class);
}
private class GenericMessageListCreator() {
public List<GenericMessage<T1>> getList(Class<T1 extends GenericMessage> clazz) {
return new ArrayList<T1>();
}
}
private class GenericMessage<T> {
public GenericMessage(){};
private T internalValue;
public void setValue(T value) {
this.internalValue = value;
}
public void echoValue() {
System.out.println("I contain " + internalValue);
}
}
private class StringMessage extends GenericMessage<String>{}
private class IntegerMessage extends GenericMessage<Integer>{}
}
Example aside, in actuality I'm writing a registry of classes that are used for Commands in a command pattern. When I get an object by its class I want to fetch the appropriate Command and pass the object to it.
I think you are looking for this signature:
public <T1 extends GenericMessage> List<GenericMessage<T1>> getList(Class<T1> clazz) {
return new ArrayList<T1>();
}
You'll find more info about generic methods here.
EDIT
Based on what I understand from your sample code, I would go for something like (I corrected some syntax errors in your code):
private class GenericMessageListCreator {
public <U, V extends GenericMessage<U>> List<U> getList(Class<V> clazz){
return new ArrayList<U>();
}
}
private class GenericMessage<T> {
public GenericMessage(){};
private T internalValue;
public void setValue(T value)
{
this.internalValue = value;
}
public void echoValue() {
System.out.println("I contain " + internalValue);
}
}
private class StringMessage extends GenericMessage<String>{}
private class IntegerMessage extends GenericMessage<Integer>{}
Thus, you'll be able to create a List<String from `StringMessage like this:
List<String> stringList = new GenericMessageListCreator().getList(StringMessage.class);
I'm not even sure which method you want to have this behavious on, but I've assuming it's getList():
private class GenericMessageListCreator() {
public <T extends GenericMessage<?>> List<T> getList(Class<T> clazz) {
return new ArrayList<T>();
}
}