How can I define class using multiple generic? - java

I want to create object like belows :
private MyHashTable<AVLtree<TreeData>, TreeData> hashTable = new MyHashTable<>();
AVLtree and TreeData is what I defined, not java built in class.
But, I have no idea how to define MyHashTable class using generic.
What I can think about is
public class MyHashTable<S<T>,T> but it doesn't work.

You can declare like this
public class MyObject<T> {
}
public class MyHashTable<S extends MyObject<T>, T> {
}
In this case you can use
public class MyHashTable<S extends AVLTree<T>, T> {
}
Hope this help.

Related

Not able to create generic bounded class objects with interface

I am trying to use bounded types with generics to create generic objects of subclasses (these implement an interface). But I am getting type mismatch errors when initializing objects with the subclasses.
Here is the interface:
public interface ScannableEntity {
}
Here's the class that implements this interface:
public final class Attachment implements ScannableEntity {
.
.
.
}
Now I created 2 classes (SegmentPageScanResult and ItemProcessor) with the bounded generic type as:
#Builder
public class SegmentPageScanResult<TEntity extends ScannableEntity> {
.
.
.
}
and
public class ItemProcessor<TEntity extends ScannableEntity> {
void submitAndExecute(SegmentPageScanResult<TEntity> pageScanResult) {
. . .
}
}
When I am trying to initialize the SegmentPageScanResult and try calling submitAndExecute method of ItemProcessor from a Unit test as follows:
#ExtendWith(MockitoExtension.class)
public class ScanTest {
#Mock
private ItemProcessor<Attachment> itemProcessor;
#Test
public void testDoScan() {
Attachment mockRecord = new Attachment();
SegmentPageScanResult<Attachment> segmentPageScanResult = SegmentPageScanResult.builder()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.scannedItems(ImmutableList.of(mockRecord))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.isLastPage(true)
^^^^^^^^^^^^^^^^^
.build();
^^^^^^^^^
verify(itemProcessor).submitAndExecute(segmentPageScanResult);
}
}
I get the error -
Required type: SegmentPageScanResult<Attachment>
Provided:SegmentPageScanResult<ScannableEntity>
Can someone please help me understand why I am not able to initialize the generic object with the class implementing the interface?
I think you might have done:
ItemProcessor<Attachment> itemProcessor = new ItemProcessor<>();
And you also have:
SegmentPageScanResult<ScannableEntity> segmentPageScanResult = ...
So when you call:
itemProcessor.submitAndExecute(segmentPageScanResult, TEST_SEGMENT_ID, TEST_SCAN_ID);
There is a mismatch between the type of the itemProcessor (Attachment) and SegmentPageScanResult (ScannableEntity). So you probably need to create the ItemProcessor and the SegmentPageScanResult with the same type parameter.
EDIT: It's not completely clear what you are trying to achieve but maybe this can help:
public class ItemProcessor<T extends ScannableEntity> {
private List<T> items;
void submitAndExecute(SegmentPageScanResult pageScanResult) {
pageScanResult.setScannedItems(items);
}
}
public class SegmentPageScanResult {
private final List<ScannableEntity> items = new ArrayList<>();
public void setScannedItems(List<? extends ScannableEntity> items) {
this.items.addAll(items);
}
}
So the SegmentPageScanResult no longer has a type parameter because it only handles ScannableEntity instances. To allow setting different types from each ItemProcessor, the method parameter allows subtypes with List<? extends ScannableEntity>
basically the answer is simple: here you specified that a class of type ScannableEntity will come. but you used SegmentPageScanResult, You used the ScannableEntity interface itself, I think that if you use the Attachment class that implements the interface class, not the interface class, the problem will be fixed, for example: You can use it as SegmentPageScanResult.

Proper way to extend ParseObject and have a generic query factory

I need a way to query different parse classes based on choices made by a user. I approached the problem as follows. Please advise how to fix the problem I have or suggest alternative/better approach.
I have classes A, B, C, ... that correspond to Parse classes. They are very similar. So, I created abstract class Q:
public abstract class Q extends ParseObject {
// some shared methods
public abstract ParseQuery<? extends Q> getQuery();
}
Each of A, B, C, ... is defined as:
#ParseClassName("A")
public class A extends Q {
private static final A INSTANCE = new A();
#Override
public ParseQuery<A> getQuery() {
return ParseQuery.getQuery(A.class);
}
public static A getInstance(){
return INSTANCE;
}
}
Than I have the following recycle adapter for my recycle view:
public class QAdapter extends ParseRecyclerQueryAdapter<Q,QAdapter.MyViewHolder>{ ... }
The error I am getting happens on the following line in my activty:
mRecyclerAdapter = new QAdapter(this, factory, true);
The error message is:
Error:(58, 70) error: incompatible types: QueryFactory<CAP#1> cannot be converted to QueryFactory<Q>
where CAP#1 is a fresh type-variable:
CAP#1 extends Q from capture of ? extends Q
I tried to make the definition of adapter class generic as public class QAdapter<T extends Q> extends ParseRecyclerQueryAdapter<T, QAdapter.MyViewHolder> {... }, yet this introduced another error saying that QAdapter did not implement onBindViewHolder even though it is implemented.
This may not work, but I would try replacing
public class QAdapter extends ParseRecyclerQueryAdapter<Q,QAdapter.MyViewHolder>{ ... }
with
public class QAdapter extends ParseRecyclerQueryAdapter<? extends Q,QAdapter.MyViewHolder>{ ... }
Try to replace
extends ParseRecyclerQueryAdapter<T, QAdapter.MyViewHolder> {... }
with
extends ParseRecyclerQueryAdapter<T extends ParseObject, QAdapter.MyViewHolder> {... }
This is how to make my ParseRecyclerQueryAdapter work
Well, as the old saying goes, "make sure everything is contiguous" or something like that. You've got a great idea for a abstract and you're doing it right, but maybe you've just got an inheritance issue by not having the same call issued by the same parameters as met by the processor. like <? extends Q,...> So in that case you've got to make sure it's all redundant. Good luck!
You should make your base class Q generic:
public abstract class Q<T extends Q<T>> extends ParseObject {
// some shared methods
public abstract ParseQuery<T> getQuery();
}
Then your class A becomes
#ParseClassName("A")
public class A extends Q<A> {
private static final A INSTANCE = new A();
#Override
public ParseQuery<A> getQuery() {
return ParseQuery.getQuery(A.class);
}
public static A getInstance(){
return INSTANCE;
}
}
and ParseQuery is:
public class ParseQuery<T> {
public static <T> ParseQuery<T> getQuery(Class<T> clazz) {
return null;
}
}

