When is the diamond operator, and when not? - java

Consider the following two lines of code:
final List<Path> paths = new ArrayList<>();
final FileVisitor<Path> fv = new SimpleFileVisitor<>();
To me, they look quite similar. However, the second line is refused by the Java compiler (1.8) with the message "Cannot infer type arguments for SimpleFileVisitor<>".
Can anyone please explain, what's the problem?

I don't see how you may get the error message Cannot infer type arguments because your syntax is correct, except for the fact that as many have said already, the class java.nio.file.SimpleFileVisitor has only one constructor which is protected:
protected SimpleFileVisitor() {
}
This means that only children of this class can initialize an instance of SimpleFileVisitor, and that's why your code doesn't compile.
I don't know this class, but by a quick look at the code I guess they simply expect you to extend it first (or use an already existing extension coming from somewhere else), and then use it the implementations of the FileVisitor interface.
If you don't have a concrete child class to use and want to create your own MySimpleFileVisitor:
public class MySimpleFileVisitor<T> extends SimpleFileVisitor<T> {
public MySimpleFileVisitor() {
super(); //<-- here you have the right to call the protected constructor of SimpleFileVisitor
}
}
... you will then be able to instantiate your class and use the already implemented methods like this:
FileVisitor<Path> fv = new MySimpleFileVisitor<>(); //<-- here you will be able to correctly infer parameter type as you do in your List example
fv.visitFile(file, attrs); //<-- here you enter the method implemented inside SimpleFileVisitor

Related

Init Generic Class Using Reflection Java

I am currently automating a process of a data handler. What I mean with automating is that the DataHandlers are initiated automatically via reflection based on a specific configuration.
But I am on a point where I do not know how I should solve this problem. It is about this peace of code:
Class<?> clazz = classLoader.loadClass(d);
Object values = clazz.getMethod("values").invoke(null);
RSA.addDataHandler(clazz,new DataHandlerSetAdapter<>(values));
I am loading the class via the classLoader and invoking a static method called "values" which returned a bunch of, you have suggested right, values!
Now the problem is with new DataHandlerSetAdapter<>(values)) which has an error in <> because the Object does not know which class to initiate.
Cannot infer arguments (unable to resolve constructor)
Would this code be in C# I would use typeof() but in JAVA there is nothing like this maybe instanceof but I cannot use this at this point. Btw .values() is returning an Array of the same type class (enum).
How can I solve this problem?
//edit
with the method .getReturnType() on the Method I would get the return type but I cannot apply it to the DataHandlerSetAdapter<>
Class DataHandlerSetAdapter
public class DataHandlerSetAdapter<T> implements DataHandler<T> {
private final Set<T> values = new ConcurrentSkipListSet<>();
.
.
.
}
It is not clear to me what you are trying to do. But if the loadable class is an enum, then why you are not doing it like this:
Class<? extends Enum<?>> clazz = classLoader.loadClass(d);
Enum<?>[] values = clazz.getEnumConstants();
RSA.addDataHandler(clazz, new DataHandlerSetAdapter<>(values));
Alternatively you can use raw types:
RSA.addDataHandler(clazz, new DataHandlerSetAdapter(values)) - note no diamonds <>.
But Still I'm not sure weather will this work for you or not. Please provide the following information to understand the root cause of failure.
Signature of DataHandlerSetAdapter constructor
Signature of RSA.addDataHandler(...) method
More info about RSA you used in your code snippet. (e.g. Is it a class or object)

Java method reference to a method with generic parameter

