create new Bounded Type Parameter - java

I'm looking to implement a generic search function to basically look if a mouse click is within one of several list of rectangles (of varying types, all children of G3_gRect). When nothing is found, it should return a new object of type T with a property defining it as being invalid (as opposed to other things that it could be).
This all works fine until I try to make it return the generic type T.
What can I do differently to make this work?
This breaks in the last line when trying to initialize a new object of type T. I assume because it doesn't know that it could always initialize that type.
private <T extends G3_gRect> T whatRect(MouseEvent e, List<List<T>> maps) {
while (!maps.isEmpty()) {
List<T> map = maps.remove(0);
for (T entry : map) {
if(entry.R.contains(e.getPoint())) return entry;
}
}
return new T(G2_gObj.ObjType.NONE); //return with empty object rather than null.
}
A few of the relevant parts of related classes:
public abstract class G2_gObj {
public enum ObjType {
FUNCTION, RIBBON, D_LINE, D_START, D_END, D_IN_AREA, C_IN_AREA, M_IN_AREA, D_OUT_AREA, M_OUT_AREA, NONE, C_OUT_AREA
}
public ObjType t;
public G2_gObj(ObjType t) {
this.t = t;
}
}
public class G3_gRect extends G2_gObj{
public G3_gRect(ObjType t) {
super(t);
}
}
public class G4_gFunct extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
public class G4_gDPoint extends G3_gRect{
public G4_gFunct(ObjType t) {
super(t);
}
}
Right now my workaround is to pass in an object of type T into this method to return if nothing is found. It works, its fine, but I imagine there is a better way to actually make this work.
Thanks!

There's no way to construct an object without knowing its exact class. Barring the use of reflection, your only option would be to have the caller pass a default value, or to return null (which would avoid unnecessary object creation).
If you do want to use reflection (a questionable decision), you can have a parameter Class<T> clazz, and return
clazz.getConstructor(ObjType.class).newInstance(G2_gObj.ObjType.NONE)

Related

How do I implement a generic class with a generic type parameter without specifying the value for the type

