Java JUnit array of classes for SuiteClasses syntax - java

Currently I have the following code to test my class...
#RunWith(Suite.class)
#SuiteClasses( { MyClass.class, MyNewClass } )
public class AllTests {
public static void suite() {
}
}
What I'd like to do would be the following, but it's syntactically incorrect - what would be the correct format?...
Class<?>[] classArray = new Class<?>[] {
MyClass.class, MyNewClass.class
};
#RunWith(Suite.class)
#SuiteClasses( classArray )
public class AllTests {
public static void suite() {
}
}

Unfortunately you can't. Annotations need to take compile-time constants, so you have to use { MyClass.class, MyNewClass.class }.

--- Update ---
The problem seems to stem from Annotations. Annotations require compile time constants, which means you cannot "build an array" of classes in a manner that might have you reassigning the array, or modifying it before the annotated method could access it.
Credit to artbristol for pointing out the obvious. Initially I started down the wrong path, which was to attempt to find out why your array did compile in my 1.7 environment.
Actually, the compile time constant restriction on Annotations makes perfect sense when considering that Annotations are meant to extends java programming via declarative means.
--- Original Post ---
Instead of attempting a wildcard, use
Class<Object>[] classArray = new Class<Object>[] { .... };
It semi-defeats the purpose of generics, since everything extends from Object; but, it will satisfy the "shove anything into it" requirements you need.

By K.Sierra from "SCJP study guide":
"Keep in mind that the wildcards can be used only for reference declarations
(including arguments, variables, return types, and so on). They can't be used as the
type parameter when you create a new typed collection. Think about that—while
a reference can be abstract and polymorphic, the actual object created must be of a
specific type."
List<?> foo = new ArrayList<? extends Animal>();
Problem: you cannot use wildcard notation in the object creation. So the
new ArrayList() will not compile.
EDIT:
#artbristol pointed another problem which is compile-time constant passed to the annotation. Look at the responses in this thread, they might be helpful. One of them suggests ENUM as a workaround.
How to use an array constant in an annotation

Related

Unusual syntax used for object construction

I'm new to Java programming. While reading through the code of an open source project, I came across a line of code which I can't understand:
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
My questions are:
I usually call a constructor like this: final Type typeOfMap = new TypeToken<Map<String, Object>>(). I have never seen it followed by other pieces of code such as {}.getType(). What kind of syntax is this?
Is {} an object? Why can you call a function on it?
P.S. Type is java.lang.reflect.Type, and TypeToken is com.google.gson.reflect.TypeToken.
I'm also new at Java, but, as far as I know, that is a constructor that belongs to an abstract generic class new TypeToken<Map<String, Object>>() {} The class tiself may look something like this: public abstract class TypeToken<X> ... now, for the method .getType(). I'm not really sure how that is coded.
You reminded me that this is in my bucket list of things to learn/understand, but I'm pretty sure that this code pattern is a little too over engineered, (ofc this may be my bias precisely because I dont know it or what it could be useful for)
the .getType() method, may be a method inside the abstract that is public and non abstract.
I personally have found that in some cases (just in some), it is more convenient to instantiate abstract objects instead of extending them (which is how they are usually used), specially in cases when your abstract object needs another object created at an specific lifecycle, or when the abstract object needs interoperability within the same class.
Now If I'm not mistaken, I Think that THAT specific implementation com.google.gson.reflect.TypeToken makes use of reflect in order to get the class type of a non initialized object, without actually creating an object (maybe it does behind curtains), if you've tried to make a newInstance of an Array of nested generic classes, you know how it can become a headache, because of something called "erasure".
I usually call a constructor like this: final Type typeOfMap = new
TypeToken<Map<String, Object>>(). I have never seen it followed by
other pieces of code such as {}.getType(). What kind of syntax is
this?
It is a syntax for Anonymous inner classes.
Is {} an object? Why can you call a function on it?
Yes, you get an object from it. That's why a method can be invoked on it.
Anonymous classes are useful when you need a specific behaviour from a class for a single time. Like in below example, if you invoke sayHello on normal A object, then it will return Hello. But, the behaviour of sayHello method gets changed for object of anonymous class and it returns Bonjour this time.
public class SomeClass {
public static void main(String[] args) {
A defaultObj = new A();
A customObj = new A() {
#Override
public String sayHello() {
return "Bonjour";
}
};
System.out.println(defaultObj.sayHello());
System.out.println(customObj.sayHello());
}
}
class A {
String sayHello() {
return "Hello";
}
}
Output
Hello
Bonjour
Gson documentation for TypeToken also mentions about the reason and usage of anonymous class. The reason for usage in TypeToken class is that it is used to retrieve the type of token at runtime. As otherwise generic type information is not available at runtime because of type erasure.
https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/reflect/TypeToken.html
Represents a generic type T. Java doesn't yet provide a way to
represent generic types, so this class does. Forces clients to create
a subclass of this class which enables retrieval the type information
even at runtime. For example, to create a type literal for
List, you can create an empty anonymous inner class:
TypeToken<List> list = new TypeToken<List>() {};

