Java HashMap generics with Class key - java

How do I stop the compiler from complaining at map.get()?
"Type mismatch: cannot convert from ClassInfo<capture#1-of ?> to ClassInfo<T>"
class Context
{
final private Map<Class<?>,ClassInfo<?>> map = new HashMap<>();
<T> ClassInfo<T> getClassInfo(Class<T> c)
{
ClassInfo<T> ci = map.get(c);
if (ci == null) {
ci = new ClassInfo<T>(c);
map.put(c, ci);
}
return(ci);
}
}
Some more information:
ClassInfo contains data about Class, gathered via reflection.
The compiler error does NOT occur with the JDK javac, only when using the Eclipse compiler.

I fixed the problem adding a ()cast to the code:
import java.util.HashMap;
import java.util.Map;
class Context
{
private final Map<Class<?>,ClassInfo<?>> map = new HashMap<Class<?>,ClassInfo<?>>();
<T> ClassInfo<T> getClassInfo(Class<T> c)
{
#SuppressWarnings("unchecked")
ClassInfo<T> ci = (ClassInfo<T>) map.get(c);
if (ci == null) {
ci = new ClassInfo<T>(c);
map.put(c, ci);
}
return(ci);
}
}
Be aware though, casts are usually dangerous, and you should only use them if you are really sure that object is in fact what you are expecting.
The downside of this solution is that it will create a warning, which I had to suppress. Hope it helps!

Just cast it and use :
#SuppressWarnings("unchecked")
ClassInfo<T> ci = (ClassInfo<T>) map.get(c);
Make sure that you are putting Type T into the hash map other wise casting exception can happen.
That is if T represents String, then map.get(c) should always return either null or ClassInfo

Related

Why does NoSuchMethodException appears when the method obviously exists?