I'm trying to make a method reference to a method which have a generic parameter specified in a class declaration.
So I have:
public interface IExecutable<P extends IParameter> {
void execute(P parameter);
}
public class Parameter implements IParameter {
public void childSpecific() {
...
}
}
public class TestClass {
...
//somewhere in the code
public void foo(Parameter parameter) {
parameter.childSpecific();
}
public void test() {
IExecutable<?> executable = this::foo; //compilation error
// The type TestClass does not define inner(IParameter) that is applicable here
executable.execute(new Parameter()); //compilation error as well
// The method execute(capture#4-of ?) in the type IExecutable<capture#4-of ?> is not applicable for the arguments (Parameter)
}
...
}
It's specific that I don't know the concrete generic type of the executable here. Using
IExecutable<Parameter> = ...
solves the problem immediately, but it's impossible for the case.
Clearly, I'm doing something wrong. But how to make it work?
Thx.
In this case, foo is not written to handle any IParameter other than Parameter. You could assign a reference to foo to a variable of type IExecutable<? extends IParameter>, however this means that it is an executable that handles some unknown type of IParameter (in this case, Parameter). Since the specific subtype is unknown, it would not be syntactically safe to pass any subtype of IParameter in to its execute method, since you don't know which it can handle within this scope!
What you need is another type variable instead of using a capture (the ?). This way you can specify that the IParameter you're passing in is the same type as the IParameter the executable accepts. You could introduce this with a new method, like I'm doing below:
public class TestClass {
public static void foo(Parameter parameter) {
parameter.childSpecific();
}
public static void main(String args) {
execute(TestClass::foo, new Parameter());
}
public static <P extends IParameter> void execute(
IExecutable<P> executable, P param) {
executable.execute(param);
}
}
The type parameter P in your interface IExecutable is constrained to being a subtype of IParameter. Consider these two subtypes:
class Parameter implements IParameter { ... }
class AnotherParameter implements IParameter { ... }
Now, an IExecutable<?> is not more specific regarding the above mentioned constraint. In fact, the ? states that it is bound to an unknown subtype of IParameter, which could be Parameter or AnotherParameter (in my example).
With such a variable declaration, you face the two problems you mentioned.
Your method foo(Parameter) does not match the more general constraint of an IExecutable<?>. As seen above, such an executable could be bound to AnotherParameter which clearly would violate the method signature of foo.
Even if it matched, it cannot be used like you did. The compiler does not know to which type the ? actually was mapped. The only thing it knows: It must be a subtype of IParameter, but which one is not known. That means, the statement executable.execute(new Parameter()) is not allowed (as also executable.execute(new AnotherParameter())). The only parameter you are allowed to pass to execute is null.
Conclusion: Point 1 could be solved by declaring the variable executable with type IExecutable<? extends Parameter>. This matches the method signature of foo. But point 2 still does not allow the call to execute.
The only thing you can do is to declare the variable as
IExecutable<Parameter> executable = this::foo;
This will compile and allow the call to
executable.execute(new Parameter());
This line exposes failure in java type inference
IExecutable<?> executable = this::foo;
Let's look at it this way
IExecutable<?> executable = p->this.foo(p);
To compile it, java needs to know the meaning of foo(p). Before java8, the type of an expression is built on the types of sub-expressions; here, the type of p needs to be known 1st to resolve foo. But the type of p is not specified, it needs to be inferred from surrounding context. Here the context is IExecutable<? extends IParameter>, and p is inferred to IParameter - and method foo(Iparameter) does not exist.
In general, type inference faces a dilemma, does it infer from top down, or bottom up? Java8 defines an extremely complicated procedure for that, which is humanly impossible to understand:)
Workarounds: specify the type of p
IExecutable<?> executable = (Parameter p)->this.foo(p);
or specify a more specific target type
IExecutable<?> executable = (IExecutable<Parameter>)p->this.foo(p);
IExecutable<?> executable = (IExecutable<Parameter>)this::foo;
If you ask the language designers, they'd consider all of this is quite obvious ... but a programmer's best action is probably just try different things till it works, than to study the actual language spec.

Passing Class<?> cls as a method parameter?

I'm having trouble completing this method.
I am trying to write a method that will let my main pass two parameters: a Talker object instance and cls a Class object representing the type which the Listener should extend from in order to receive the message. I'm very new to Java and could use some help with this.
Here's the code for the method:
public void sMessage(Talker talker, Class<?> cls) {
for ( Listener l : mParticipants)
{
if (cls.isAssignableFrom(cls.getSuperclass())) {
l.onMessageReceived(talker.getMessage());
}
}
}
Not sure how I should complete this, or how to make a call from main:
singletonDemo.sMessage(demoTalker, Class?);
Not really following the examples I've seen so far. Any suggestions?
#BornToCode is correct about calling the method, but what you want to achieve with the method is still slightly wrong.
cls.isAssignableFrom(cls.getSuperclass())
will always return false. This is because you cannot take a parent class and assign it to the child class. I believe what you are looking for is a way to check if the listener extends the class specified. You can do this by getting the class of the listener.
cls.isAssignableFrom(l.getClass())
or more simply
cls.isInstance(l)
I do not understand what cls should represent. However, you should get something like:
singletonDemo.sMessage(demoTalker, SomeClass.class);
or:
singletonDemo.sMessage(demoTalker, someClassInstance.getClass());
For your information, cls.isAssignableFrom(cls.getSuperclass()) will always return false. The documentation of isAssignableFrom says:
Determines if the class or interface represented by this Class object is either the same
as, or is a superclass or superinterface of, the class or interface represented by the
specified Class parameter.

Java generics question - Class<T> vs. T?