Java compiler not able to infer type on generic chain

As mentioned below (to remark it as I might have explained myself badly):
I want to understand the principle behind this issue so that I can apply that knowledge to the real problem.
ISSUE START
I am working in a system intended to be an abstract library to be used by many subsystems. The idea is to have an standard behaviour extensible by implementations.
My problem is that java compiler is not able to inferr method parameter type, even though it makes no sense since the boundaries are well set on every related generic class/method.
Below there is an example, the minimum example to reproduce the problem. I am aware it looks a bit silly in this example, but that is because of the simplification:
public class Test {
public static void main(String[] args) {
Gen<? extends Base> gen = new HijaGen();
gen.applyTo(Hija.EXAMPLE);
}
private interface Base {
String getName();
}
private enum Hija implements Base {
EXAMPLE;
#Override
public String getName() {
return this.name();
}
}
private interface Gen<T extends Base> {
boolean applyTo(T base);
}
private static class HijaGen implements Gen<Hija> {
#Override
public boolean applyTo(Hija base) {
return false;
}
}
}
Basically it says that applyTo expects a subclass of Base and Hija is not valid, which from my perspective makes no sense.
Thanks in advance.
EDIT:
This code is for a library, so that the solution could not be specifying the type since then it could not be extensible through particular implementations.
I am already aware that if I specify the generic type instead of throwing a type wildcard it will perfectly work. But my question is how is it possible that even though Hija subclasses Base, and method firm requires a subclass of Base it will never compile...
I want to understand the principle behind this issue so that I can apply that knowledge to the real problem.
A Gen<? extends Base> is a Gen of something which extends Base. It applies to some specific type of Base but we do not know which. In practice, this means you will never be able to call applyTo on a variable with type Gen<? extends Base>, except by passing null.
Change your code to
Gen<Hija> gen = new HijaGen();
gen.applyTo(Hija.EXAMPLE);
I suspect you'll probably say you can't do that, because your code is just an example, and the above is not possible in the real code. In which case you will need to give a better example
I think there is a similar problem explained in the docs here and the problem that they propose is to make a helper (or wrapper) to clarify the types. So I guess you can try adding this function:
private static <T extends Base> boolean applyTo(Gen<T> gen, T base){
return gen.applyTo(base);
}
And change the main function as follows:
public static void main(String[] args) {
boolean b = applyTo(new HijaGen(), Hija.EXAMPLE);
}
On the lines of what Carlos has mentioned, there is one more way to resolve this. It can be used if you are sure of the suppliers of the implementation of Gen<T>.
Here, instead of the helper to call applyTo(), we define a factory method to create the instance of the Gen implementation and cast it to Gen<Base>, which in my opinion is safe for all practical purposes. Note that the factory method get() need not be static. The rest of the code remains unchanged from your sample.
public static void main( String[] args ){
Gen<Base> gen = (Gen<Base>) get();
gen.applyTo( Hija.EXAMPLE );
}
static Gen<? extends Base> get(){
/* Create the instance of the Gen interface implementation here. */
return new HijaGen();
}
Explanation
Gen<? extends Base> expects to refer to an instance of an implementation of Gen that uses a type that is either Base or an sub-type of it. Since a "sub-type" can be from one of many possible hierarchies from Base downward (as shown in the picture below), it cannot be sure that the parameter passed to applyTo() method is of the same child hierarchy path and not just a 'relative' with the same ancestral parent Base. That is why it won't allow a call to applyTo() with its reference being of Gen<? extends Base> for a parameter of with reference as Base.
However, when the reference is Gen<Base>, it knows that applyTo() will accept any parameter that is a child type of Base. And hence, it stops worrying about type mismatch.
I have tried to show what I mean by different child hierarchy paths. It is like the case of a family tree.

