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>() {};
Related
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.
Let's say you have some Java code as follows:
public class Base{
public void m(int x){
// code
}
}
and then a subclass Derived, which extends Base as follows:
public class Derived extends Base{
public void m(int x){ //this is overriding
// code
}
public void m(double x){ //this is overloading
// code
}
}
and then you have some declarations as follows:
Base b = new Base();
Base d = new Derived();
Derived e = new Derived();
b.m(5); //works
d.m(6); //works
d.m(7.0); //does not compile
e.m(8.0); //works
For the one that does not compile, I understand that you are passing in a double into Base's version of the m method, but what I do not understand is... what is the point of ever having a declaration like "Base b = new Derived();" ?
It seems like a good way to run into all kinds of casting problems, and if you want to use a Derived object, why not just go for a declaration like for "e"?
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java. The way I learned it earlier this summer was, every object has one class, which corresponds to the name of the class following "new" when you instantiate an object, but an object can have as many types as it wants. For example, "e" has type Base, Derived, (and Object ;) ) but its class is Derived. Is this correct?
Also, if Derived implemented an interface called CanDoMath (while still extending Base), is it correct to say that it has type "CanDoMath" as well as Base, Derived, and Object?
I often write functions in the following form:
public Collection<MyObject> foo() {}
public void bar(Collection<MyObject> stuff){}
I could just as easily have made it ArrayList in both instances, however what happens if I later decide to make the representation a Set? The answer is I have a lot of refactoring to do since I changed my method contract. However, if I leave it as Collection I can seamlessly change from ArrayList to HashSet at will. Using the example of ArrayList it has the following types:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
There are a number of cases where confining yourself to a particular (sub)class is not desired, such as the case you have where e.m(8.0);. Suppose, for example, you have a method called move that moves an object in the coordinate graph of a program. However, at the time you write the method you may have both cartesian and radial graphs, handled by different classes.
If you rely on knowing what the sub-class is, you force yourself into a position wherein higher levels of code must know about lower levels of code, when really they just want to rely on the fact that a particular method with a particular signature exists. There are lots of good examples:
Wanting to apply a query to a database while being agnostic to how the connection is made.
Wanting to authenticate a user, without having to know ahead of time the strategy being used.
Wanting to encrypt information, without needing to rip out a bunch of code when a better encryption technique comes along.
In these situations, you simply want to ensure the object has a particular type, which guarantees that particular method signatures are available. In this way your example is contrived; you're asking why not just use a class that has a method wherein a double is the signature's parameter, instead of a class where that isn't available. (Simply put; you can't use a class that doesn't have the available method.)
There is another reason as well. Consider:
class Base {
public void Blah() {
//code
}
}
class Extended extends Base {
private int SuperSensitiveVariable;
public setSuperSensistiveVariable(int value) {
this.SuperSensistiveVariable = value;
}
public void Blah() {
//code
}
}
//elsewhere
Base b = new Extended();
Extended e = new Extended();
Note that in the b case, I do not have access to the method set() and thus can't muck up the super sensitive variable accidentally. I can only do that in the e case. This helps make sure those things are only done in the right place.
Your definition of type is good, as is your understanding of what types a particular object would have.
What is the point of having Base b = new Derived();?
The point of this is using polymorphism to change your implementation. For example, someone might do:
List<String> strings = new LinkedList<String>();
If they do some profiling and find that the most common operation on this list is inefficient for the type of list, they can swap it out for an ArrayList. In this way you get flexibility.
if you want to use a Derived object
If you need the methods on the derived object, then you would use the derived object. Have a look at the BufferedInputStream class - you use this not because of its internal implementation but because it wraps an InputStream and provides convenience methods.
Also, I'm a bit confused as to the meaning of the word "type" as it is used in Java.
It sounds like your teacher is referring to Interfaces and Classes as "types". This is a reasonable abstraction, as a class that implement an interface and extends a class can be referred to in 3 ways, i.e.
public class Foo extends AbstractFoo implements Comparable<Foo>
// Usage
Comparable<Foo> comparable = new Foo();
AbstractFoo abstractFoo = new Foo();
Foo foo = new Foo();
An example of the types being used in different contexts:
new ArrayList<Comparable>().Add(new Foo()); // Foo can be in a collection of Comparable
new ArrayList<AbstractFoo>().Add(new Foo()); // Also in an AbstractFoo collection
This is one of the classic problems on object oriented designs. When something like this happens, it usually means the design can be improved; there is almost always a somewhat elegant solution to these problems....
For example, why dont you pull the m that takes a double up into the base class?
With respect to your second question, an object can have more than one type, because Interfaces are also types, and classes can implement more than one interface.
(This is probably a duplicate, but I could not find it - feel free to point it out)
Consider the following Java class:
public class A<T0, T1> {
public A(T0 t0, T1 t1) {
...
}
}
Instantiating this class is easy using something along the lines of new A<Integer, String>(1, "X").
Suppose now that most instances of this class have a String as the second type parameter T1 and that the object of this type used in the constructor call is also pretty much standard.
If A had not been using generics, a common extension would be an additional constructor without the second argument:
public class A {
public A(int t0, String t1) {
...
}
public A(int t0) {
this(t0, new String("X"));
}
}
Unfortunately, this does not seem to be possible for a class that does use generics - at least not without a forced cast:
public A(T0 t0) {
this(t0, (T1)(...));
}
The reason? While this constructor only takes a single argument, it still uses two type parameters and there is no way to know a priori that whatever type T1 the user of the class supplies will be compatible with the default value used in the constructor.
A slightly more elegant solution involves the use of a subclass:
public class B<T0> extends A<T0, String> {
...
}
But this approach forces yet another branch in the class hierarchy and yet another class file with what is essentially boilerplate code.
Is there a way to declare a constructor that forces one or more of the type parameters to a specific type? Something with the same effects as using a subclass, but without the hassle?
Is there something fundamentally wrong in my understanding of generics and/or my design? Or is this a valid issue?
Easiest method is just to add a static creation method.
public static <T0> A<T0,String> newThing(T0 t0) {
return new A<T0,String>(t0, "X");
}
(Perhaps choose a name appropriate for the particular usage. Usually no need for new String("...").)
From Java SE 7, you can use the diamond:
A<Thing,String> a = new A<>(thing);
As I understand it, you want to have a second constructor that (if called) would force the generic type T1 to be a String.
However, the generics are specified BEFORE you call the constructor.
That second constructor, if valid, could allow someone to do this:
B<Integer, Integer> b = new B<Integer, Integer>(5);
The error here is that you've specified the second generic type as an Integer BEFORE calling the constructor. And then the constructor would, in theory, specify the second generic type as a String. Which is why I believe it's not allowed.
You could qualify the generic types, i.e.
A<T0, T1 super MyDefaultType> {
public A(T0 t0) {
this(t0, new MyDefaultType());
}
}
You can't use T1 extends MyDefaultType since if you define a subclass, a MyDefaultType instance would not be compatible with the type of T1.
"Most instances" is the root problem.
Either T1 is a parameterized type or not. The single-argument constructor presumes both. Therein lies the problem.
The subclass solution solves the problem by making all instances satisfy T1=String.
A named constructor / factory method would also solve the problem, by ensuring T1=String.
public static <T0> A<T0,String> makeA( T0 t0 ) {
return new A<T0,String>( t0, "foo" );
}
Is there a way to declare a constructor that forces one or more of the type parameters to a specific type? Something with the same effects as using a subclass, but without the hassle?
I believe it is impossible. Think about this. Developer defines class that can be generic, i.e. the type of parameter is defined during creating the object. How can the developer define constructor that forces user to use specific type of the parameter?
EDIT:
If you need this you have to create factory or factory method that creates instances of this class with predefined parameter type.
Subclass it. As far as I've ever been taught, that's one of the great features of OOP. Enjoy it. Disk space is cheap.
If it's an issue with future maintenance of the code, consider making the original class abstract, and creating two subclasses off of it (one with the double-generic constructor, and one with the single.
My question is very similar to this question. I want to be able to instantiate an object of the type parameter type, but also without needing to pass in a "factory". I really need to be contained all in the one class.
public class myClass<E> {
E someObject;
public myClass(){
someObject = new E();
}
}
Previous solutions required the constructor of myClass to be changed to have a factory parameter, and then to call the constructor of that, but for my purposes I don't want to modify any calls to myClass from the outside.
The problem is that you don't know what E is, nor how to construct it. It could be any type (it's universally quantified). You need to supply evidence that, whatever E is, it can really be constructed. A "factory" of a given type serves as a kind of witness to the fact that it can.
Think about this for a second: What if I pass Void as the parameter E? How would you go about constructing a value of type Void?
Being able to construct E for all E would be like creating something out of nothing. It's a logical impossibility. ∀E. E is an uninhabited set.
What you really want is either for E to have a bound, or to pass a constructor (factory) as a witness of the fact that E is in the set of constructable objects.
No, as explained in answers to the linked question, you can't do that. Modify the interface to pass in a factory object. (NB: Class makes a bad factory.)
You know your code doesn't work, and you are expecting a solution with a close enough syntax.
How about this?
//doesn't work. cannot make x.someObject a new String()
//MyClass<String> x = new MyClass<String>();
//this can work...
MyClass<String> x = MyClass.neu(String.class);
public class MyClass<E>
{
static public <T> MyClass<T> neu(Class<T> clazz){...}
}
I need to write a function that accepts an object , but I want to enforce in the function call (not after the function is called) that the object is an interface.
Meaning , I want to make sure this is an Interface at compile time , not on run time.
What do I mean?
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
In this example , the passed object is an interface , and I want that the MyClass.register function to enforce the this requirment in it's declaration.
I don't know which interface I'm going to get , and there is no use defining another interface to be implemented by all other implementation , because I need the real interface.
To accept only objects that implement an interface as argument, use the interface as type, i.e.:
void acceptMaps(Map argument) {
}
can be called with objects implementing the Map interface, like HashMap but not with Strings for instance as they do not implement Map.
Is this what you meant with your question?
Edit in this example, objects implementing SortedMap which extends Map are accepted too, so in your case you could create a BaseInterface and extend that in the interfaces (like AcceptedInterface extends BaseInterface) you want to be accepted by your .register(BaseInterface arg) method.
You can't instantiate an interface so you would never be able to create one to send in. You can specify an interface in the parameters for the function and only objects which implement that interface can be passed in. But there is no way to require an interface be what is passed in because you can't create them.
I think you need to rethink what you're trying to accomplish.
You're making a distinction between the type of the object (in this case A) and the type of the reference to the object (in this case ISomething).
Sounds like you want to permit this code:
ISomething something = new A();
MyClass.register(something);
but forbid this code:
A something = new A();
MyClass.register(something);
I don't think you can achieve this with Java.
Let me see if I understand.
Do you want to check at compile time that the argument passed to a function is some interface? Any interface?
If that's the question, the answer is you can't.
I don't know which interface I'm going to get [...] I need the real interface.
You can't actually validate if you don't know which type to expect.
In Java you need to know the type to validate the parameter, the argument must be of the same type or a descendant, Java doesn't make distinctions on this regard at compile time, you can make it at runtime as Daff aswered.
You can ask the class of the object you get interfaces it implements during runtime.
If you can't already give the compiler the types of the interfaces you expect it has no way to predict what is going to be passed into your method so you will have to use runtime reflection.
There's no way to check at runtime, if the 'object is an interface' because an object can never ever be 'an interface', it only be an instance of a class that implements an interface.
And it's not possible to restrict a method signature to interface usage, say you'll allow type 'Animal' but not type 'Dog' which implements animal behavior. (I guess that's what you were looking for)
Taking your example - you want a compiler error for this implementation:
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here
But practically spoken - I see no immediate reason. If you want to enforce programmers to use interfaces - user code inspection or quality check tools. If you want to restrict instantiation of an implementation, protect the constructor and use a factory to produce instances.
"The object is an interface" doesn't make sense. It seems like you want to enforce that the pointer passed into the function was declared with an interface type like
Interface_t x = new Class_which_implements_interface_t();
as opposed to
Class_which_implements_interface_t y = new Class_which_imlements_interface_t();
The only problem is that if you make a function like this:
void some_func(Interface_t z) {...}
And you call it with some_func(x); or some_func(y); the function is passing the reference by value, which means that inside of some_func, z is a copy of x or y which has been casted to an Interface_t pointer. There is no way to get information about what type the original pointer had. As long as it is able to be casted to an Interface_t it will compile and run.