Let's say I have
public abstract class GenericClass<T> {
abstract T getValue(T value);
}
I want to sub-class this with a class that works for any List<U>. Is it possible to implement this without having to do #SuppressWarnings("rawtypes") and #SuppressWarnings("unchecked")? For example, this works:
public class ListClass extends GenericClass<List> {
#Override
List getValue(List value) {
return value;
}
}
but I have to use #SuppressWarnings("rawtypes") to get ride of the compiler warnings. I want to avoid doing ListClass<U> extends GenericClass<List<U>> because my ListClass doesn't actually care what U is so client's shouldn't have to have separate instances for ListClass<Double> and ListClass<Integer> (for example).
Note: my real code uses CompletableFuture and is obviously more complicated and I end up having to add ugly casts and #SuppressWarnings("unchecked") when I try to use the extension methods off of CompletableFuture such as future.exceptionallyAsync((e) -> handleException((Throwable) e)).
Ideally I would want something like this to work (but it doesn't recognize the method as a valid override):
public class ListClass extends GenericClass<List> {
#Override
<U> List<U> getValue(List<U> value) {
return value;
}
}

Java generic interface calling with abstract parameter

I know there's many similar question but I had no luck finding a nice and clean solution if it's possible at all.
I'm implementing a generic interface with subclasses of an abstract type. Problem is that when I'm calling them I either must do type cast in a switch/case or cast type in every method inside interface implementations and I can't figure out a nice and clean approach... I'll better just write down a short example.
// An abstract type with 2 implementations...
public abstract class ObjTypeAbstract {}
public class ObjType extends ObjTypeAbstract {}
public class ScriptType extends ObjTypeAbstract {}
Now the processor for both types with an interface
interface ProcessorInterface<T extends ObjTypeAbstract> {
public void abcMethod(T obj);
}
public class ObjProcessor implements ProcessorInterface<ObjType> {
public void abcMethod(ObjType obj) {}
}
public class ScriptProcessor implements ProcessorInterface<ScriptType> {
public void abcMethod(ScriptType obj) {}
}
What I'm struggling with is a way of calling those processors based on ObjAbstractType. I have a single class that servers as middleware?? or how should I call it.:
Idea was to simple get the right processor via a single switch/case:
public class Processor {
private ProcessorInterface objProcessor = new ObjProcessor();
private ProcessorInterface scriptProcessor = new ScriptProcessor();
public methodAbc(ObjAbstractType obj) {
getProcessor(obj).abcMethod(obj);
}
private ProcessorInterface getProcessor(ObjAbstractType obj) {
if (obj instanceof ObjType) {
return objectProcessor;
} else if (obj instanceof ScriptType) {
return scriptProcessor;
}
return nullProcessor;
}
}
This is what I'd like to have, it also takes care of type casting of objAbstract to actual type for abcMethod, problem is that it results in RawType warning which won't break the code, but I'd like to get rid of it.
And thats where I'm stuck... because if I cast processors to specific type like this:
private ProcessorInterface<ObjType> objProcessor = new ObjProcessor();
private ProcessorInterface<ScriptType> scriptProcessor = new ScriptProcessor();
I won't be able to return an abstract one from getProcessor method so I would have to implement those interfaces with an ObjAbstractType with all it's method and have type casting in all methods of every processor like:
public class ScriptProcessor implements ProcessorInterface<ObjAbstractType> {
public void abcMethod(ObjAbstractType obj) {
ScriptType scr = (ScriptType) obj;
}
}
The other solution might be having a switch/case inside Processor middleware class and cast ObjAbstractType in it, but I'd have to write that switch inside abcMethod and all others or from getProcessor method returns both the Processor and casted ObjType... so I'd have to return some dto containing both. :/
Do you have any ideas / patterns that might help me to get rid of RawType call warning without extending the code with more switch/case or type casts?
Wish you a nice day and I'll be glad for any discussion, David.
You need a way to store the mapping between a ObjTypeAbstract class and a ProcessorInterface instance.
You could use a Map that associates ObjTypeAbstracts (as key) to ProcessorInterfaces (as value).
About the raw type issue, you could use ProcessorInterface<? extends ObjTypeAbstract> for the declared variable but you will still need to perform a unsafe cast to ProcessorInterface<ObjTypeAbstract> to be able to invoke ProcessorInterface.abcMethod() with as parameter a ObjTypeAbstract declared type.
This cast is unavoidable with your actual design.
It could give something like :
public class Processor {
private Map<Class<? extends ObjTypeAbstract>, ProcessorInterface<? extends ObjTypeAbstract >> map = new HashMap<>();
public Processor(){
map.put(ObjType.class, new ObjProcessor());
map.put(ScriptType.class, new ScriptProcessor());
}
public void methodAbc(ObjTypeAbstract obj) {
#SuppressWarnings("unchecked")
ProcessorInterface<ObjTypeAbstract> processorInterface = (ProcessorInterface<ObjTypeAbstract>) map.get(obj.getClass());
processorInterface.abcMethod(obj);
}
}
I don't think there is a substantially more elegant way to get around some form of instanceof logic. However, there should not be need for casting, if you add some types to getProcessor.
public <T extends ObjTypeAbstract> ProcessorInterface<T> getProcessor(Class<T> theClass) {
if (theClass.isAssignableFrom(ObjType.class)) {
return objProcessor;
} else if (theClass.isAssignableFrom(ScriptType.class)) {
return scriptProcessor;
}
return null;
}
This can then be called like this:
ProcessorInterface<ScriptType> scriptProcessor = new Processor().getProcessor(ScriptType.class);
ProcessorInterface<ObjType> objProcessor = new Processor().getProcessor(ObjType.class);

The method validate(capture#2-of ? extends Object) in the type Validator<capture#2-of ? extends Object> is not applicable for the arguments (String)

I am sorry about putting the error directly as the title, but I couldn't find any better title.
I have an interface defined as following to be used as a blueprint for all my validator classes:
public interface Validator<T> {
public boolean validate(T item);
}
And then I have some classes that would implement it, lets say one of them is this:
public class EmptyStringValidator implements Validator<String> {
private final String _errorMessage;
public EmptyStringValidator() {
this("String cannot be empty.");
}
public EmptyStringValidator(String message) {
this._errorMessage = message;
}
#Override
public String getMessage() {
return this._errorMessage;
}
#Override
public boolean validate(String item) {
return gsi.application.core.Validation.isEmptyString(item);
}
}
I would like to put it all in an array and call it all in one loop. So this is the code I am using:
public List<Validator<? extends Object>> validators;
public FormItem<T> addValidator(Validator<? extends Object> validator) {
this.validators.add(validator);
return this;
}
public boolean validate() {
for (Validator<? extends Object> validator : this.validators)
if (!validator.validate(this.getInputValue())) {
this._errorMessage = validator.getMessage();
return false;
}
return true;
}
However, that code is giving an error at the validate() function, specifically at this part:
validator.validate(this.getInputValue())
It gives me the error that I have mentioned
The method validate(capture#2-of ? extends Object) in the type Validator<capture#2-of ? extends Object> is not applicable for the arguments (String)
which to my understanding doesn't makes sense. To my understanding <? extends Object> should accept anything that derives from the Object class, right?
Could anyone point out what am I doing wrong or point me at the right direction?
Thanks.
As an aside, ? extends Object is no different from saying ?. That isn't the root of your problem, however.
The issue is that validators is a List<Validator<? extends Object>>. In other words, each element can be any kind of Validator<T>, not necessarily a Validator<String>. So you can put a Validator<String> into it, but when you pull an element out you don't know what kind of Validator it is, and so you don't know if it is compatible with the type returned by this.getInputValue().
The simplest fix would be to specify a concrete type (eg: String) for the type parameter. A more complicated fix would be to use a type variable in place of ? extends Object, and have getInputValue()'s type signature use that same type variable. You need to constrain the types such that getInputValue()'s return type is assignable to the parameter of validate().
An even better type for collected validators generally is Validator<? super T>, where T is the input type, in this case String.
This way addValidator(Validator<? super String> validator) accepts Validator<String> but also Validator<CharSequence> and Validator<Object>.
For example:
class LongerThan10 implements Validator<CharSequence> {
#Override
public boolean validate(CharSequence item) {
return item.length() > 10;
}
}
formItem.addValidator(str -> !str.isBlank())
formItem.addValidator(new LongerThan10());
In this specific case it makes not much sense, but it is a good idea to accept validators that work with super types generally.

Function with generic list parameter? (Overloading function)

Objective: What I need is to create a function or functions to handle different types of List parameter, and I will be iterating through the list in the function.
Attempts:
1- Multiple functions with different type of List
public static int update(List<MyClass> myClasses){};
public static int update(List<Project> rojects){};
public static int update(List<Time> times){};
But that deemed to be in-compilable as due to multiple functions with same parameter type List.
2- Generic type of list, and using (instanceof) However, I failed to completely do this as I am not sure how, and as much as I read, this seems to be an unfavorable way of such action.
My question: what is the Java way of implementing such requirement? I need a clean code, I don't care if it is complicated, I care mostly about accuracy and proper coding.
PS: if the instanceof the correct way, then would you please provide me with a small example on how to iterate the list with the different types.
Thanks in advance :)
EDIT: The different objects have no relation with each other, as in, they do not extend each other nor do they extend a super class. The blocks of each function are generating an SQLite statements which would be different for each type.
Respond to 'harsh's answer:
So I ended up using a combination of your suggestions, and that is to implement a base class with a function of getClassType() which returns a string of the class name, then I would check the returned value in the update(List<T> list) function.
public static <T extends Item> int update(List<T> list){
...
// Loop through the list and call the update function
for (T item: list){
if (item.getClassType() == MyClass.CLASS_TYPE)
update((MyClass) item);
}
...
}
public interface Item {
/**
* #return Return the class type, which is the name of the class
*/
public String getClassType();
}
public class ClassProject implements Item{
public static final String CLASS_TYPE = "ClassProject";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class ClassTime implements Item{
public static final String CLASS_TYPE = "ClassTime";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
public class MyClass implements Item{
public static final String CLASS_TYPE = "MyClass";
#Override
public String getClassType() {
return CLASS_TYPE;
}
...
}
Reason for doing this whole interface is because I don't like istanceof and not sure about it's performance and cost, so I attempted to make one of my own. Now is this a terrible way of doing this?
Can you do something like this:
public class Update<T>
{
public static int update(List<T> objects){};
}
OR
public static <T> int update(List<T> objects){};
whichever is more appropriate in your case.
So if you go by second approach and due to type erasure at runtime, you are left with instanceof checking:
public static <T> int update(List<T> objects){
for(T object : objects)
{
if(object.getClass().isInstance(Pair.class))
{
//do something
}else if(object.getClass().isInstance(Time.class))
{
}
}
return 0;
}
But that's doesn't look a good design, you can improve above by using a factory method:
static Handler getHandler(Class<?> handlerClass)
{
if(handlerClass.isInstance(Project.class))
{
//return ProjectHandler
}else if(handlerClass.isInstance(Time.class))
{
//return TimeHandler
}
//return errorHandler
}
interface Handler {
int handle();
}
public static <T> int update(List<T> objects){
for(T object : objects)
{
getHandler(object.getClass()).handle();
}
return 0;
}
Now a nicer approach IMO would be to designate your classes under update via marker interface and then cleanly handle update in each of the classes:
interface Updateable {
int update();
}
public static <T extends Updateable> int update2(List<T> objects){
for(T object : objects)
{
object.update();
}
return 0;
}
Based on your answer to my comment you are left with two approaches. The first would be to try to come up with an interface that all the possible types that would be passed to this method implement. If your interface was called Foo you could define the method as something like:
public int update(List<Foo> list)
Then your code inside would be based on the methods available in Foo.
If you can't do this then you will need separate methods per possible type. You can't do instanceof at runtime due to Type Erasure. The underlying type if the list is erased in the compiled code and therefor will not be available for instanceof logic.
EDIT:
To clear up a little confusion on my above answer. You can do instanceof on a per element basis when iterating the list, something like this:
for(Object item:list){
if (item instanceof A){
//do A based logic
}
else if (item instanceof B){
//do B based logic
}
}
You can't however check the list type at runtime like so:
if (list instanceof List<A>)
Your best bet really would be to try and generalize the types supported via an interface as suggested in my first solution. Doing the instanceof approach will lead to code that will constantly need to be modified as you add more supported types.
Expanding harsh's answer, can't you do:
public class Update
{
public static <T> int update(List<T> objects, Class<T> clazz){};
}
And then, in your implementation, vary behavior according to the passed Class instance?

Why does this class behave differently when I don't supply a generic type?

I don't understand why this confuses the compiler. I'm using the generic type T to hold an object that's not related to the put and get methods. I always thought GenericClass and GenericClass<Object> were functionally identical, but I must be mistaken. When compiling the DoesntWork class I get incompatible types - required: String - found: Object. The Works class does what I expect. What's going on here?
public class GenericClass<T> {
public <V> void put(Class<V> key, V value) {
// put into map
}
public <V> V get(Class<V> key) {
// get from map
return null;
}
public static class DoesntWork {
public DoesntWork() {
GenericClass genericClass = new GenericClass();
String s = genericClass.get(String.class);
}
}
public static class Works {
public Works() {
GenericClass<Object> genericClass = new GenericClass<Object>();
String s = genericClass.get(String.class);
}
}
}
The thing about how raw types work -- generic types that you've left out the arguments for -- is that all generics for them and their methods are erased as well. So for a raw GenericClass, the get and put methods also lose their generics.
This is because when you work with a generic class without the extra type information you work with what is sometimes called the degenerate form of the class. The degenerate form has ALL generic type information removed.
Essentially - your class becomes something like:
public class GenericClass {
public void put(Class key, Object value) {
// put into map
}
public Object get(Class key) {
// get from map
return null;
}
...
}
The compiler response you are seeing is therefore expected behaviour.
It's mentioned in a Java Puzzlers.

Categories

Resources