Generic return value (java) - java

This works nicely:
// Return all objects with code 'code'.
static List<? extends ICode> getObjects(String code, List<? extends ICode> list)
{
<ICode> retValue = new ArrayList<ICode>();
for (ICode item : list)
{
if (item.getCode().equals(code))
{
retValue.add(item);
}
}
return retValue;
}
The 'singular' version can be:
// Return the first object found with code 'code'.
static ICode getObject(String code, List<? extends ICode> lijst)
{
for (ICode item : lijst)
{
if (item.getCode().equals(code)) return item;
}
return null;
}
But instead of return value ICode I would like return value <? extends ICode>.
Can it be done?
See Jon Skeets answer, I now prefer to use the T instead of ? also in the plural version:
// Return all objects with code 'code'.
public static <T extends ICode> List<T> getObjects(String code, List<T> lijst)
{
List<T> retValue = new ArrayList<T>();
for (T item : lijst)
{
if (item.getCode().equals(code))
{
retValue.add(item);
}
}
return retValue;
}

I assume you want it to be the same type as the actual list. In that case, this should do it:
static <T extends ICode> T getObject(String code, List<T> list)
{
for (T item : list)
{
if (item.getCode().equals(code)) return item;
}
return null;
}

If you let the return type be ICode then you can return any type that extends ICode.

Related

How get list of all classes that inherit from the interface with the specified generic (interface<concrete class>)

I have command interface
public interface ICommand {...}
and handler interface that is associated with specific command
public interface ICommandHandler<T extends ICommand> {
IResponse handle(T command);
}
For example, I have concrete command
public class GetCatalogById implements ICommand{
private final long catalogId;
public GetCatalogById(long catalogId) {
this.catalogId = catalogId;
}
public long getCatalogId() {
return catalogId;
}
}
How programmatically get list (List) of all classes in project that
implements ICommandHandler<GetCatalogById>
?
Your problem can be divided into 2 subproblems:
Getting a list of all classes that implement ICommandHandler
Filtering ones which have a required type parameter
As #ArvindKumarAvinash said, you can find many solutions to the first subproblem here.
And here is my solution for a second one:
public static <T extends ICommand> List<Class<? extends ICommandHandler<T>>> getCommandHandlers(
Class<T> commandClass, String packageName
) {
return new Reflections(packageName).getSubTypesOf(ICommandHandler.class).stream()
.filter(subtype -> !subtype.isInterface())
.filter(subtype -> Objects.equals(getParameter(subtype, ICommandHandler.class, 0), commandClass))
.map(subtype -> (Class<? extends ICommandHandler<T>>) subtype)
.collect(Collectors.toList());
}
#Nullable
public static <T> Type getParameter(
Class<T> clazz,
Class<? super T> parametrizedParent,
int index
) {
Type result = null;
for (ParameterizedType parent : getParameterizedParents(clazz, parametrizedParent)) {
result = parent.getActualTypeArguments()[index];
if (!(result instanceof TypeVariable)) return result;
index = getTypeVariableIndex((TypeVariable<?>) result);
}
return result;
}
private static <T> List<ParameterizedType> getParameterizedParents(Class<? extends T> clazz, Class<T> parent) {
List<ParameterizedType> genericParents = new ArrayList<>();
Class<? extends T> current = clazz;
while (true) {
Type supertype = getSuperType(current, parent);
if (supertype instanceof ParameterizedType)
genericParents.add((ParameterizedType) supertype);
else genericParents.clear();
Type rawSupertype = toRawType(supertype);
if (rawSupertype == parent) {
Collections.reverse(genericParents);
return genericParents;
}
current = (Class<? extends T>) rawSupertype;
}
}
private static <T> Type getSuperType(Class<? extends T> child, Class<T> parent) {
if (child == parent) return child;
Type superclass = child.getGenericSuperclass();
if (isSubTypeOfClass(superclass, parent)) return superclass;
for (Type type : child.getGenericInterfaces())
if (isSubTypeOfClass(type, parent)) return type;
throw new IllegalArgumentException(child.getName() + " is not assignable from " + parent.getName());
}
private static int getTypeVariableIndex(final TypeVariable<?> typeVariable) {
return Arrays.asList(typeVariable.getGenericDeclaration().getTypeParameters()).indexOf(typeVariable);
}
private static boolean isSubTypeOfClass(Type type, Class<?> clazz) {
Type rawType = toRawType(type);
return rawType instanceof Class && clazz.isAssignableFrom((Class<?>) rawType);
}
private static Type toRawType(Type type) {
return type instanceof ParameterizedType ? ((ParameterizedType) type).getRawType() : type;
}

How to avoid warning in cast to Generic in this case?

