Multiple toString() Methods with Generics - java

I have an object which will be stored in two different data structures.
I am using generics, and each structure has to print out the object in a different way. Is there a way to have multiple toString() methods that will invoke accordingly?
I can't create two different methods that return a string, as custom methods are not defined in the generic type, so you can't call them unless you cast it, which breaks the point behind generics.
Should I just create two different objects with different toString() methods for each data structure? Or is there an alternative?
Thanks

I think you need to use the toString() of the different objects, but you should still be able to do this with generics in place.
I imagine your generic class has at least one instance of the generic type. If that is the case, override your generic classes toString() to delegate to the generic type object instance.
If your generic class only has a single instance, you can do something like this:
class Holder<T> {
private T instance;
public Holder(T _instance) {
instance = _instance;
}
public String toString() {
return instance.toString();
}
}
And if your class has multiple instances of the generic type (as with many Collection's), you can delegate to each instance of the type.
class CollectionHolder<T> {
private Collection<T> collection;
public CollectionHolder(Collection<T> _collection) {
collection= _collection;
}
public String toString() {
StringBuilder builder = new StringBuilder();
for(T t : collection) {
builder.append(t); //same as builder.append(t.toString())
}
return builder.toString();
}
}

If you need to call it on both you need to add it to your interface. It's entirely possible you don't want to use toString() for it, since toString() is supposed to be a human readable representation.
class Nay1 {
String someCrazyMethod() { return "ugh"; }
}
class Nay2 {
String someRandomMethod() { return "ook"; }
}
Well this sucks. You wouldn't want a Nay1 to ook, or a Nay2 to ugh. But you need something uniform!
interface NayInterface {
String nayRepresentation();
}
And your new classes:
class Nay1 implements NayInterface {
String someCrazyMethod() { return "ugh"; }
public String nayRepresentation() { return someCrazyMethod(); }
}
class Nay2 implements NayInterface {
String someRandomMethod() { return "ook"; }
public String nayRepresentation() { return someRandomMethod(); }
}
Now no matter what, you can call myNayInterface.nayRepresentation(); to get your string representation that matches the appropriate class without doing any casting.
class ActuallyDoesSomething<T extends NayInterface> {
String foo;
public ActuallyDoesSomething(T t) {
this.foo = t.nayRepresentation();
}
public String foo() { return foo; }
}
Obviously if you want to use toString() instead of nayRepresentation, you can do that. But this will allow you to not have to consume toString and keep that instead for debugging purposes.

Related

How to call a getter from a subclass which hasn't an abstract declaration in the superclass

I have a superclass that I instantiate as ArrayList. A subclass of the superclass is saved in the ArrayList. Now I want to get the information out of the ArrayList, but the getter for the attribute is only available in the subclass. I can get the information (which are saved in the ArrayList too) from other classes that have an abstract declaration in the abstract superclass. However, I don’t like to implement “dummy” methods in all classes which extend the superclass.
Code truncated:
public class Question{
QuestionPool() {
questionPool = new ArrayList<Question>();
ClozeQuestions q15 = new ClozeQuestions("Erster Text", "Zweiter Text");
questionPool.add(q15);
}
public int startQuiz{
System.out.printf("Q: %s", questionPool.get(i).?????
}
}
public abstract class Question {
String question;
public String getQuestion() {
return question;
}
}
public class ClozeQuestions extends Question {
ClozeQuestions(String questionPart1, String questionPart2){
this.questionPart1 = questionPart1;
this.questionPart2 = questionPart2;
}
public String getQuestionPart1() {
return questionPart1;
}
public String getQuestionPart2() {
return questionPart2;
}
}
To circumvent the problem I implemented a "helper method" in the Question class:
ClozeQuestions question2ClozeQuestion = new ClozeQuestions();
return question2ClozeQuestion.getQuestionPart1();
}
Which I call from the QuestionPool class:
System.out.printf("Q: %s", questionPool.get(i).getQuestionPart1());
Since the objects in the list are stored as the type of the superclass, you will have to cast it to the subclass before you can access the subclass methods. This is what type casting looks like:
(Subclass)objectOfSuperclassType
And to be safe, you should type check before casting which can be done with 'instanceof':
if (objectOfSuperclassType instanceof Subclass) {
Subclass objectOfSubclassType = (Subclass)objectOfSuperClass
}
And finally, an example of how to implement this when dealing with a list:
List<Superclass> myList = new ArrayList<>();
myList.add(new Subclass());
if (myList.get(0) instanceof Subclass) {
System.out.println( ((Subclass) myList.get(0)).getSomeString() );
}
Although this may answer your question, the code you provided does not require the List to be initialized with the superclass at all. If you were to have two different subclasses and stored both of them in the same list, only then would it make sense to do this.

Fluent API with inheritance and generics

I'm writing a fluent API to configure and instantiate a series of "message" objects. I have a hierarchy of message types.
To be able to access method of subclasses when using the fluent API, I used generics to parametrize the subclasses and make all fluent methods (that start with "with") return the generic type. Note that I omitted most of the body of the fluent method; a lot of configuration goes on in them.
public abstract class Message<T extends Message<T>> {
protected Message() {
}
public T withID(String id) {
return (T) this;
}
}
The concrete subclasses redefine the generic type similarly.
public class CommandMessage<T extends CommandMessage<T>> extends Message<CommandMessage<T>> {
protected CommandMessage() {
super();
}
public static CommandMessage newMessage() {
return new CommandMessage();
}
public T withCommand(String command) {
return (T) this;
}
}
public class CommandWithParamsMessage extends
CommandMessage<CommandWithParamsMessage> {
public static CommandWithParamsMessage newMessage() {
return new CommandWithParamsMessage();
}
public CommandWithParamsMessage withParameter(String paramName,
String paramValue) {
contents.put(paramName, paramValue);
return this;
}
}
This code works, i.e. I can instantiate any of the classes and use all fluent methods:
CommandWithParamsMessage msg = CommandWithParamsMessage.newMessage()
.withID("do")
.withCommand("doAction")
.withParameter("arg", "value");
Calling the fluent methods in any order is a major goal here.
However, the compiler warns that all return (T) this are unsafe.
Type safety: Unchecked cast from Message to T
I'm unsure how I could reorganize the hierarchy to make this code truly safe. Even though it works, the use of generics in this fashion feels really convoluted.
Especially, I'm not able to foresee situations where runtime exceptions will happen if I just ignore the warnings.
There will be new message types, so I need to keep the code extensible.
If the solution is to avoid inheritance altogether I would also like to obtain suggestion of alternatives.
There are other questions here on SO that address a similar issue. They point to a solution where all intermediate classes are abstract and declare a method like protected abstract self(). Still, in the end it's not safe.
Your code is fundamentally an unsafe use of Generics. For example, if I write a new class which extends message, say Threat, and has a new method doSomething(), and then I create a message parameterised by this new class and it creates an instance of Message, and then attempts to Cast it to its subclass. However, since it is an instance of Message, and not of Threat, an attempt to call this message will cause an Exception. Since it is not possible for Message to doSOmething().
Further, its also unnecessary to use Generics here. Plain old inheritance will work fine. Since sub types can override methods by making their return types more specific, you can have:
public abstract class Message {
protected Message() {
}
public Message withID(String id) {
return this;
}
}
And then
public class CommandMessage extends Message {
protected CommandMessage() {
super();
}
public static CommandMessage newMessage() {
return new CommandMessage();
}
public CommandMessage withCommand(String command) {
return this;
}
}
This will work fine, on the understanding that you call your arguments in the right order:
CommandWithParamsMessage.newMessage()
.withID("do")
.withCommand("doAction")
.withParameter("arg", "value");
will fail, but
CommandWithParamsMessage.newMessage().withParameter("arg", "value")
.withCommand("doAction").withID("do")
Will succeed, since it only "up types", finally returning a "message" class. If you want it not to "uptype", then simply overwrite the inherited commands, and now you can call the methods in any order, since they are all return the original type.
E.g.
public class CommandWithParamsMessage extends
CommandMessage {
public static CommandWithParamsMessage newMessage() {
return new CommandWithParamsMessage();
}
public CommandWithParamsMessage withParameter(String paramName,
String paramValue) {
contents.put(paramName, paramValue);
return this;
}
#Override
public CommandWithParamsMessage withCommand(String command){
super.withCommand(command);
return this;
}
#Override
public CommandWithParamsMessage withID(String s){
super.withID(s);
return this;
}
}
Now you will fluently return a CommandWithParamsMessage with either of the two fluent calls above.
Does this solve your problem, or have I misunderstood your intent?
I've done something like this before. It can get ugly. In fact, I've tried it more times than I've used it; usually it gets erased and I try to find a better design. That said, to help you move a little further down the road try this:
Have your abstract classes declare a method like:
protected abstract T self();
This can replace this in your return statements. The subclasses will be required to return something that matches the bound for T -- but it doesn't guarantee that they return the same object.
If you change the signatures like this you should neither get any warnings nor do you need any casts:
abstract class Message<T extends Message<T>> {
public T withID(String id) {
return self();
}
protected abstract T self();
}
abstract class CommandMessage<T extends CommandMessage<T>> extends Message<T> {
public T withCommand(String command) {
// do some work ...
return self();
}
}
class CommandWithParamsMessage extends CommandMessage<CommandWithParamsMessage> {
public static CommandWithParamsMessage newMessage() {
return new CommandWithParamsMessage();
}
public CommandWithParamsMessage withParameter(String paramName, String paramValue) {
// do some work ...
return this;
}
#Override protected CommandWithParamsMessage self() {
return this;
}
}
The compiler warns you of this unsafe operation, because it cannot factually check the correctness of your code. This makes it, as a matter of fact, unsafe and there is nothing you can do to prevent this warning. Even though an unsafe operation is not compile-checked, it can still be legitimate at run time. If you circumvent the compiler check, it is however your job to validate your own code for its use of correct types which is what the #SupressWarning("unchecked") annotation is for.
To apply this to your example:
public abstract class Message<T extends Message<T>> {
// ...
#SupressWarning("unchecked")
public T withID(String id) {
return (T) this;
}
}
is fine, because you can as a matter of fact tell with certainty that this Message instance is always of the type that is represented by T. But the Java compiler cannot (yet). As with other suppression warnings, the key to using the annotation is to minimize its scope! Otherwise, you can easily retain the annotation suppression by accident after you made code changes that render your former manual check for type safety as invalid.
As you only return a this instance, you can however easily outsource the task to a specific methods as recommended in another answer. Define a protected method like
#SupressWarning("unchecked")
public T self() {
(T) this;
}
and you can always call the mutator like here:
public T withID(String id) {
return self();
}
As another option, and if it is possible for you to implement, consider an immutable builder which only exposes its API by interfaces but implements a full builder. This is how I normally build fluent interfaces these days:
interface Two<T> { T make() }
interface One { <S> Two<S> do(S value) }
class MyBuilder<T> implements One, Two<T> {
public static One newInstance() {
return new MyBuilder<Object>(null);
}
private T value; // private constructors omitted
public <S> Two<S> do(S value) {
return new MyBuilder<S>(value);
}
public T make() {
return value;
}
}
You can, of course, create smarter constructions where you avoid the unused fields. If you want to look at examples of me using this approach, look at my two projects which use fluent interfaces quite heavily:
Byte Buddy: API for defining a Java class at run time.
PDF converter: A conversion software for converting files using MS Word from Java.
This is not a solution for your original problem. It is only an attempt to capture your actual intention, and sketch an approach where where the original problem does not appear. (I like generics - but class names like CommandMessage<T extends CommandMessage<T>> extends Message<CommandMessage<T>> make me shudder...)
I know that this is structurally rather different from what you originally asked about, and you might have omitted some details in the question that narrow down the range of possible answers so that the following is no longer applicable.
But if I understood your intention correctly, you could consider letting the subtypes be handled by the fluent calls.
The idea here is that you initially can only create a simple Message:
Message m0 = Message.newMessage();
Message m1 = m0.withID("id");
On this message, you can call the withID method - that's the only method that all messages have in common. The withID method returns a Message in this case.
Until now, the message is neither a CommandMessage nor any other specialized form. However, when you call the withCommand method, you obviously want to construct a CommandMessage - so you now simply return a CommandMessage:
CommandMessage m2 = m1.withCommand("command");
Similarly, when you call the withParameter method, you receive a CommandWithParamsMessage:
CommandWithParamsMessage m3 = m2.withParameter("name", "value");
This idea is roughly (!) inspired by a blog entry, which is in German, but the code nicely shows how this concept may be used to construct type-safe "Select-From-Where" queries.
Here, the approach is sketched, roughly adapted for your use-case. Of course, there are some details where the implementation will depend on how this is actually going to be used - but I hope that the idea becomes clear.
import java.util.HashMap;
import java.util.Map;
public class FluentTest
{
public static void main(String[] args)
{
CommandWithParamsMessage msg = Message.newMessage().
withID("do").
withCommand("doAction").
withParameter("arg", "value");
Message m0 = Message.newMessage();
Message m1 = m0.withID("id");
CommandMessage m2 = m1.withCommand("command");
CommandWithParamsMessage m3 = m2.withParameter("name", "value");
CommandWithParamsMessage m4 = m3.withCommand("otherCommand");
CommandWithParamsMessage m5 = m4.withID("otherID");
}
}
class Message
{
protected String id;
protected Map<String, String> contents;
static Message newMessage()
{
return new Message();
}
private Message()
{
contents = new HashMap<>();
}
protected Message(Map<String, String> contents)
{
this.contents = contents;
}
public Message withID(String id)
{
this.id = id;
return this;
}
public CommandMessage withCommand(String command)
{
Map<String, String> newContents = new HashMap<String, String>(contents);
newContents.put("command", command);
return new CommandMessage(newContents);
}
}
class CommandMessage extends Message
{
protected CommandMessage(Map<String, String> contents)
{
super(contents);
}
#Override
public CommandMessage withID(String id)
{
this.id = id;
return this;
}
public CommandWithParamsMessage withParameter(String paramName, String paramValue)
{
Map<String, String> newContents = new HashMap<String, String>(contents);
newContents.put(paramName, paramValue);
return new CommandWithParamsMessage(newContents);
}
}
class CommandWithParamsMessage extends CommandMessage
{
protected CommandWithParamsMessage(Map<String, String> contents)
{
super(contents);
}
#Override
public CommandWithParamsMessage withID(String id)
{
this.id = id;
return this;
}
#Override
public CommandWithParamsMessage withCommand(String command)
{
this.contents.put("command", command);
return this;
}
}

