Given:
public interface PrimaryKey<Key extends Comparable> {
Key getKey();
}
and
public class PrimaryKeyComparator implements Comparator<PrimaryKey> {
public int compare(PrimaryKey first, PrimaryKey second) {
return first.getKey().compareTo(second.getKey());
}
}
This combination works, but gives warnings about raw types. I've tried various ways of adding the type arguments, but every combination I've tried breaks the code.
Try this:
public interface PrimaryKey<TKey extends Comparable<TKey>> {
TKey getId();
}
public class PrimaryKeyComparator<TKey extends Comparable<TKey>>
implements Comparator<PrimaryKey<TKey>> {
public int compare(PrimaryKey<TKey> first, PrimaryKey<TKey> second) {
return first.getId().compareTo(second.getId());
}
}
Related
I would like to create a contract (an interface), with a generic parameter, which enforces that the implemented class must also be the type specified in the generic parameter.
public interface SelfDefaultAlternativeDetailSupport<T extends AlternativeDetail> extends T { // syntax error (extends T)
default T resolveDetail() {
if (someConditions()) {
return this;
} else {
return getAlternativeDetails().stream()
.filter(somePredicate)
.findFirst().orElse(null);
}
}
List<T> getAlternativeDetails();
}
Example Usage
public interface CustomerDetail extends AlternativeDetail {
String getName();
}
public class Customer implements SelfDefaultAlternativeDetailSupport<CustomerDetail>, CustomerDetail {
#Override
public String getName() {
return "default name";
}
#Override
public List<AlternativeDetails> getAlternativeDetails() {
...
}
}
In other words, I would like that when a class implements SomeInterface<X>, the class must also implement X, But the attempt above has syntax because I cannot make SelfDefaultAlternativeDetailSupport extends T. Is this possible in Java?
You can make it a self-referential generic type:
public interface SelfDefaultAlternativeDetailSupport<T extends SelfDefaultAlternativeDetailSupport<T> & AlternativeDetail> {
#SuppressWarnings("unchecked")
default T resolveDetail() {
if (someConditions()) {
return (T) this;
} else {
return getAlternativeDetails().stream()
.filter(somePredicate)
.findFirst().orElse(null);
}
}
List<T> getAlternativeDetails();
}
Then you can have:
public class Customer implements SelfDefaultAlternativeDetailSupport<Customer>, CustomerDetail {
#Override
public List<Customer> getAlternativeDetails() {
...
}
}
Just be careful to never use a different class as the parameter to SelfDefaultAlternativeDetailSupport. If you want to avoid the unchecked cast of this, you can use getThis methods, but I don't think it's really worth it.
Problem:
I have two interfaces (here GenCarry and Gen):
public interface GenCarry<T extends Gen> {
GenCarry<T> setGen(T gen);
}
public interface Gen<T extends GenCarry> {
void applyOn(T carry);
}
It works when I ignore the 'rawtypes' Warning, but trying to complete them I don't get too far:
GenCarry<T extends Gen<GenCarry<T>>>
Gen<C extends GenCarry<Gen<C>>> -> error: not a valid substitute for the bounded parameter.
Question:
How would an interface like that look if complete - or is that even possible?
Is there a better approach to "generalize" an interface like that?
You can define two type parameters:
public interface GenCarry<K extends GenCarry<K, T>, T extends Gen<T, K>> {
GenCarry<K, T> setGen(T gen);
}
public interface Gen<K extends Gen<K, T>, T extends GenCarry<T, K>> {
void applyOn(T carry);
}
class StringGenCarry implements GenCarry<StringGenCarry, StringGen> {
#Override
public StringGenCarry setGen(StringGen client) {
...
}
}
class StringGen implements Gen<StringGen, StringGenCarry> {
#Override
public void applyOn(StringGenCarry network) {
...
}
}
I am having some trouble grasping generics. I've read through Oracle's tutorial on generics and it doesn't seem to address my question. I also don't know what to search for in finding my answer.
Let's say that I have the following code:
public abstract class Buff<V> {
public V value;
{
public interface Buffable<V> {
public void buff(Buff<V extends Buff> buff);
}
public class DoubleBuff extends Buff<double> {
public double value;
}
public class DoubleBuffable implements Buffable<DoubleBuff> {
public void Buff(DoubleBuff buff) {
//implementation
}
}
I want to be able to create classes that inherit Buff and have the member "value," but specify value's type (See DoubleBuff). I also want to define classes that implement the buff method using an input parameter that is of a subtype of Buff.
DoubleBuffable is some class that implements Buffable, but expects an input of DoubleBuff and not StringBuff.
Am I expressing my generics correctly?
Firstly, syntax. The declaration:
public interface Buffable<V> {
public void buff(Buff<V extends Buff> buff);
}
Should be:
public interface Buffable<V extends Buff> {
public void buff(Buff<V> buff);
}
The type variable you want, should be specified in the class declaration.
But you say:
I also want to define classes that implement the buff method using an input parameter that is of a subtype of Buff.
This way, the below declaration would suit your statement better:
public interface Buffable<V extends Buff<?>> {
public void buff(V buff);
}
You may want to change that <?> part if you need a more specific type of Buff.
Lastly, other required change and the final classes:
public abstract class Buff<V> {
public V value;
}
public interface Buffable<V extends Buff<?>> {
public void buff(V buff);
}
// instead of primitive types, you should use their wrappers: double-->Double
public class DoubleBuff extends Buff<Double> {
public double value;
}
public class DoubleBuffable implements Buffable<DoubleBuff> {
public void buff(DoubleBuff buff) {
//implementation
}
}
Primitives can't be used as generic types. Try "Double" instead of "double".
I have the following interface
public interface Identifiable {
public Comparable<?> getIdentifier();
}
And an implementing class
public class Agreement implements Identifiable {
private Long id;
public Comparable<Long> getIdentifier() {
return id;
}
}
EDIT: Note that there may be other implementations with different types of identifiers.
Now I would like to, yes, compare the comparables:
// Agreement a;
// Agreement b;
...
if (a.getIdentifier().compareTo(b.getIdentifier()) {
...
But the compareTo gives me the following compiler error:
The method compareTo(Long) in the type Comparable<Long> is not applicable for the arguments (Comparable<Long>)
How is this interface supposed to be used with Generics?
Comparable<T> is meant to be used as an upper bound for a generic parameter:
public interface Identifiable<T extends Comparable<T>> {
public T getIdentifier();
}
public class Agreement implements Identifiable<Long> {
private final Long id;
public Long getIdentifier() {
return id;
}
}
This forces the return type to be a T, not just something that can be compared to a T.
Your code is inherently unsafe.
To understand why, consider the following code:
class Funny implements Comparable<Long> { ... }
class Funnier implements Identifiable {
public Comparable<Long> getIdentifier() {
return new Funny();
}
}
Identifiable<Funny> funnier;
funnier.getIdentifier().compareTo(funnier.getIdentifier());
// You just tried to pass a Funny to compareTo(Long)
I'm trying to create a generic service that is based on a class with a generics based collection
public class GenericClass<T> {
List<T> results;
public List<T> getResults() {
return results;
}
}
Im just not sure how to create a service that is based on this GenericClass and has a concrete implementation of T. I would expect something like
public class ServiceManagerImpl<GenericClass<T>> implements ServiceManager<GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
But the compiler doesn't like this. Any ideas how to do this?
Marc
You are close... just pass the T through:
public class ServiceManagerImpl<T> implements ServiceManager<GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
I can suggest the following implementation that doesn't break the rules of JLS:
// ServiceManager.java
public interface ServiceManager<E, T extends GenericClass<E>> {
}
// ServiceManagerImpl.java
public class ServiceManagerImpl<E, T extends GenericClass<E>> implements ServiceManager<E, T> {
public T getMyClass() {
return null;
}
}
The content between <> is called Type Parameters, and GenericClass<T> is not a valid Type Parameter in declaration.
Quote from java generic guide
A generic class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.
so, you need to use GenericClass<T> in implementation, not in declaration.
// declaration
public class ServiceManagerImpl<YourGenericType> implements ServiceManager<YourGenericType> {
public YourGenericType getMyClass() {
...
}
}
// implementation
ServiceManager<GenericClass<Object>> sm = new ServiceManagerImpl<GenericClass<Object>>();
public class ServiceManagerImpl<T extends GenericClass<T>> implements ServiceManager<T extends GenericClass<T>> {
public GenericClass<T> getMyClass() {
...
}
}
I am not sure my answer is legal , but it seems meet your requirement:
public class ServiceManagerImpl<T extends GenericClass> implements ServiceManager<T>
{
#Override
public T getMyclass() {
//do your work here;
}
}
Although it may have a unchecked warning when I declare this class , but this really does!
ServiceManager<GenericClass<Integer>> manager = new ServiceManagerImpl<GenericClass<Integer>>();//passed
You should try likes this;
public class ServiceManagerImpl<GenericClass<Object>> implements ServiceManager<GenericClass<Object>> {
public GenericClass<Object> getMyClass() {
...
}
}
You can replace Object with Integer or String or any data types as you likes.