Java generic : Restricting a class to specific implementations.

I have the following class hierarchy:
public abstract class Config<T> implements Proxy<T> {
public abstract T parse();
public T get() {....}
}
public class IntegerConfig<Integer> extends Config<Integer> {
public Integer parse() {...}
}
public class LongConfig<Long> extends Config<Long> {
public Long parse() {...}
}
public class IntegerListConfig<List<Integer>> extends Config<List<Integer>> {
public List<Integer> parse() {....}
}
And so on...
I'd like to introduce a new class:
public class ConfigMutation<T> implements Proxy<T> {
public ConfigMutation(....) {
//// create a concrete implementation of Config<T> according to actual parameterized type
}
}
Essentially, I'd like to avoid repeating the entire class hierarchy of Config, and support in ConfigMutation all types that have parameterized implementations in Config class hierarchy.
Couldn't find a way to do it. (Class<T>)((ParameterizedType)getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0] obviously returns T, and not the actual type.
Also, once this problem is solved, I'd be happy if someone could suggest some factory pattern with generic types, so when I'm instantiating a Config derived class inside ConfigMutation, I wouldn't have to do it with a huge if...else block on actual type.
Thanks,
Lior
Change your ConfigMutation class to :
public class ConfigMutation<U,T extends Config<U>> implements Proxy<U> {
public ConfigMutation() {
}
}
You can then use ConfigMutation as :
ConfigMutation<Integer,IntegerConfig> mutation;
You won't be able to do something as follows which is what you want :
ConfigMutation<String,IntegerConfig> mutation;
That said, there is a change you need to make to your concrete Config implementers as well. For example, change IntegerConfig to :
public class IntegerConfig extends Config<Integer> {
public Integer parse() {...}
}
The Integer in IntegerConfig<Integer> will be considered as a type parameter and not the Integer class which is not what you want. (An IDE should give you a warning for this; The type parameter Integer is hiding the type Integer)

Java generics - ensure static method is implemented

I'm using generics like this: public class MyList<T>. Is there any way to ensure that the class represented by T implements a certain static method?
No, even without generics there is never a way to ensure a class implements a static method.
You can, however, create a generic static method.
public static <T> List<T> makeSingletonList(T item) {
ArrayList<T> result = new ArrayList<T>();
result.add(item);
return result;
}
Unfortunately not.
As an alternative, consider whether the static methods of your class belongs in some sort of associated class like a builder:
class Person {
public static Person createFromDatastore(Datastore datastore) { ... }
}
It may be better to move the static to a separate class as a non-static method:
class PersonBuilder implements Builder<Person> {
public Person createFromDatastore(Datastore datastore) { ... }
}
This means that you can dictate clients of your generic class can now be required to provide it:
public class MyList<B extends Builder<T>, T> ...

Extending Generic Abstract Class & Correct Use of Super

public abstract class AbstractTool<AT extends AbstractThing> {
protected ArrayList<AT> ledger;
public AbstractTool() {
ledger = new ArrayList<AT>();
}
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool<AT extends AbstractThing> extends AbstractTool {
public Tool() {
super();
}
}
How do I correctly call super to pass the AT generic of Tool to the AbstractTool constructor?
It seems no matter what I pick AT to be when I declare Tool (Say, Tool<Thing>), that I always get back an AbstractThing instead of Thing. This seems to defeat the purpose of generics...
Help?
public class Tool<AT extends AbstractThing> extends AbstractTool<AT> {
In other words, if you extend or implement something with generics, remember to define the generics arguments for them.
Shouldn't it rather be
Tool<AT extends...> extends AbstractTool<AT>?
I think what you probably want is:
public abstract class AbstractTool<AT extends AbstractThing> {
protected List<AT> ledger = new ArrayList<AT>();
public AT getToolAt(int i) {
return ledger.get(i);
}
// More code Which operates on Ledger ...
}
public class Tool extends AbstractTool<Thing> {
// Tool stuff ...
}
Since Tool is a concrete class, it doesn't need to be parametrized itself. There is no need for the constructors if you initialize the List (oh and remember to program to the interface) at declaration, and because it is protected the subclasses can access it directly.

Categories

Resources