Java generics - ensure static method is implemented - java

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> ...

Related

Using self-referential generic types in Java

Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.

Need to understand the syntax class Builder<T extends Builder<T>>

I am following examples in "Effective Java" and came across the following code:
abstract static class Builder<T extends Builder<T>>
and its implementation:
public static class Builder extends Pizza.Builder<Builder>
Why is this declared T extends Builder<T> and not T extends Builder. Is it really needed to add the template <T>? What is the impact if I just use Builder<T extends Builder>?
It is called as "generic type". That declaration means T can be any type that is subclass of Builder<T>.
The goal of implementing Generics is finding bugs in compile-time other than in run-time. Finding bugs in compile-time can save time for debugging java program, because compile-time bugs are much easier to find and fix.
What is the impact if we just use Builder<T extends Builder>?
It transforms into raw type. And type safety goes off.
Builder<T extends Builder<T>> means that,
The class T passed in must implement the Builder interface / extend Builder class, and the generic parameter of Builder must be T itself.
I have some examples to show that actually the difference is not that big. I think the OP wants to know the difference between T extends Builder<T> and T extends Builder.
public abstract class Builder2<T extends Builder2> {
//doesn't compile either, because String is not a subtype of Builder2
static class WrongHouseBuilder extends Builder2<String> {}
//all ok
static class RawHouseBuilder extends Builder2 {}
static class HouseBuilder1 extends Builder2<RawHouseBuilder> {}
static class HouseBuilder2 extends Builder2<HouseBuilder1> {}
static class HouseBuilder3 extends Builder2<HouseBuilder2> {}}
Now with Builder<T>:
public abstract class Builder<T extends Builder<T>> {
//all ok
static class RawCarBuilder extends Builder {}
static class CarBuilder extends Builder<CarBuilder> {}
//ok as well, T doesn't have to be CarBuilder2
static class CarBuilder2 extends Builder<CarBuilder> {}
//doesn't compile because CarBuilder2 is not a subtype of Builder<CarBuilder2>
static class CarBuilder3 extends Builder<CarBuilder2> {}}
Of cause with T extends Builder<T>, you have more protection, but not that much.
UPDATE
Just to clarify, we should not use raw type. #Radiodef has provided an interesting example in the comment. And a quote from that answer to help you understand it:
In simpler terms, when a raw type is used, the constructors, instance methods and non-static fields are also erased.
Minor: It looks more natural to me to use Builder as an interface, not an abstract class. This is a sort of recursive type declaration. It is used for type safety to prevent nasty things like the following happens:
public abstract Builder<T extends Builder<T>> {
T build();
}
public class Entity extends Builder<String>{ // does not compile
#Override
public String build() {
return null;
}
}
public class Entity extends Builder<Entity>{ //ok
#Override
public Entity build() {
return null;
}
}
Anyway more naturally looking version (from my point of view) is:
public interface Buildable<T extends Buildable<T>> {
T build();
}
public final class Entity implements Buildable<Entity>{
//other methods
#Override
public Entity build() {
//implementation
}
}
I see that the question is about the <T> part in Builder<T>. Without this <T>, you simply get a raw type, and your IDE might complain.
But in my answer, I'd like to explain what's the purpose of T extends Builder<T>, because other answers do not seem to cover it (maybe you know this already).
T extends Builder<T> serves the purpose of returning appropriate Builder.this in all the Builder methods (except build() method, of course).
I usually use it with a protected abstract method like T thisInstance().
Example:
abstract class NamedBuilder<T extends NamedBuilder<T>> {
private String name;
T name(String name) {
this.name = name;
return thisInstance();
}
protected abstract T thisInstance();
}
final class MoreSpecificBuilder extends NamedBuilder<MoreSpecificBuilder> {
#Override
protected MoreSpecificBuilder thisInstance() {
return this;
}
}
Thanks to such approach, you do not have to redefine name() method in all the NamedBuilder subclasses to return the specific subclass.
Without such constraint type parameter T, you would have:
abstract class NamedBuilder {
NamedBuilder name(String name);
}
and you would need to override all such methods in subclasses like that:
final class MoreSpecificBuilder extends NamedBuilder {
#Override
MoreSpecificBuilder name(String name) {
super.name(name);
return this;
}
}
EDIT: Without the constraint extends Builder<T> on type parameter T:
abstract class NamedBuilder<T> {
// ...
}
this would work fine, although such design would be less intuitive and more error-prone.
Without such constraint, compiler would accept anything as T (e.g. String), so the constraint acts simply as a compile-time check for the implementors of NamedBuilder.

How can I define class using multiple generic?

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.

Setting Java generics of iterators

I've noticed something funny Java does (or at least Netbeans) when I use classes implementing ArrayList and changing the generics type of the elements. I basically created an abstract class that extends ArrayList and some subclasses that are supposed to work with String objects (so something like ArrayList<String>). One of the things I did to try to achieve that was this:
public abstract class A extends ArrayList {
...
}
#Override
public abstract class B extends A {
public Iterator<String> iterator() {
return super.iterator();
}
}
Another one was this:
public abstract class A extends ArrayList {
...
}
public abstract class B<String> extends A {
#Override
public Iterator<String> iterator() {
return super.iterator();
}
}
The first one overrides successfully the iterator() method assigning a String value to it. The other one somehow cancels out the type casting. The funny thing is that none of them works when it comes to for loops. This receives type Object instead of String.
for (String s : B) {
...
}
Do you have any idea why this happens and how can I fix it without implementing my own iterator?
Not sure what you are trying to do but if I understand correctly you want a class that extends ArrayList and has a Generic type of String... Perhaps you are looking for this:
public abstract class A<T> extends ArrayList<T> {
...
}
public abstract class B extends A<String> {
...
}
Then in your code, this:
B myList = ...;
for ( String s : myList ) {
...
}
Will work just fine. Though I think you could come up with a much better solution. Do you have more specifics about your problem?
Use composition instead of Inheritance
public class A implements Iterable<String>{
List<String> myList = new ArrayList<String>();
//do operations on myList
public Iterator<String> iterator() {
return myList.iterator();
}
}
If you extend generic class you should care about generics. I mean that your declaration should look like
public abstract class A extends ArrayList<String> {
...
}
if you want to use strings or
public abstract class <T> A extends ArrayList<T> {
...
}
if you want your class to be generic.
In both cases you do not have to override iterator() method: you can invoke its from super class and it will return you "good" iterator. Your declaration is equivalent to
public abstract class A extends ArrayList<Object> {
...
}
This is the reason for "strange" behavior.
BTW may I ask you why are you extending ArrayList? It really sounds strange.
OMG this is terrible:
public abstract class B<String> extends A {
#Override
public Iterator<String> iterator() {
return super.iterator();
}
}
String is not the class String, rather, you are declaring a new type variable called String (like T) that shadows the class String

Static methods in an abstract 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);
...
}
}

Categories

Resources