Return type from a Java Factory Pattern

This might be a very basic question with a very obvious answer but i am having hard time figuring this out.
How to know the return type of a method of a class involve in java factory patterns. for example looking at the code below... what would be the return type of the method invocation and how to cast it properly... and also how to write the javadoc also for the classes.
i am trying to write a library which user then can plug in to their project...
I have an interface
public interface myInterface
{
public Object doA();
public Object doB();
}
and concrete Classes as follow
public class concerete1 implements myInterface
{
public concerete1() {
}
#override
public Object doA()
{ return new String("Hello"); }
#override
public Object doB()
{ return "hello".getBytes(); }
}
and
public class concerete1 implements myInterface
{
public concerete2() {
}
#override
public Object doA()
{ return "hello".getBytes(); }
#override
public Object doB()
{ return new String("Hello"); }
}
and my factory class is as follow
public class factory
{
private myInterface mi;
public myInterface actionProducer(String choice)
{
switch(choice)
{
case "a":
mi = new concerete1();
break;
case "b":
mi = new concerete2();
break;
}
return mi;
}
}
and my test runner class is as follow
String result = factory.actionProducer("a").doA();
You should not have to explicitly test the dynamic type of a factory method's return value. The static type should tell you all you need to know. That means the return type should be as specific as it needs to be to tell you what you can do with the object. For example, a factory method that makes maps of varying implementation should return Map:
public interface MapFactory {
public Map makeMap();
...
}
Whether the Map is a HashMap or TreeMap or ConcurrentSkipListMap, you can use the Map methods to interact with it. If it turns out you need to call ceilingKey, which isn't a Map method, you have a design problem.
In your case, your factory methods make no sense, since there is no more specific type to return than Object, and nothing you can do with the return values beyond the API of Object. A more reasonable factory would return objects that can be interacted with the same way, regardless of how the objects are implemented.
You shouldn't be interested in real factory product type. Abstract factory are constructed for factoring objects with common interface / abstract superclass.
So, if you will have
public abstract class Animal {
public void eat();
public String foo();
}
and implementor classes:
public class Dog extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "howgh";
}
}
public class Cat extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "meow";
}
}
Your factory interface will look something like this:
public interface AnimalFactory {
public Animal createAnimal();
}
And the concrete factory will be
public class CatFactory implements AnimalFactory {
public Cat createAnimal(){
return new Cat();
}
}
public class DogFactory implements AnimalFactory {
public Dog createAnimal(){
return new Dog();
}
}
So you can create common interface products, without knowing their real class:
Animal awesomeAnimal = catFactory.createAnimal();
System.out.println(awesomeAnimal.foo());
the output will be "meow". It is possible, because all products are subclasses of common interface (Animal here).
The return type will be an Object in all cases. I don't know what you're trying to cast to, but if it's a String, casting into a String from a byte array is not possible. You would have to use one of the String class' constructors instead ("String result = new String(factory.actionProducer("a").doA());"). If you were calling "doB()" (and thus getting a String as an Object) you could convert it to a string either by casting it ("String result = (String)factory.actionProducer("a").doA();") or by calling the return Object's toString() method ("String result = factory.actionProducer("a").doB().toString();").
Javadoc for these methods would describe each of them as returning an Object, because that's what they do.
In short, I would change the return types of "doA()" and "doB()" to what they are actually returning (String or byte array), but maybe this is not an option for what you are trying to do. Some additional context might help in coming up with a more detailed answer.
EDIT: Sorry, I didn't realize that the String and byte array return types were reversed over the two implementations. In the answer I described "doA()" as returning a byte array and "doB()" as returning a String, and I believe those are flipped around in the implementation you're using in your example (Concrete1). However, everything else pretty much stands.
The simplest answer would be to declare 'result' as an Object and then force a cast and just hope you got it right: if you don't, you'll get an error at runtime:
Object obj = factory.actionProducer("a").doA();
String str = (String) obj;
However, in your example, doA() returns either String or byte[], depending on the choice of implementation, so this will fail for "b" and succeed for "a". Maybe it was a typo in the question though?
With a slightly clearer definition of your objectives, using generic types might help, but its hard to say without more information.