Best way to avoid this warning? Is there any case/example where the (T) cast can fail? (Java language compiled with Eclipse)
Example updated for reference with Lee's answer: cast fail subtly using result.
interface Test {
}
class Test1 implements Test {
void doSomething() {}
}
class Test2 implements Test {}
public class TestIterable<T extends Test> implements Iterable<T> {
final ArrayList<T> result=new ArrayList<>();
public TestIterable(Object obj) {
if (obj instanceof Test) {
Test t = (Test) obj;
result.add((T) obj); // Warning: unchecked cast from Test to T
// Iteresting decompilation result....
// result.add((Test) obj);
}
}
#Override
public Iterator<T> iterator() {
return result.iterator();
}
public static void main(String[] args) {
TestIterable<Test1> x = new TestIterable<>(new Test2());
for (Test1 y :x.result) {
y.doSomething();
// java.lang.ClassCastException
};
}
}
Two alternatives. The natural solution to require a T object probably does not fit your needs. Then the type T has to be explicitly passed because of the type erasure making any other construct senseless.
class TestIterable<T extends Test> implements Iterable<T> {
final List<T> result = new ArrayList<>();
public TestIterable(T obj) {
result.add(obj);
}
public TestIterable(Class<T> type, Object obj) {
if (obj == null || type.isAssignableFrom(obj.getClass())) {
result.add(type.cast(obj));
}
}
#Override
public Iterator<T> iterator() {
return result.iterator();
}
}

PECS parametrized class

I have a little piece of code where i created my own java.util.stream realization.
I need to parametrize it using PECS rule. But either I didn't understand PECS rule well or my class designed bad - I don't know how to correctly implement it.
When I'm trying to implement it (? extends T) in filter() method realization, for example - I can't use foreach cycle.
Maybe you have some ideas? Thanks in advance.
public class Streams<T> {
private final List<T> list;
private List<T> resultList = new ArrayList<>();
private Streams(List<T> list) {
this.list = list;
}
public static <E> Streams<E> of(List<E> list) {
return new Streams<>(list);
}
public Streams<T> filter(Predicate<T> predicate) {
for (T elem : list) {
if (predicate.test(elem)) {
resultList.add(elem);
}
}
return this;
}
public Streams<T> transform(Function<? super T, ? extends T> function) {
for (T elem : resultList) {
resultList.set(resultList.indexOf(elem), function.apply(elem));
}
return this;
}
public <E, I> Map<E, I> toMap(Function<T, E> function1, Function<T, I> function2) {
HashMap<E, I> map = new HashMap<>();
for (T elem : resultList) {
map.put(function1.apply(elem), function2.apply(elem));
}
return map;
}
}

java generics <T extends Number>

I have this code:
public class Test<T extends Number>{
public static void main(String[] args){
Test<Short> test = new Test(Short.class);
System.out.println(test.get());
}
private Class<T> clazz;
public Test(Class<T> clazz){
this.clazz=clazz;
}
public T get(){
if(clazz == Short.class)
return new Short(13); //type missmatch cannot convert from Short to T
else return null;
}
}
but it does not compile... Any Idea how I repair this?
You cannot construct a Short with an int (there is no such constructor), and you could cast to T like
public T get() {
if (clazz == Short.class)
return (T) Short.valueOf((short) 13);
else
return null;
}
Because your return type is generic T not Short. so you will get type mismatch.
The kind of construction in your code looks more suitable for a non-generics implementation:
Instead of:
public T get() {
Declare it as:
public Number get () {
Even if you write below, compiler will complain
Short s = new Short(13); //The constructor Short(int) is undefined
workaround
Short s = new Short((short) 13);
your case
return (T) new Short((short) 13);
public T get() {
if (clazz == Short.class) {
Short s = 13;
return (T) s;
} else {
return null;
}
}

java generics and collection assignment

If I have this class:
class Foo<T> implements SomeInterface
{
final private List<T> list = new ArrayList<T>();
final private Class<? extends T> runtimeClass;
public Foo(Class<? extends T> cl) { this.runtimeClass = cl; }
// method override from SomeInterface
#Override public boolean addChild(Object o)
{
// Only add to list if the object is an acceptible type.
if (this.runtimeClass.isInstance(o))
{
list.add( /* ??? how do we cast o to type T??? */ );
}
}
public List<T> getList()
{
return this.list;
} // yes, I know, this isn't safe publishing....
}
how would I perform a runtime cast from Object to type T?
Use this:
list.add(this.runtimeClass.cast(o))
See Class.cast() for details
// method override from SomeInterface
#Override public boolean addChild(Object o)
{
// Only add to list if the object is an acceptible type.
if (this.runtimeClass.isInstance(o))
{
list.add((T)o);
}
}

Categories

Resources