I have a bounded generic class, let's call it Generic, with a parameter T that extends an abstract class Abstract:
Generic Class:
public class Generic<T extends Abstract> {
public <T extends Abstract> List<T> method() {
Map<String,String> map = T.getMap(); //this is the line with the error. I'll explain it below
//return statement and such
}
}
Abstract Class
public abstract class Abstract {
protected Map<String, String> map;
public abstract Map<String, String> getMap();
}
The class referenced by T in the generic class
public class class1 extends Abstract {
public class1() {
//map is inmutably defined here and assigned to the super
}
#Override
public Map<String, String> getMap() {
return super.map;
}
}
When trying to reference the method getMap() which comes from a class inside bounds of T (and which all possible instances of T will have, per the abstract class definition, I get the following error:
non-static method getMap() cannot be referenced from a static context
Yet there are no static keywords anywhere. What am I missing??
Thanks!
Because the method getMap() is an instance method (ie not static), you need an instance if T to call the method on.
Your class hierarchy looks off too. I think you actually want something more like:
public class Generic<T> extends Abstract<T> {
}
public abstract class Abstract<T> {
protected Map<String, T> map;
}
but without context of your intention, I can't be sure.
Related
When I define a method to return a class of Type , shouldn't I be able to override the method with any type that extends Base? Take the following example:
MultiEntryModel.java (parent class)
protected abstract <T extends Model> List<T> getDataList();
ProgramData.java
public class ProgramData extends MultiEntryModel {
...
#Override
protected List<Program> getDataList() {
return programs;
}
}
Program.java
public class Program extends Model {
...
}
I'm getting an unsafe type cast warning in Programs.java, even though I'm returning a List containing objects of type Program, which extends the Model class, just as indicated by the method signature in the base class <T extends Model>. Why?
protected abstract <T extends Model> List<T> getDataList();
This means that a List will be returned which has to be safe for any T. For example:
List<SomeModel> someModelList = thing.getDataList();
If the list you're returning is a List<Program>, this is going to be unsafe - because you can add a SomeModel into that list, and/or you can try to get a SomeModel from the list. If Program is a subtype/supertype of Program, just one of those operations is safe; otherwise, they are both unsafe.
Don't define the type variable on the method - put it on the class:
abstract class TheClass<T extends Model> {
protected abstract List<T> getDataList();
}
class ProgramClass extends TheClass<Program> {
protected List<Program> getDataList() { return programs; }
}
I have such structure:
public class Record{}
public class ParsedRecord extends Record {}
public class RecordsList extends ParsedRecord {}
public abstract class Processor<T extends Record >{ private BlockingQueue<T> queue;}
public class Dispatcher extends Processor<ParsedRecord> {
List<ParsedRecord> list;
public Dispatcher() {
}
public void process(ParsedRecord record){
//blabla
}
}
I want to use Dispatcher class with parameters that are ParsedRecord or any type that extends from ParsedRecord class.
Could some please help me to understand how to properly change Dispatcher class definition?
Could be as simple as changing your class definition to:
public class <T extends ParsedRecord> Dispatcher extends AbstractProcessor<T> {
and then: use that T as type for your list, or for the parameter given to process().
But the real answer here is: study the concept. Don't try to go with trial and error.
You declare a Processor class but you extend AbstractProcessor.
You have probably do a naming mistake in the question.
So I suppose you have only an AbstractProcessor class to give a concrete answer.
In your case, if you want related the type declaration of the class with the parameter of the method, you have to declare the method in the parent class first and specify the parameter of it with the declared type :
public abstract void process(T record){
You would have a parent class :
public abstract class AbstractProcessor<T extends Record >{
...
public abstract void process(T record);
...
}
And in the subclass you get this symmetric declaration :
public class Dispatcher extends AbstractProcessor<ParsedRecord> {
...
public void process(ParsedRecord record){
//blabla
}
}
I am unable to compile a method which needs to override a method from an abstract class supertype which uses generics for one of the parameters. The compiler complains that the extending class' setRef() method does not override a method from the supertype.
Parent Abstract Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
Ref is:
public interface Ref<M extends AbsClass<? extends Interf>> { }
and Interf is:
public interface Interf { }
Extending Child Class (setRef() doesn't compile):
public class ChildClass extends AbsClass<InterfImpl> {
#Override
public Ref<ChildClass> getRef() {
return null;
}
#Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
I have also tried using wildcards, and received same error. With wildcards, the abstract class' setRef() is:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
and the extending class' setRef() is:
public void setRef(Ref<ChildClass> newRef)
or even:
public void setRef(Ref<? extends ChildClass> newRef)
The only way I can get it to compile is if the extending class' setRef() uses the abstract class' type:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
But I would like to limit the typing of the newRef parameter to be Ref<ChildClass> or subtypes, so this isn't perfect. How can I get my extending class to only allow ChildClass or its subtypes for the setRef() method's newRef parameter? Part of my confusion is that the ChildClass' getRef() return value handles the generic typing just fine, and the same "signature" on setRef()'s parameters fails to compile. Help? Thanks!
The problem with setRef is that you could access an instance of ChildClass through a variable of type AbsClass<? extends Interf> and thus the parameter type for setRef would look like <M extends AbsClass<? extends Interf>> which again could be any M but which also doesn't match <M extends AbsClass<Q>> since Q has been defined to be InterfImpl in your case.
You could change ChildClass to this:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
but this would still allow any M and you can't just use Ref<ChildClass> because what I said above, i.e. the compiler wouldn't know about Ref<ChildClass> if you used a variable of type AbsClass<InterfImpl> or even AbsClass<? extends InterfImpl>.
One way to allow only for ChildClass parameters would be to use ChildClass in the generic type as well, e.g. like this:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}
You are getting an error because in AbsClass.setRef(), your parameter is of type Ref<? extends AbsClass<Q>>
But in your ChildClass.setRef() the parameter is of type Ref<? extends ChildClass>.
For overriding, a subclass should have the same typed parameters in the method as it's parent (before type erasure when using Generics).
I have a class:
public class MultipleSorting<T extends Enum<?>> {
private T criteriaType;
public Class<T> getCriteriaClass() {
Field field = ReflectionUtils.getField(getClass(),"criteriaType");
ReflectionUtils.makeAccessible(field);
return (Class<T>)field.getType();
}
}
This class is get instantiated as:
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?,?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController() {
super();
multipleSorting = new MultipleSorting<U>();
}
}
The actual value of U is passed from the child class of MultiSortPageableController which is:
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T,ArticleSortField> {
}
The ArticleSortField is an Enum.
I was expecting the method getCriteriaClass of MultipleSorting would return ArticleSortField from a method of MultiSortPageableController. But it is returning java.lang.Enum.
I am unable to figure it out why it is not returning the actual enum and how can I make it so. Any pointer would be very helpful to me. I need to get ArticleSortField.
Purpose:
I two requirement:
To get the actual class of enum type (say ArticleSortField.class)
To list enum value. If I have the enum class, then I could invoke class..getEnumConstants().
Java compiler removes information about generics, therefore when you use reflection you get no information about the declared type, other than Enum. This process is called type erasure.
How about passing the type down, via the constructor, like this:
public class MultipleSorting<T extends Enum<?>> {
private Class<T> criteriaType;
MultipleSorting(Class<T> criteriaType) {
this.criteriaType = criteriaType;
}
public Class<T> getCriteriaClass() {
return criteriaType;
}
}
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?, ?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController(Class<U> criteriaType) {
super();
multipleSorting = new MultipleSorting<U>(criteriaType);
}
}
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T, ArticleSortField> {
public AbstractArticleSearchController() {
super(ArticleSortField.class);
}
}
I want to define an abstract method like so:
public abstract class Saveable {
public Set<Field> getFieldSet();
...
}
getFields() should always return the same output regardless of the object's state. However, I can't declare this as a static method because I want it to be overridden. Now I'm implementing a class User which extends Saveable and it has some static methods which require the field set. Obviously, I can't get it because I don't have an object. Any idea on a design that would allow me to get the fields in a static method?
One approach would be "fake" the this reference by passing in an instance of the correct object to the static methods, and then calling getFields on that object.
Another option is to store the field list in a static field on the class. Your overridden getFields() implementation can return it (or preferably a copy of it,) and your static methods can access it directly.
My preference would be to implement the latter option, as it's a lot less clumsy (since you never have to new up an otherwise useless object to pass in to the static methods.) As well, it captures the idea that the class's fields don't rely on a given instance.
Unfortunately an inherited class can't override a static method, but it can hide it by declaring an static method with the same signature.
This will not help you if your final purpose is to use the GetFields() inside another inherited method in the Saveable class, because it will always call Saveable.getFields(), not the static method in your extending class.
You can leave your current method as non-static and abstract in Savable and return a static Set out of the non-static implementation.
public class User extends Savable {
public static Set<AField> aSet = new HashSet<AField>();
#Override
public Set<? extends Field> getFields() {
return aSet;
}
}
When calling a static method, you're calling the class' name as a scope.
So there's actually no meaning of overriding, you're only hiding it anyway.
Besides, because of the same reason, it cannot be inherited because it belongs to the class type, not a class instance.
The best you can do is call the base class' static method in the derived class, and have the same method name.
Expanding #dlev 's answer, how about you store the fields in a hashmap keyed off by unique identifier per class.
If you are using Spring, you can inject the set of fields in every object. Hence only the reference will be duplicated.
This is the proposal, I worked out. But you somehow have to name the derived class name, when loading those fields, there is no other way around, apart from declaring the methods static anyway.
public abstract class Saveable {
public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
return FieldsProvider.get(clazz);
}
}
public class FieldsProvider {
private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
new HashMap<Class<? extends Saveable>, Set<? extends Field>>();
public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
Set<? extends Saveable> set = new HashSet<? extends Saveable>();
set.addAll(col);
map.put(clazz, set);
}
public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
Set<? extends Field> set = map.get(clazz);
if (set != null) {
return set;
}
return Collections.emptySet();
}
}
public class User extends Saveable {
static {
FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
}
static void someMethod() {
Set<? extends Field> fieldsSet = getFields(User.class);
...
}
}