How do I define the return type inside a Java generics method?

I have a generic method, for example:
public static<T> T execute(...) {
...
}
How can I define what type T is in the method body? For example:
if (T == String) {
// do something with strings
// return string;
}
if (T == Bitmap) {
// do something with bitmap
// return bitmap;
}
I tried the following, but it didn't work:
T par = null;
if(par instanceof String) {
// do something with strings
// return string;
}
I tried declaring par like below, but that didn't work either.
T par = (T) null;
T par = (T) new Object();
You could probably do something like this:
public static <T> T execute(Class<T> t) {
if(String.class == t) {
}
}
If your code only supports a discrete set of data types, you don't want to use generics. As mentioned in the comments on the original post, this situation calls for overloaded method calls.
Consider, for example, a situation where you support Strings, Integers, and Doubles, but you don't have specific logic for other data types. You would define your methods such as:
public static String execute(String s) { ... }
public static Integer execute(Integer i) { ... }
public static Double execute(Double d) { ... }
public static Object execute(Object o) { ... }
The first three methods would define the logic for the three discrete data types you do support, while the final would define logic and/or error handling for any other data types you do not support. (Of course, this doesn't cover primitives not of int or double type, but this is just an example.)
Generics were initially added to Java to support a Collection knowing exactly what it contained. It was a way of guaranteeing that a List held only Strings by declaring it a List<String>, for example. This capability was then extended, but the basic concept held -- guarantee that if you put an unknown object of type X in, even if you don't know what X is at compile time, you can write logic for getting that same type X out. (This article is an interesting read, if out-dated.)
This does not mean it should be used where the logic applied in a method or class is dependent on the data type of the input. It should be used where it doesn't matter the incoming data type, and the same logic will be applied consistently across the unknown data type X. So if you have different logic for String than Doubles, you should not be using generics.
tl;dr:
Since the original post indicated different logic based on the data type of the input parameter, therefore, generics are not appropriate to be used. Overloading the execute method based on the supported data types should be used instead.
T Here is known as Type Parameters.
// here will define the type of T in the method go()
public interface Comparable<T> {
public int compareTo(T t) {
// do something...
}
}
For eg:
I am having a class Song, and i want to sort the songs on the basis of its title.
public class Song implements Comparable<Song> {
private String title;
public void compareTo(Song s) {
title.compareTo(s.title());
}
public void setTitle(String s) {
this.title = s;
}
public void getTitle() {
return this.title;
}
public String toString() {
return getTitle();
}
}
If you're splitting the functionality in code that way already, and the inputs are the same, you'd probably be well served with different functions. So instead of(using Jeshurun's answer)
public static <T> T execute(Class<T> t)
{
if(String.class == t) {
}
}
BitMap b = execute(BitMap.class);
You would have
public BitMap bitmapExecute(...)
{
commonWork();
//do bitmap stuff
}
public String stringExecute(...)
{
commonWork();
//do String stuff
}
BitMap b = bitmapExecute(...);
String s = stringExecute(...);
If there's a large block of common code, with only a small section different based on type, you can move that common code to its own function.
public someObject commonWork(...)
{
//Do common stuff
}
As long as you are making the decision about the type at compile time, you shouldn't have to have instanceof blocks.

Java generics (template) specialization possible (overriding template types with specific types)

I'm wondering what are the options to specialize generic types in Java, i.e. in a templated class to have specific overrides for certain types.
In my case I was a generic class (of type T) to return null usually, but return "" (the empty string), when T is the String type, or 0 (zero) when its the Integer type, etc.
Merely providing a type-specific overload of a method produces a "method is ambiguous" error:
e.g.:
public class Hacking {
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
Bar<String> barString = new Bar<String>();
// OK, returns null
System.out.println(barInt.get(new Integer(4)));
// ERROR: The method get(String) is ambiguous for the type Bar<String>
System.out.println(barString.get(new String("foo")));
}
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
}
Is the only option to subclass the generic class with a specific type (see StringBar in the following example?
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
StringBar barString2 = new StringBar();
// OK, returns null
System.out.println(barInt.get());
// OK, returns ""
System.out.println(barString2.get());
}
public static class Bar<T> {
public T get() {
return null;
}
}
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
}
Is this is the only way, it's a bit of a pain to have to create a subclass for every type I want to specialize instead of an overload of get() in the Bar class.
I'm guessing I could check the instanceof in the Bar.get() method, e.g.
T get(T t) {
if (t instanceof String) return "";
if (t instanceof Integer) return 0;
else return null;
}
However I've been taught to avoid instanceof and use polymorphism when possible.
All things considered, the concensus appears to be that the StringBar method mentioned in the question is the only way to go.
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
Generics in Java are very different from templates in C++ in this respect. It is not possible to write a specific version of a generic class to do something different for a particular case, as C++ can do. It is also not possible to determine at run time what T is - this is because that information is not passed into the byte code (object code) and so doesn't even exist at runtime. This due to something called "type erasure".
BarString and BarInt would be the obvious way of doing this, but there are improvements you can make. For example you can write a generic Bar to cover the common cases, and then write specialized BarString and BarInt to implement special cases. Ensure that the instances can only be created through a factory, which takes the class of the object to be processed:
class Bar<T> {
class BarString extends Bar<String> {
// specialist code goes here
}
static Bar<T> createBar(Class<T> clazz) {
if (clazz==String.class) {
return new BarString();
} else {
return new Bar<T>;
}
That probably won't compile, but I don't have the time to work out the exact syntax. It does illustrate the principle.
The compiler is actually correct, because the following code is compile-time checked (Bar<String> barString = new Bar<String>();) when compiled, from
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
to
public static class Bar<String> {
public String get(String x) {
return null;
}
public String get(String x) {
return "";
}
}
and is ambiguous as you can't have 2 identical methods with the same return types and the same parameter arguments.
See an explanation by Jon Skeet's:
What is the concept of erasure of generics in java?
Java Generics - Types erasures - when and what happens?
You can subclass Bar<T> and create StringBar (note I removed the static keyword) and override get() method.
public class BarString extends Bar<String> {
#Override
public String get(String x) {
return "";
}
}
Generics in Java aren't made for specialization. They're made for generalization! If you want to specialize for certain types, you should be specializing...through a subclass.
Often you don't need to do something in a specialized manner however. Your StringBar example is kind of contrived because you could have this:
public class Bar<T> {
private final T value;
public T get() {
return value;
}
}
I don't see why you need to specialize for a String here.

Categories