I'm using Hibernate validator and trying to create a little util class:
public class DataRecordValidator<T> {
public void validate(Class<T> clazz, T validateMe) {
ClassValidator<T> validator = new ClassValidator<T>(clazz);
InvalidValue[] errors = validator.getInvalidValues(validateMe);
[...]
}
}
Question is, why do I need to supply the Class<T> clazz parameter when executing new ClassValidator<T>(clazz)? Why can't you specify:
T as in ClassValidator<T>(T)?
validateMe.getClass() as in ClassValidator<T>(validateMe.getClass())
I get errors when I try to do both options.
Edit: I understand why #1 doesn't work. But I don't get why #2 doesn't work. I currently get this error with #2:
cannot find symbol
symbol : constructor ClassValidator(java.lang.Class<capture#279 of ? extends java.lang.Object>)
location: class org.hibernate.validator.ClassValidator<T>
Note: Hibernate API method is (here)
Because T is not a value - it's just a hint for the compiler. The JVM has no clue of the T. You can use generics only as a type for the purposes of type checking at compile time.
If the validate method is yours, then you can safely skip the Class atribute.
public void validate(T validateMe) {
ClassValidator<T> validator =
new ClassValidator<T>((Class<T>) validateMe.getClass());
...
}
But the ClassValidator constructor requires a Class argument.
Using an unsafe cast is not preferred, but in this case it is actually safe if you don't have something like this:
class A {..}
class B extends A {..}
new DataRecordValidator<A>.validate(new B());
If you think you will need to do something like that, include the Class argument in the method. Otherwise you may be getting ClassCastException at runtime, but this is easily debuggable, although it's not quite the idea behind generics.
Because ClassValidator is requiring a Class object as its parameter, NOT an instance of the class in question. Bear in mind you might be able to do what you're trying to do with this code:
ClassValidator<? extends T> validator = new ClassValidator<? extends T>(validateMe.getClass());

How to cast a complete list without iterating through it in Java

Say I have this class :
public class BaseJob{
String name;
public void setName(String name){
this.name=name;
}
public String getName()
{
return name;
}
}
and another class that extends it :
public class DetailedJob extends BaseJob{
public void doThing();
}
Furthermore, I have this method in another class :
List<BaseJob> getSomeJobs()
Now, my problem is :
is it possible to avoid to cast each item sequentially in the returned list of getSomeJobs, if I know for sure that every BaseJob returned is indeed a DetailedJob ?
Put differently, is there another solution than the following to cast all items in the list :
List<BaseJob> baseJobList = getSomeJobs();
List<DetailedJob> detailedJobList = new ArrayList<DetailedJob>();
for (BaseJob baseJob : baseJobList)
detailedJobList.add((DetailedJob) baseJob);
Probably what you want to do is parameterising the class that defines getSomeJobs.
public final class JobHolder<T extends BaseJob> {
public List<T> getSomeJobs() {
...
Generally unchecked casts indicate a design problem. They are unavoidable in certain situations such as low-level implementations and when dealing with serialisation.
If you know that all of the jobs are going to be detailed jobs, why would you put them in an arraylist of basejobs? There's no reason to, and that method would eliminate many possible errors and exceptions.
Well, there's:
List<BaseJob> baseJobList = getSomeJobs();
#SuppressWarnings("unchecked")
List<DetailedJob> detailedJobList = (List) baseJobList;
The downside of this is that if any of the jobs in the list aren't detailed jobs, the exception will only be thrown when someone tries to fetch it. Also, if a new non-detailed job is added to baseJobList afterwards, that could screw up anyone using detailedJobList. Basically you've lost a lot of type safety. In some cases you may not care, but it's not something you should do lightly.
You could create a parameterized getSomeJobs method to take in an argument saying that you know everything is a DetailedJob, meaning that it would return a DetailedJob list rather than the base class.
If you use instanceof, you wouldn't even need to cast, you could just ask if each element is an instance of a DetailedJob and proceed for there. This is almost no better than looping through each object and casting, however.
While it doesn't directly solve your casting problem I'd be temped to use two methods on the 'other class':
List<BaseJob> getAllJobs();
and
List<DetailedJob> getDetailedJobs();
This makes your code more readable to anyone using the 'other class' and will hopefully prevent mistakes.
Either that or I'd genericise the 'other class' like #Tom Hawtin suggests.
Your other class that provides the getSomeJobs method should implement an interface (to help with your unit testing, among other things). Let's call it JobProvider. You can declare the interface such that it will always produce a list of something that extends a base job, and in subclasses where you know your job is always going to be of a certain sub-type, you can narrow the type definition there.
interface JobProvider {
List<? extends BaseJob> getSomeJobs();
}
class JobProviderImpl implements JobProvider {
public List<DetailedJob> getSomeJobs() {
// do stuff and return
}
}
Now, in other code, if you know you're dealing with a JobProviderImpl, you can case it and know that the list will contain only DetailedJobs.
if (provider instanceof JobProviderImpl) {
List<DetailedJob> detailedJobs = ((JobProviderImpl) provider).getSomeJobs();
}
Make getSomeJobs() or write another function getSomeDetailedJobs() that returns
List < DetailedJob> instead of List < BaseJob>. I dont know how else we can be "sure" about all elements being of type DetailedJobs.

Categories

Resources