I am trying to implement a class representing an XML tree as follows:
public class XML<T extends XML<T>> {
private final List<MarkupLanguage> nodeList = new ArrayList<>();
private final Map<String, String> attributeList = new HashMap<>();
public T attr(final String key, final String value) {
if (value != null) {
this.attributeList.put(key, value);
}
return (T) this;
}
public T appendTo(final T node) {
node.add(this);
return (T) this;
}
...
}
My problem is typing of these clauses - I am getting unchecked cast for "return (T) this;"
and also when I try to use the XML class by itself:
final XML url = new XML("url");
new XML("loc")
.add("http://goout.cz")
.appendTo(url);
I am getting:
Unchecked cast to call appendTo(T) as a member of raw type XML.
How can I improve my code to get better typing?
Just type it:
final XML<T> url = new XML<T>("url");
new XML<T>("loc")
.add("http://goout.cz")
.appendTo(url);
It also looks like you really want to use XML<T> for your methods, not T, so you can avoid the casts (but I could be wrong):
public XML<T> attr(String key, String value) {
if (value != null) {
this.attributeList.put(key, value);
}
return this;
}
public XML<T> appendTo(XML<T> node) {
node.add(this);
return this;
}
What about the approach below (simple inheritance plus generic methods):
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class XmlTest {
#Test
public void test() {
XMLFirstSubclass url = new XMLFirstSubclass("url");
XMLSecondSubclass xmlSecondSubclassInstance = new XMLSecondSubclass(
"loc").add("http://goout.cz").appendTo(url);
}
}
abstract class XML {
private final List<String> texts = new ArrayList<String>();
private final List<XML> nodes = new ArrayList<XML>();
private final String nodeName;
protected XML(String nodeName) {
this.nodeName = nodeName;
}
#SuppressWarnings("unchecked")
public <R extends XML> R add(String text) {
texts.add(text);
return (R) this;
}
#SuppressWarnings("unchecked")
public <R extends XML, T extends XML> R add(T node) {
nodes.add(node);
return (R) this;
}
#SuppressWarnings("unchecked")
public <R extends XML, T extends XML> R appendTo(T node) {
node.add(this);
return (R) this;
}
}
class XMLFirstSubclass extends XML {
public XMLFirstSubclass(String nodeName) {
super(nodeName);
}
}
class XMLSecondSubclass extends XML {
public XMLSecondSubclass(String nodeName) {
super(nodeName);
}
}
Note that the generic methods allow to get a node from one type T and return the instance's type R, which can be different than the argument's type. T can be different than R, but both inherit XML.
Comments about the approach presented in the question
The approach that you're using until now can lead to strange situtations.
Let's illustrate this with an example.
Below, we try to write the first class that specializes XML:
public class XMLFirstSubclass extends XML<OtherXMLSubclass> { ... }
If we're writing the first XML subclass, the only possible values to OtherXMLSubclass is XMLFirstSubclass or not declaring the generic type at all.
First option:
public class XMLFirstSubclass extends XML<XMLFirstSubclass> { ... }
Second:
public class XMLFirstSubclass extends XML { ... }
If you chose to use generics in your class design, the second option seems bad.
Taking a closer look into the first option, it opens the possibility of getting subclasses like:
class XMLSecondSubclass extends XML<XMLFirstSubclass> {
...
}
Note that this compiles perfectly, but will cause class cast exceptions in XMLSecondSubclass method calls at runtime.
Related
I have a list of implementations to SomeInterface
List<SomeInterface> listOfThingsThatImplementsSomeInterface
I want to extract a specific implementation from the list according to its class name
private SomeInterface getThisType(SomeInterfaceImpl myType) {
SomeInterfaceImpl impl = null
for (SomeInterface current: listOfThingsThatImplementsSomeInterface) {
if (current instanceof myType) {
impl = current
break;
}
}
return impl;
}
Is that possible in Java? should I be using generics?
First you need the Class instance of the desired class (which you have, you mention "according to its class name"). You can get a Class instance from the class name using
Class<?> cls = SomeInterfaceImpl.class;
or if you have the class name as a String:
Class<?> cls = Class.forName("package.ClassName")
or from an instance using
SomeInterfaceImpl myType = ...;
Class<?> cls = myType.getClass()
Then you can call this method, assuming your have a List<SomeInterface> listOfThingsThatImplementsSomeInterface somewhere:
private SomeInterface getThisType(Class<?> myType) {
for (SomeInterface current: listOfThingsThatImplementsSomeInterface) {
if (myType.isInstance(current)) {
return current;
}
}
return null; //nothing found
}
Suppose we have the desired implementation Class instance, (refer to #f1sh answer if the class is Class<?>), it can be done using Stream,
private <T extends SomeInterface> Optional<T> getThisType(Class<T> type) {
return this.someInterfaceList.stream().filter(type::isInstance)
.map(type::cast).findFirst();
}
The key to match the type is using Class#isInstance.
Some points to note:
Make method return type generic so no cast is needed.
Class#cast can be used to convert the return type of the Stream.
Use Optional to handle case when no element matched.
Full example
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class FilterByClass {
List<SomeInterface> someInterfaceList = new ArrayList<>();
public static void main(String[] args) {
FilterByClass filterByClass = new FilterByClass();
filterByClass.someInterfaceList = List.of(new SomeInterfaceImplA(), new SomeInterfaceImplB(), new SomeInterfaceImplC());
System.out.println(filterByClass.getThisType(SomeInterfaceImplA.class).get().name());
System.out.println(filterByClass.getThisType(SomeInterfaceImplB.class).get().name());
System.out.println(filterByClass.getThisType(SomeInterfaceImplC.class).get().name());
}
private <T extends SomeInterface> Optional<T> getThisType(Class<T> type) {
return this.someInterfaceList.stream().filter(type::isInstance)
.map(type::cast).findFirst();
}
public interface SomeInterface {
default String name() {
return this.getClass().getSimpleName();
}
}
public static class SomeInterfaceImplA implements SomeInterface { }
public static class SomeInterfaceImplB implements SomeInterface { }
public static class SomeInterfaceImplC implements SomeInterface { }
}
The method should take the class as parameter. Let's say your interface is T, you can receive a parameter of type Class<? extends T>
Then go through the list and check for an element with the same class
Here is an example that should work:
private static <T> Optional<T> getThisType(
List<T> listOfThingsThatImplementsInterfaceT,
Class<? extends T> klass) {
return listOfThingsThatImplementsInterfaceT.stream()
.filter(klass::isInstance)
.findFirst();
}
Test with a list of Serializable
List<Serializable> listOfThingsThatImplementsSerializable = Arrays.asList(
new Integer(1), new Float(2), new Double(3)
);
System.out.println(
getThisType(listOfThingsThatImplementsSerializable, Float.class)
);
Looking for the Float returns Optional[2.0]
I have this project I'm working on and basically this is what I would like to achieve.
This is what I have:
MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.build();
MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();
So the step builder pattern forces the user to use the withValue() method and the withAnotherValue() method in that order. The method field() is optional and can be used as many times as you want.I followed this website for example http://www.svlada.com/step-builder-pattern/
So what I would like to achieve is this:
MyObject obj = MyObject.builder(Type.ROCK)
.withColour("blue")
.withValue("string")
.withAnotherValue("string")
.build();
MyObject obj = MyObject.builder(Type.STONE)
.withWeight("heavy")
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();
So in the builder() method you'd put an enum type and based on the enum you'd have a different set of methods appear. So for ROCK the withValue(),withAnotherValue() and withColour() are now mandatory. But for STONE withWeight(), withAnotherValue() and withColour() are mandatory.
I something like this possible? I have been trying for the past two days to figure this out but I just can't seem to get it to give specific methods for each type. It just shows all the methods in the Builder.
Any thoughts and help is much appreciated.
Code:
Enum
public enum Type implements ParameterType<Type> {
ROCK, STONE
}
ParameterType
interface ParameterType<T> {}
MyObject
public class MyObject implements Serializable {
private static final long serialVersionUID = -4970453769180420689L;
private List<Field> fields = new ArrayList<>();
private MyObject() {
}
public interface Type {
Value withValue(String value);
}
public interface Value {
Build withAnotherValue(String anotherValue);
}
public interface Build {
MyObject build();
}
public Type builder(Parameter type) {
return new Builder();
}
public static class Builder implements Build, Type, Value {
private final List<Field> fields = new ArrayList<>();
#Override
public Build withAnotherValue(String anotherValue) {
fields.add(new Field("AnotherValue", anotherValue));
return this;
}
#Override
public Value withValue(String value) {
fields.add(new Field("Value", value));
return this;
}
#Override
public MyObject build() {
MyObject myObject = new MyObject();
myObject.fields.addAll(this.fields);
return myObject;
}
}
}
This isn't possible using enum, but you could do this with a custom enum-like class:
public final class Type<B extends MyObject.Builder> {
private final Supplier<? extends B> supplier;
private Type(Supplier<? extends B> supplier) {
this.supplier = Objects.requireNonNull(supplier);
}
public B builder() {
return supplier.get();
}
public static final Type<MyObject.RockBuilder> ROCK =
new Type<>(MyObject.RockBuilder::new);
public static final Type<MyObject.StoneBuilder> STONE =
new Type<>(MyObject.StoneBuilder::new);
}
public class MyObject {
// ...
// And this method is probably superfluous at this point.
public static <B extends MyObject.Builder> builder(Type<? extends B> type) {
return type.builder();
}
}
You could adapt that approach to a step builder easily, but there's a separate issue here. Since each step in a step builder specifies the next step in the return type, you can't re-use step interfaces very easily. You would need to declare, for example, separate interfaces RockValueStep, StoneValueStep, etc. because the interfaces themselves specify the step order.
The only simple way around that would be if the separate types (rock, stone, etc.) only strictly added steps such that e.g. Type.ROCK returns a ColourStep and Type.STONE returns a WeightStep, and both ColourStep and WeightStep return ValueStep:
// Rock builder starts here.
interface ColourStep { ValueStep withColour(String c); }
// Stone builder starts here.
interface WeightStep { ValueStep withWeight(String w); }
// Shared.
interface ValueStep { AnotherValueStep withValue(String v); }
And then:
public final class Type<B /* extends ABuilderStepMarker, possibly */> {
// (Constructor and stuff basically same as before.)
public static final Type<MyObject.ColourStep> ROCK =
new Type<>(/* implementation */::new);
public static final Type<MyObject.WeightStep> STONE =
new Type<>(/* implementation */::new);
}
The reasons this kind of thing can't be done using enum are pretty much:
enum can't be generic:
// This is an error.
enum Type<T> {
}
Although you could declare an abstract method on an enum and override it with a covariant return type, the covariant return type is never visible:
// This is valid code, but the actual type of
// Type.ROCK is just Type, so the return type of
// Type.ROCK.builder() is just MyObject.Builder,
// despite the override.
enum Type {
ROCK {
#Override
public MyObject.RockBuilder builder() {
return new MyObject.RockBuilder();
}
};
public abstract MyObject.Builder builder();
}
Considering you are looking for specific methods for a specific type of builder, having multiple builders, one for each type of MyObject that can be built may work best. You can create an interface that defines the builder and then put the common functionality into an abstract class, from which the individual builders extend. For example:
public interface Builder {
public MyObject build();
}
public abstract class AbstractBuilder() {
private final List<Field> fields = new ArrayList<>();
protected void addField(String key, String value) {
fields.add(new Field(key, value));
}
#Override
public MyObject build() {
MyObject myObject = new MyObject();
myObject.fields.addAll(this.fields);
return myObject;
}
}
public class StoneBuilder extends AbstractBuilder {
public StoneBuilder withValue(String value) {
addField("Value", value);
return this;
}
// ...More builder methods...
}
public class RockBuilder extends AbstractBuilder {
public RockBuilder withAnotherValue(String value) {
addField("AnotherValue", value);
return this;
}
// ...More builder methods...
}
This allows you to build MyObject instances in the following manner:
MyObject obj = new RockBuilder()
.withValue("string")
.build();
MyObject obj = new StoneBuilder()
.withAnotherValue("string")
.build();
Your question can be generalised as follows: "How can I write the following method?"
public <T extends AbstractBuilder> T builder(final SomeNonGenericObject object) {
// code goes here
}
And the answer is: "You cannot, because there is no way for the compiler to infer what the type of T is. The only way that this is possible is by somehow passing T as a parameter:
public <T extends AbstractBuilder> T builder(final SomeNonGenericObject object, final Class<T> builderClass) {
// code goes here
}
or
public <T extends AbstractBuilder> T builder(final SomeGenericObject<T> object) {
// code goes here
}
For example:
public <T extends AbstractBuilder> T builder(final Supplier<T> object) {
return supplier.get();
}
final Supplier<AbstractBuilder> rockBuilderSupplier = RockBuilder::new;
builder(rockBuilerSupplier)
.withColour("blue")
// etc
Or simply use Justin Albano's answer, which works just as well.
Legacy code:
public <B extends IBox> List<B> getBoxList(String key)
There is no way for the method to know which subtype the caller is actually expecting, so there is no sensible way to fulfill this contract.
Important: there is no way to infer the expected subtype from the key.
Therefore the signature should be:
public List<IBox> getBoxList(String key)
Is my reasoning correct?
You can easily do that like this:
public List<? extends IBox> getBoxList(String key)
No, it doesn't. Consider the following code which won't even compile under Java 8, but will compile under Java 7 with a warning. The caller is actually expecting a list of BlueBox from the BoxDB:
List<BlueBox> boxList = boxDB.<BlueBox>getBoxList("123");
But what he actually gets is a List of RedBox. So the method is not delivering what it promises.
import java.util.*;
public class HelloWorld
{
public static void main(String[] args)
{
BoxDB boxDB = new BoxDB();
List<BlueBox> boxList = boxDB.<BlueBox>getBoxList("123");
for (IBox box: boxList) {
System.out.println(box.getClass().getName());//prints "RedBox"
}
}
}
interface IBox {
String getKey();
}
class RedBox implements IBox {
String key;
public RedBox(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
class BlueBox implements IBox {
String key;
public BlueBox(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
class BoxDB
{
public <B extends IBox> List<B> getBoxList(String key) {
List<B> result = new ArrayList<>();
result.add((B)new RedBox("123"));
return result;
}
}
There is a subtle difference between the two. The first retains the type while the second flattens the type to it's interface. By moving to the second you are essentially discarding some information that may be useful to the caller.
interface IBox {
}
public static <B extends IBox> List<B> getBoxList1(String key) {
return null;
}
public static List<IBox> getBoxList2(String key) {
return null;
}
class ABox implements IBox {
}
class BBox implements IBox {
}
public void test() {
List<ABox> aBox = Test.<ABox>getBoxList1("Hello");
List<BBox> bBox = Test.<BBox>getBoxList1("Hello");
// Not allowed.
List<ABox> cBox = Test.getBoxList2("Hello");
List<IBox> dBox = Test.getBoxList2("Hello");
}
To explain this lets start with an example
public RedBox implements IBox{
//implementation here
}
public BlueBox implements IBox{
//implementation here
}
Now suppose one case I need list of RedBoxe and YellowBox then my call as per the first code would be
List<RedBox> redBoxList = getBoxList(redKey);
List<YellowBox> yellowBoxList = getBoxList(yellowKey);
But in the later case this would be:
List<RedBox> redBoxList = (List<RedBox>)getBoxList();//Since it returns List<IBox>
List<RedBox> redBoxList = (List<RedBox>)getBoxList();
So the former code is much efficient in ensuring type safety.
Former code makes more sense. To read more about generics refer to Effective Java.
What should be the signature of a method that takes a generic object and returns another generic object, one that either is the same or a sub class of the original class? That is, if the method takes some generic class A, the returned object is guaranteed to be either A or B such that B extends A (directly or indirectly)?
The code below exemplifies what I'm trying to do, in the function getList():
package com.company;
import java.util.ArrayList;
public class Main {
private Main(){
List<String> stringList = new GenericMessageListCreator.getList(StringGenericMessage.class);
}
private class GenericMessageListCreator() {
public List<GenericMessage<T1>> getList(Class<T1 extends GenericMessage> clazz) {
return new ArrayList<T1>();
}
}
private class GenericMessage<T> {
public GenericMessage(){};
private T internalValue;
public void setValue(T value) {
this.internalValue = value;
}
public void echoValue() {
System.out.println("I contain " + internalValue);
}
}
private class StringMessage extends GenericMessage<String>{}
private class IntegerMessage extends GenericMessage<Integer>{}
}
Example aside, in actuality I'm writing a registry of classes that are used for Commands in a command pattern. When I get an object by its class I want to fetch the appropriate Command and pass the object to it.
I think you are looking for this signature:
public <T1 extends GenericMessage> List<GenericMessage<T1>> getList(Class<T1> clazz) {
return new ArrayList<T1>();
}
You'll find more info about generic methods here.
EDIT
Based on what I understand from your sample code, I would go for something like (I corrected some syntax errors in your code):
private class GenericMessageListCreator {
public <U, V extends GenericMessage<U>> List<U> getList(Class<V> clazz){
return new ArrayList<U>();
}
}
private class GenericMessage<T> {
public GenericMessage(){};
private T internalValue;
public void setValue(T value)
{
this.internalValue = value;
}
public void echoValue() {
System.out.println("I contain " + internalValue);
}
}
private class StringMessage extends GenericMessage<String>{}
private class IntegerMessage extends GenericMessage<Integer>{}
Thus, you'll be able to create a List<String from `StringMessage like this:
List<String> stringList = new GenericMessageListCreator().getList(StringMessage.class);
I'm not even sure which method you want to have this behavious on, but I've assuming it's getList():
private class GenericMessageListCreator() {
public <T extends GenericMessage<?>> List<T> getList(Class<T> clazz) {
return new ArrayList<T>();
}
}
The code:
interface Property<T>
{
T get();
}
class BoolProperty implements Property<Boolean>
{
#Override
public Boolean get()
{
return false;
}
}
class StringProperty implements Property<String>
{
#Override
public String get()
{
return "hello";
}
}
class OtherStringProperty implements Property<String>
{
#Override
public String get()
{
return "bye";
}
public String getSpecialValue()
{
return "you are special";
}
}
is used by my class:
class Result<P extends Property<X>, X>
{
P p;
List<X> list;
}
As you see it has two type parameters P and X. Despite of that the X can always be deduced from P but the language requires me to supply both:
Result<BooleanProperty, Boolean> res = new Result<BooleanProperty, Boolean>();
Is there any trick to get rid of the X type parameter? I want just use
Result<BooleanProperty> res = new Result<BooleanProperty>();
Also, I don't want lose type information and use it as:
Result<OtherStringProperty> res = new Result<OtherStringProperty>();
String spec = res.p.getSpecialValue();
String prop = res.list.get(0);
I would change Result class to be something like
class Result<X> {
Property<X> property;
List<X> list;
}
I don't think the compiler can infer X from Property, as your Result class is waiting two definitions for the two generics.
You can't infer the type, but you can add an extra level of indirection:
class BoolProperty implements Property<Boolean>
{
#Override
public Boolean get()
{
return false;
}
}
class Sub<X, P extends Property<X>> {
P p;
List<X> list;
}
class Result<X> extends Sub<X, Property<X>> {
}
Result<Boolean> res = new Result<Boolean>();
List<Boolean> list = res.list;
Boolean b = res.p.get();
List<String> res2 = res.list; // compilation error
There is a similar question whose answer you might find interesting: https://stackoverflow.com/a/4452268/247763
Essentially, there's no real way to get around including the extra generic type, because the compiler can't know what type you're using without it. I'm guessing this defeats the purpose of your approach, but you could try extending Result while specifying the types - something like this:
class BoolResult extends Result<BoolProperty, Boolean> {
// Do stuff
}
Have you tried using the wildcard generic?
class Result<? extends Property<X>>
{
// stuff
}