How does Lombok.val actually work?

Lombok.val allows you to
use val as the type of a local variable declaration instead of
actually writing the type. When you do this, the type will be inferred from the initializer expression. The local variable will also be made final.
So instead of
final ArrayList<String> example = new ArrayList<String>();
You can write
val example = new ArrayList<String>();
I've tried to do some research into how this actually works but there doesn't seem to be a huge amount of information. Looking at the github page, I can see that val is an annotation type. The annotation type is then used, rather than an actual annotation.
I wasn't even aware you could even use annotation types in this manner but upon testing it the following code is indeed valid. However, I'm still not sure why you would ever want to use the type in this way.
public class Main
{
public #interface Foo { }
public static void main(String... args)
{
Foo bar;
System.out.println("End");
}
}
How does Lombok process these usages if they are not annotations, but annotation types? To my (obviously incorrect) understanding, the syntax should look more like:
#Val foo = new ArrayList<String>();
(I'm aware constraints of annotations mean the above is not valid syntax)
In order for Lombok to work, the source code needs to parse without errors. That's why, as you already mentioned, #val foo = new ArrayList<String>(); wouldn't work.
Although Lombok uses annotations, and an annotation processor, the annotation processor is only used as a means to get involved by the compiler.
Lombok does not have a registered processor for #val. Instead, it processes all java files, visits the whole AST and replaces val by the type of the initialization expression of the local variables.
For the actual replacement, for Eclipse/ecj see this class and this one. For javac, see this class.
Disclosure: I am a Lombok developer.

Change flow of static call (Java)

I have many instances of
Foo.a()
but now I want to split up calls to a() based on certain criteria. If possible I would like to keep the Foo.a() calls unchanged. Instead, perhaps Foo could become a factory that manages the flow and FooA and FooB could extend Foo. For example, in Foo:
private static Class<?> foo;
static {
if (certain_criteria) {
foo = SomeUtil.getClass("FooA");
} else {
foo = FooB.class;
}
Object obj = foo.newInstance();
o = (Foo) obj;
}
...
public static void a() {
o.a(); //And this should call either FooA.a() or FooB.a()
//But a() should be accessed in a static way
}
I can't make a() in Foo non-static because then I'll have to change the 100+ calls throughout the project to Foo.a(). Is there a way around this? Or a better way to handle the flow?
I also tried to use foo to call a(), but that gives a compiler error because it is of type Class?>. If I change it to
Class<Foo>
then I get
Type mismatch: cannot convert from Class<FooB> to Class<Foo>
You propose using static method Foo.a() as a facade over selecting and invoking an appropriate implementation, in a configurable manner chosen by class Foo. Your specific idea seems to rely on subclasses of Foo to implement the Strategy pattern for supporting Foo.a().
You are conflating at least two separable pieces to this:
the strategy for implementing Foo.a(), and
the mechanism by which a specific strategy is chosen and instantiated.
In particular, although you may have reason to want to use subclasses of Foo to represent your strategies in the real code, no such reason is apparent in your example code. Schematically, then, you seem to want something like this:
public class Foo {
private static FooStrategy strategy = FooStrategyFactory.createStrategy();
public static void a() {
strategy.doA();
}
}
interface FooStrategy {
void doA();
}
You don't need to go all the way there, of course. Your original idea was basically to let Foo itself serve in the place of FooStrategy, and to let a static initializer serve instead of a separate FooStrategyFactory. There's nothing inherently wrong with that; I just pull it apart to more clearly show what role each bit serves.
You also expressed some specific implementation issues:
If I change it to Class<Foo> then I get
Type mismatch: cannot convert from Class to Class
The equivalent in my scheme above would be declaring a variable of type Class<FooStrategy>, and attempting to assign to it a Class<FooStrategyA> representing a class that implements FooStrategy. The correct type for a Class object that may represent any class whose instances are assignment-compatible with type FooStrategy is Class<? extends FooStrategy>. That works whether FooStrategy itself is a class or an interface.
I can't call any classes from Foo on foo. "The method a() is undefined for the type Class"
You seem to have been saying that you could not invoke static methods of class Foo on an object of type Class<? extends Foo>. And indeed, you can't. Objects of class Class have only the methods of class Class. Although you can use them to reflectively invoke methods of the classes they represent, such methods are not accessible directly via the Class instance itself. That issue does not arise directly in the scheme I presented, but it could arise in the factory or strategy implementations.
Moreover, static methods are not virtual. They are bound at compile time, based on the formal type of the reference expressions on which they are invoked. In order to apply the strategy pattern correctly, the needed strategy implementation methods need to be virtual: non-private and non-static.

Should java allow classes names to be defined same as generic type parameters?

I created classes like below in the same package test. It was just to test whether java really allows it. And it does but then it comes in to problems.
package test;
public class E {
}
package test;
public class T {
}
package test;
import test.E;
import test.T;
public class K<E, T> {
E e;
T t;
public K(E e, T t) {
this.e = e;
this.t = t;
}
public static void main(String[] args) {
K k = new K<E, T>(new E(), new T());
}
}
Above code give multiple compilation problems
Multiple markers at this line
- Cannot make a static reference to the non-static type E
- Cannot make a static reference to the non-static type T
- Cannot make a static reference to the non-static type T
- Cannot make a static reference to the non-static type E
- K is a raw type. References to generic type K<E,T> should be
parameterized
It clearly shows compiler is confused between E and class E same for T.
So workaround is define it real types using package.
K k = new K<test.E, test.T>(new test.E(), new test.T());
Now if there all these classes are in default package there is no way to solve this compilation issue.
So Question is should java allow declaration of such classes in default package?
It clearly shows compiler is confused between E and class E same for T.
I think you've got that wrong. I think that if you read the relevant parts of the JLS carefully (I'll look them up later) you will find that they clearly state what E and T should resolve to in the various contexts. I would be very surprised if the compiler is getting the resolution wrong; i.e. not implementing the JLS.
In reality, the confusion is in the mind of the person who wrote the code ...
The problem here is that the rules about what takes precedence over what are probably not what you (and typical programmers) expect. But they are like they are for a good reason.
Normally this doesn't matter, but if you ignore the normal Java naming conventions and use one-letter names for classes, then you might get burnt.
So Question is should java allow declaration of such classes in default package?
Alternatively, should "you" be ignoring the Java class naming conventions?
Frankly, there are a lot of ways that a programmer can hurt themselves if they ignore the style guidelines / recommendations. But if you try to protect the programmer too much, you actually hurt him/her by making it impossible to implement stuff where you need to push the envelope. The best policy is (IMO) to not treat programmers as children. If they really want to juggle with sharp knives ... let them.
This is very nice research.
But, you are still allowed to create a class with name String, Java never complained against using same class name. To differentiate whether you use your String class (or) Java provided String class, you need to append the package (full name).
As Matt Ball said, default packages are shouldn't be used.
Backward compatibility could be another reason why Generic Types not defined as "reserve words"
Whether allow same class name (or) not, I think that is what packages are for. As long as there is a way to differentiate which class we are referring to, I think it is perfectly fine to allow same name.
You can get really confused if you want to. I am not sure its up to the compiler to prevent you from writing confusing code but I do think the compiler should try to be clear in its error messages.
public class T<T> {
public T() {
}
public static <T> T T() {
T T = null;
return T; // which T is this?
}
}
Considering you can write
public class String<Object>{}
Disalowing class with same name as how YOU named type parameter or forbiding you to name type parameter as any existing class would be insane (Class with conflicting name can be from another jar created in future, so any name of type parameter can be same as name of some class, and vice versa)

Categories