I have been trying to solve this problem with my code but it keeps throwing a NoSuchMethodException no matter what I do. Does this have to do with imports I have added?
The code is:
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.stream.LongStream;
public class Dishouse {
public Function<Long, Long> dionym() {
Function<Long, Long> meth = (a) -> a - 62;
return meth;
}
public Function<Float, Float> femality(Function<Float, Float> sorbonist) {
Function<Float, Float> func = (a) -> a / 92;
return func.compose(sorbonist);
}
public Optional<Long> bristler(LongStream s, Predicate<Long> p,
BinaryOperator<Long> b) {
LongStream result = s.filter((LongPredicate) p);
Long count = result.count();
long stre[] = result.toArray();
if (count > 1) {
Optional<Long> e = null;
for (int i = 0; i < stre.length; i++) {
e = Optional.of(b.apply(stre[i], stre[i + 1]));
}
return e;
} else {
return Optional.empty();
}
}
The error is:
Method bristler not found: java.lang.NoSuchMethodException: Dishouse.bristler(java.util.stream.Stream, java.util.function.Predicate, java.util.function.BinaryOperator)
Above, I have included the whole class Dishouse and no other class or method interacts with this class.
It doesn't. LongStream isn't a Stream. Possibly you want Stream<Long> instead, which is not the same thing (one operates on primitive longs, the other operates on Long objects).
For the same reason, casting a Predicate<Long> to LongPredicate cannot work. casts just assert types, they don't convert things (unless casting to one primitive to another primitive type), and a Predicate<Long> isn't a LongPredicate.
NB: Your code can also return either null or Optional.empty or some optional which is a gigantic code smell. This isn't how you are supposed to use optional.
LongStream is not a sub-interface of Stream. To map a Stream<Long> to a LongStream, use the following:
Stream<Long> sl = ...
LongStream ls = sl.mapToLong(x -> x);

Finding specific type of custom exception on all inner exceptions

I am trying to recursively find all inner exceptions (getCause's) from a top level exception...of a specific instance type.
public class MyCustomRunTimeException extends RuntimeException {
public MyCustomRunTimeException() {
}
public MyCustomRunTimeException(Exception innerException) {
super(innerException);
}
}
Here is what I've tried:
and my early "find" method:
private void findAllSpecificTypeOfInnerExceptions(Exception ex)
{
Collection<MyCustomRunTimeException> MyCustomRunTimeExceptions = Stream.iterate(ex, Throwable::getCause)
.filter(element ->
element != null
&& element instanceof MyCustomRunTimeException
)
.map(obj -> (MyCustomRunTimeException) obj)
.collect(Collectors.toList());
}
It is not working. :( I've tried several other things (not shown yet)... I'll post them as "appends" to this question if I get anything that doesn't throw an exception.
Not working.... I'm getting NullPointers exceptions. and (depending on my tweaks) java.lang.reflect.InvocationTargetException exception.
Here is some examples that would find 1:N "matches".
Exception exampleOne = new MyCustomRunTimeException();
Exception exampleTwo = new Exception(new MyCustomRunTimeException());
Exception exampleThree =new Exception(new Exception(new MyCustomRunTimeException()));
Exception exampleFour =new Exception(new Exception(new MyCustomRunTimeException(new ArithmeticException())));
This is a case where I really think it's easiest doing the recursive bit in a loop, rather than using streams entirely:
List<Throwable> exlist = new ArrayList<>();
while(ex.getCause()!=null) {
exlist.add(ex.getCause());
ex = ex.getCause();
}
exlist = exlist.stream().filter(e -> e instanceof MyCustomRunTimeException).collect(Collectors.toList());
There are better options in Java 9+, and if you use external libraries, but not really in core Java 8 (hacks do exist, but that makes it much less clear than the above, IMHO, and I really don't see that it's worth introducing an external library just for this purpose.)
Or this variation:
private <T extends Throwable> Collection<T> aggregateSubClassExceptions(Throwable inputEx, Class<T> type) {
Collection<T> returnItems = new ArrayList<>();
Throwable exc = inputEx;
while (exc != null) {
if (type.isInstance(exc)) {
returnItems.add(type.cast(exc));
}
exc = exc.getCause();
}
return returnItems;
}
This code was getting the specific type AND any subclasses:
Collection<MyCustomRunTimeException> testItOutCollection;
Exception exampleOne = new MyCustomRunTimeException();
Exception exampleTwo = new Exception(new MyCustomRunTimeException());
Exception exampleThree = new Exception(new Exception(new MyCustomRunTimeException()));
Exception exampleFour = new Exception(new Exception(new MyCustomRunTimeException(new ArithmeticException())));
MyCustomRunTimeException exampleFive = new MyCustomRunTimeException(new MySubMyCustomRunTimeException(new MyCustomRunTimeException(new ArithmeticException())));
testItOutCollection = this.aggregateSubClassExceptions(exampleOne, MyCustomRunTimeException.class);
testItOutCollection = this.aggregateSubClassExceptions(exampleTwo, MyCustomRunTimeException.class);
testItOutCollection = this.aggregateSubClassExceptions(exampleThree, MyCustomRunTimeException.class);
testItOutCollection = this.aggregateSubClassExceptions(exampleFour, MyCustomRunTimeException.class);
testItOutCollection = this.aggregateSubClassExceptions(exampleFive, MyCustomRunTimeException.class);
The problem is that Stream.iterate produces an infinite stream. It never knows when to stop, even if the cause is null.
You can pass a stopping condition in the form of takeWhile but it is only available in Java 9+. See also: Limit a stream by a predicate for Java 8 workarounds (I recommend this)
Collection<MyCustomRunTimeException> exceptions = Stream.iterate(ex, Throwable::getCause)
.takeWhile(throwable -> throwable.getCause() != null)
.filter(element -> element instanceof MyCustomRunTimeException)
.map(obj -> (MyCustomRunTimeException) obj)
.collect(Collectors.toList());
You can still create your recursive solution, using java-8. Here is a small helper method that you need:
private static Stream<Throwable> streamIt(Throwable initial) {
if (initial == null) {
return Stream.empty();
}
return Stream.concat(
Stream.of(initial),
Stream.of(initial)
.map(Throwable::getCause)
.flatMap(StackWalkerSandbox::streamIt));
}
This will give you a Stream<Throwable>, what you do next with it, it's entirely up to you. For example for your description that you wanted and taken into account the examples from the accepted answer, you could do:
streamIt(exampleFive)
.filter(MyCustomRunTimeException.class::isInstance)
.map(MyCustomRunTimeException.class::cast)
.collect(Collectors.toList())
.forEach(System.out::println);

How do I return a Number object of the same concrete type as one passed in?

I have the following incomplete class. It implements a method that takes any Number object as a parameter and constrains it to a limit stored in a long and then returns the original value or the constrained value. However, the returned constrained value must be of the same concrete type as the input parameter.
public class Max implements Constraint {
long max;
public Number constrain(Number n) {
if (n.longValue() <= max) {
return n;
}
// return a number of the type passed in with value max
}
}
There are other questions about creating an object of the same type as another, but the answers assume a no-arg constructor is available and this is not the case for the numeric types.
I have played with:
n.getClass().getConstructor(new Class<?>[] { n.getClass() }).newInstance(max);
but I still have issues about passing in the right parameter even here. I am back to square one. In any case, it isn't very elegant.
I know I can do it with a lot of if statements, but I am looking for something smarter.
Because the constuctor of SubClasses of Number takes primitives as parameter, you cannot look for the constructore that has the Wrapper Class as parameter
The constructor that they all have, is the String one
long max;
public Number constrain(Number n) {
if (n.longValue() <= max)
try{
return n.getClass()
.getConstructor(String.class)
.newInstance(String.valueOf(max));
}catch(Exception ex){ex.printStackTrace();}
return n;
}
public static void main(String[]args){
Max m = new Max();
m.max = 10;
System.out.println(m.constrain(new Double(25)).getClass()); // class java.lang.Double
System.out.println(m.constrain((int) 18).getClass()); // class java.lang.Integer
}
Working DEMO
with Java 5 or hogher you can use a generic in your methods like this
package test;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Assert;
public class Max {
Number max;
public <T extends Number> T constrain(T n) {
if (n.floatValue() <= max.floatValue()) {
return n;
} else {
return castTo(max, n.getClass());
}
}
#SuppressWarnings("unchecked")
private <T extends Number> T castTo(Number max2, Class<? extends Number> class1) {
if (class1.equals(AtomicInteger.class)) {
return (T) new AtomicInteger(max2.intValue());
} else if (class1.equals(AtomicLong.class)) {
return (T) new AtomicLong(max2.longValue());
// these case are dangerous to handle
} else if (class1.equals(BigDecimal.class)) {
return (T) BigDecimal.valueOf(max2.doubleValue());
} else if (class1.equals(BigInteger.class)) {
return (T) BigInteger.valueOf(max2.longValue());
// Std Case
} else if (class1.equals(Byte.class)) {
return (T) (Byte) max2.byteValue();
} else if (class1.equals(Double.class)) {
return (T) (Double) max2.doubleValue();
} else if (class1.equals(Float.class)) {
return (T) (Float) max2.floatValue();
} else if (class1.equals(Integer.class)) {
return (T) (Integer) max2.intValue();
} else if (class1.equals(Long.class)) {
return (T) (Long) max2.longValue();
} else if (class1.equals(Short.class)) {
return (T) (Short) max2.shortValue();
} else {
throw new IllegalArgumentException("Can't handle this kind of Number : " + class1.getName());
}
}
public static void main(String[] args) {
Max max = new Max();
max.max = 32;
Integer constrain = max.constrain(33);
Assert.assertEquals(Integer.class, constrain.getClass());
Assert.assertEquals(max.max, constrain);
Double constrain2 = max.constrain(33d);
Assert.assertEquals(Double.class, constrain2.getClass());
Assert.assertEquals(max.max.doubleValue(), constrain2, 0);
Float constrain3 = max.constrain(33f);
Assert.assertEquals(Float.class, constrain3.getClass());
Assert.assertEquals(max.max.floatValue(), constrain3, 0);
Short constrain4 = max.constrain((short) 33);
Assert.assertEquals(Short.class, constrain4.getClass());
Assert.assertEquals(max.max.shortValue(), constrain4, 0);
Byte constrain5 = max.constrain((byte) 33);
Assert.assertEquals(Byte.class, constrain5.getClass());
Assert.assertEquals(max.max.byteValue(), constrain5, 0);
Long constrain6 = max.constrain(33l);
Assert.assertEquals(Long.class, constrain6.getClass());
Assert.assertEquals(max.max.longValue(), constrain6, 0);
BigDecimal constrain7 = max.constrain(BigDecimal.valueOf(33));
Assert.assertEquals(BigDecimal.class, constrain7.getClass());
BigInteger constrain8 = max.constrain(BigInteger.valueOf(33));
Assert.assertEquals(BigInteger.class, constrain8.getClass());
AtomicInteger constrain9 = max.constrain(new AtomicInteger(33));
Assert.assertEquals(AtomicInteger.class, constrain9.getClass());
AtomicLong constrain10 = max.constrain(new AtomicLong(33));
Assert.assertEquals(AtomicLong.class, constrain10.getClass());
}
}
but inside your code to construct all child of number there no common constructor the safest way is to reduce the case you want handle here i didn't handle all Striped64 children
I discovered:
import org.apache.commons.beanutils.ConvertUtils;
...
return (Number)ConvertUtils.convert(max, n.getClass());
I haven't looked at the source, but I doubt it is very clever inside. I believe it just hosts a collection of type converters.
So this is an alternative - not better than the other answers, but at least it is concise.
Edit - v3 - without String.
If you only talk about members of Numbers that allows primitive type as the input of constructor like Float/Double/Integer/Long/..., the following could work:
//Number n is valid someInput;
//Note this only works for Classes that take a single numeric value as input
Class type = (Class) n.getClass().getDeclaredField("TYPE").get(n);
return n.getClass().getConstructor(type).newInstance(max)
Things like BigInteger will not work with this one.
Edit - v2
It seems like, for primitive types n, if the "Number n" is replaced by different signatures and by using Integer.TYPE (or Float.TYPE and etc.) you might pass in the 'int' as parameters of getConstructor. You may use n.TYPE here (but as a reminder TYPE is the class member, and it may pop some warning).
n.getClass().getConstructor(n.TYPE).newInstance(max);
Still, as #azro pointed out: if you insist not using string and want it smart, you still need branches and it could be nastier: you need to consider all subclasses of Number, including BigInteger.
True, casting it to string is nasty, but otherwise, you may need to wrap each subclass of Number with an extra class that allows the non-primitive type as args of the constructor. I barely think if-statements is nastier.
Original Answer
I am not very familiar with Reflection.
But a major problem here is the constructor of Numbers are either String or primitive types like 'int', and you cannot really utilize 'int' as the input of getConstructor.
at least, the following may work.
//assume n is some Number object.
n.getClass().getConstructor(String.class).newInstance(max.toString());
This works as classes like Float/Integer/BigInt.../ have constructors that take String as the input.

java generics compile error, generic class on the stack

I'm not sure why this doesn't work in Java:
import java.util.Map;
public class FreqCounter<T,R> {
private Map<T, Integer> hist;
private R item;
public FreqCounter (final R item_) {
item = item_;
}
public T getMostFrequentElement() {
T most_frequent_element = T();
Integer highestcount = 0;
for(T t : item) {
Integer count = hist.get(t);
if(count == null) {
hist.put(t, 1);
}
else {
hist.put(t, count + 1);
}
if(count + 1 > highestcount) {
most_frequent_element = t;
highestcount = count + 1;
}
}
return most_frequent_element;
}
}
class HelloWorld {
public static void main(String[] args) {
String s = "aaabbcccc";
FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
}
}
Problem lines:
1. T most_frequent_element = T();
2. for(T t : item)
3. FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s);
Cannot find symbol: method T()
required: array or java.lang.Iterable, found: R
Required java.lang.Integer
Found: java.lang.String
reason: actual argument java.lang.String cannot be converted to java.lang.Integer by method invocation conversion
What I was trying to do was make a class that could count how many times an element in an iterable container shows up. Originally I just wanted to make it to count characters in a string but I thought I could make it more general. I think some of this would work in C++?
Also, does FreqCounter<Character, Integer> counter = new FreqCounter<Character, Integer>(s); need to be "newed" as opposed to declared on the stack?
T is a Generic type, not a real one, and one of the limitations of generics is that you cannot instantiate a new one (which is what I think you were trying to do here).
What you can do though is assign, call methods in, keep references too, duplicate references too, etc.
What you probably actually wanted to do was pull the set of Ts out of the keySet of the Map.
T t = null;
int count = 0;
for (Entry<T, Integer> e: hist.entrySet()) {
if (e.getValue() > count) {
count = e.getValue();
t = e.getKey();
}
}
return t;
Java Generics provide a lot of the same functionality that C++ templates do, but they work in quite a different way. Quite apart from anything else you only have one ArrayList class no matter how many different ways you instantiate one. The generics are used for compiler time type checking and then erased and are not present at all during run time.

Java generics and numeric types

I'd like to create a generic method which does effectively this:
class MyClass {
static <T extends Number> T sloppyParseNumber(String str) {
try {
return T.valueOf(str);
} catch (Exception e) {
return (T)0;
}
}
}
Now above does not compile for two reasons: there's no Number.valueOf() method and 0 can't be cast to T.
Example usage:
String value = "0.00000001";
System.out.println("Double: " + MyClass.<Double>sloppyParseNumber(value));
System.out.println("Float: " + MyClass.<Float>sloppyParseNumber(value));
double d = MyClass.sloppyParseNumber(value);
float f = MyClass.sloppyParseNumber(value);
Is implementing above generic method possible with Java? If yes, how? If no, what's a good alternative approach?
Edit: there seems to be a few possible duplicates, but I did not find one, which covers exactly this. I'm hoping there's some trick to pull, which would allow these two operations: parse string to a Number subclass, and return 0 value for a Number subclass.
I agree 100% with TofuBeer. But in case you wish to avoid verbosity for time sake, this should also do:
static <T extends Number> T sloppyParseNumber(String str,Class<T> clas) {
if (clas == null) throw new NullPointerException("clas is null");
try {
if(clas.equals(Integer.class)) {
return (T) Integer.valueOf(str);
}
else if(clas.equals(Double.class)) {
return (T) Double.valueOf(str);
}
//so on
catch(NumberFormatException|NullPointerException ex) {
// force call with valid arguments
return sloppyParseNumber("0", clas);
}
throw new IllegalArgumentException("Invalid clas " + clas);
}
But purely from T, you cannot get the type at runtime.
Java generics only provide compile time checks and the type information is pretty much thrown away after compilation. So the statement T.valueOf isn't possible in Java. The solution is to go the verbose way as already mentioned in the comments. Also, is there any reason why you want to do MyClass.<Double>sloppyParseNumber(value) but not MyClass.sloppyParseDouble(value) since you are anyway specifying the type at compile time?
Static methods are bound by the type, since the type is, at best, Number and Number doesn't have a valueOf method what you are after isn't going to work.
The easiest way is to just make a number of static methods like sloppyParseInt, sloppyParseFloat, etc...
You could do something like this, not sure I like it, and can probably be improved on:
public class Main
{
private static final Map<Class<? extends Number>, NumberConverter> CONVERTERS;
static
{
CONVERTERS = new HashMap<>();
CONVERTERS.put(Integer.class, new IntegerConverter());
}
public static void main(String[] args)
{
Number valueA;
Number valueB;
valueA = CONVERTERS.get(Integer.class).convert("42");
valueB = CONVERTERS.get(Integer.class).convert("Hello, World!");
System.out.println(valueA);
System.out.println(valueB);
}
}
interface NumberConverter<T extends Number>
{
T convert(String str);
}
class IntegerConverter
implements NumberConverter<Integer>
{
#Override
public Integer convert(String str)
{
try
{
return Integer.valueOf(str);
}
catch (NumberFormatException ex)
{
return 0;
}
}
}
So, I decided on an alternative approach:
static String trimTo0(String str) {
if (str == null) return "0";
str = str.trim();
if (str.isEmpty()) return "0";
return str;
}
Usage:
String value = null;
System.out println("Double value: " + Double.parseDouble(trimTo0(value)));
Note that this is more limited than the method in the question, this does not convert invalid, non-numeric strings to "0". Doing that fully would require two separate methods, one supporting decimal point and another just supporting integers.
You can try this:
private <T> T convertToType(Class<T> clazz,String str) throws Exception {
return clazz.getConstructor(String.class).newInstance(str);
}
Here you need to consider that the Type must have a constructor with a String parameter.

Categories