In Java, the standard way to create an object is using
MyClass name = new MyClass();
I also often see the construct
new MyClass() { /*stuff goes in here*/ };
I've been looking online for a while and can't find a good explanation of what the second construct style does or how it does it.
Can someone please explain how and why you would use the second construct?
This construct makes actually two things: 1) It declares an anonymous class which extends the class you use in the constructor and 2) creates an instance of this anonymous class.
Edit: When using such a construct you can observe the anonymous class by looking at the generated .class files. There is the normal MyClass.class file and another one for each anonymous subclass: MyClass$1.class for the first and so on.
You would use the second construct in the case that you want to make an anonymous class. if you have a method that takes a callback as an argument, you might want to specify the implementation of the callback inline as opposed to giving it a name and putting it in a separate file or declaring it elsewhere in the same file.
There's also a trick called double brace initialization where you can get around not having syntax for literal maps and lists by using anonymous classes, like this:
Map map = new HashMap() {{put("foo", 1); put("bar", 2);}};
Here the nested braces create an instance initializer. The object bound to map is not a HashMap, its class is an anonymous class extending HashMap. (That means if you have a PMD rule about classes needing to declare serial uids then it will complain about this.)
Double-brace initialization is a fun trick to know but don't use it in real code. It's not safe to pass around the map created like this, because the inner object keeps a reference to the outer instance so if anything in the program holds onto a reference to the map it keeps the outer object from getting garbage-collected. There are also problems with serialization.
As others have already said, it creates an instance of an anonymous class, subclassing Class. Here's an example how it is commonly used:
panel.addMouseListener(
new MouseAdapter () {
#Override
public void mouseEntered(MouseEvent e) {
System.out.println(e.toString());
}
}
);
The above code creates an instance of an anonymous class which extends MouseAdapter. In the anonymous class the method mouseEntered has been overridden to demonstrate that the anonymous class works basically as any other class. This is very convenient and common way to create (usually simple) listeners.
Second construction creates an instance of anonymous class which is a subclass of Class.
If you want to new a object by a protect constructor from another package, you can use:
new Foo() {};
otherwise you will get an access error. It equals anonymous subclass inherited from Foo class.
From jdk8 onwards you may have seen different syntax seems like creating an objects while using lambda expressions.
NOTE: Lambda expressions don't get translated into anonymous inner classes, they use invoke dynamic that was introduced in Java 7 to execute functional methods.
For Example:
public class LambdaSample {
public static void main(String[] args) {
//If implementation is only one statement then {} braces are optional
Runnable oneLineImplRunnable = ()->System.out.println("This is one line lambda expression");
//Multiple statements in the implementation then {} braces are mandatory
Comparator<StudentTest> stdComparator = (StudentTest s1,StudentTest s2)->{
if(s1.getFirstName().equals(s2.getFirstName())) {
return s1.getLastName().compareTo(s2.getLastName());
}else {
return s1.getFirstName().compareTo(s2.getFirstName());
}
};
}
}
Related
I made a small research on web and reviewed related topics on this site, but the answers were contradictory: some people said it is not possible, others said it is possible, but dangerous.
The goal is to pass an object of the anonymous class as a parameter of the RMI method. Due to RMI requirements, this class must be serializable. Here's no problem, it is easy to make class Serializable.
But we know that instances of inner classes hold a reference to an outer class (and anonymous classes are inner classes). Because of this, when we serialize instance of inner class, instance of outer class is serialized as well as a field. Here's the place where problems come: outer class is not serializable, and what's more important - I do not want to serialize it. What I want to do is just to send instance of the anonymous class.
Easy example - this is an RMI service with a method that accepts Runnable:
public interface RPCService {
Object call(SerializableRunnable runnable);
}
And here is how I'd like to call the method
void call() {
myRpcService.call(new SerializableRunnable() {
#Override
public Object run {
System.out.println("It worked!");
}
}
}
As you can see, what I want to do is to send an "action" to the other side - system A describes the code, that should be run on system B. It is like sending a script in Java.
I can easily see some dangerous consequences, if this was possible: for example if we access a field or captured final variable of outer class from Runnable - we'll get into a trouble, because caller instance is not present. On the other hand, if I use safe code in my Runnable (compiler can check it), then I don't see reasons to forbid this action.
So if someone knows, how writeObject() and readObject() methods should be properly overriden in anonymous class OR how to make reference to outer class transient OR explain why it is impossible in java, it will be very helpful.
UPD
Yet another important thing to consider: outer class is not present in the environment that will execute the method (system B), that's why information about it should be fully excluded to avoid NoClassDefFoundError.
You could try making Caller.call() a static method.
However, the anonymous class would still need to be available in the context in which you deserialize the serialized instance. That is unavoidable.
(It is hard to imagine a situation where the anonymous class would be available but the enclosing class isn't.)
So, if someone can show, how I can properly override writeObject and readObject methods in my anonymous class ...
If you make Caller.call() static, then you would do this just like you would if it was a named class, I think. (I'm sure you can find examples of that for yourself.)
Indeed, (modulo the anonymous class availability issue) it works. Here, the static main method substitutes for a static Classer.call() method. The program compiles and runs, showing that an anonymous class declared in a static method can be serialized and deserialized.
import java.io.*;
public class Bar {
private interface Foo extends Runnable, Serializable {}
public static void main (String[] args)
throws InterruptedException, IOException, ClassNotFoundException {
Runnable foo = new Foo() {
#Override
public void run() {
System.out.println("Lala");
}
};
Thread t = new Thread(foo);
t.start();
t.join();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(foo);
oos.close();
Foo foofoo = (Foo) new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray())).readObject();
t = new Thread(foofoo);
t.start();
t.join();
}
}
Another important thing to remember about: the Caller class is not present in the environment, that executes the method, so I'd like to exclude all information about it during serialization to avoid NoClassDefFoundError.
There is no way to avoid that. The reason that deserialization in the remote JVM is complaining is that the class descriptor includes a reference to the outer class. The deserializing side needs to resolve that reference even if you managed to clobber the reference, and even if you never explicitly or implicitly used the synthetic variable in the deserialized object.
The problem is that the remote JVM's classloader needs to know the type of the outer class when it loads the classfile for the inner class. It is needed for verification. It is needed for reflection. It is needed by the garbage collector.
There is no workaround.
(I'm not sure if this also applies to a static inner class ... but I suspect that it does.)
Attempting to serialize anonymous Runnable instance without outer class refers not only to a serialization problem, but to a possibility of arbitrary code execution in another environment. It would be nice to see a JLS reference, describing this question.
There is no JLS reference for this. Serialization and classloaders are not specified in the JLS. (Class initialization is ... but that is a different issue.)
It is possible to run arbitrary code on a remote system via RMI. However you need to implement RMI dynamic class loading to achieve this. Here is a reference:
http://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/rmi/spec/rmi-arch.doc.html#280
Note that adding dynamic class loading for remote classes to RMI introduces significant security issues. And you have to consider issues like classloader leaks.
If you mad enough to do the trick you can use reflection to find field that contains reference to outer class and set it to null.
Your example as stated above cannot work in Java because the anonymous inner class is declared within class Caller, and you explicitly stated that class Caller in not available on the RPC server (if I understood that correctly). Note that with Java RPC, only data is sent over the network, the classes must already be available on the client and the server. It that respect your example doesn't make sense because it looks like you want to send code instead of data. Typically you would have your serializable classes in a JAR that is available to the server and the client, and each serializable class should have a unique serialVersionUID.
You can't do exactly what you want, which is to serialize an anonymous inner class, without also making its enclosing instance serializable and serializing it too. The same applies to local classes. These unavoidably have hidden fields referencing their enclosing instances, so serializing an instance will also attempt to serialize their enclosing instances.
There are a couple different approaches you can try.
If you're using Java 8, you can use a lambda expression instead of an anonymous inner class. A serializable lambda expression does not (necessarily) have a reference to its enclosing instance. You just need to make sure that your lambda expression doesn't reference this explicitly or implicitly, such as by using fields or instance methods of the enclosing class. The code for this would look like this:
public class Caller {
void call() {
getRpcService().call(() -> {
System.out.println("It worked!");
return null;
});
}
(The return null is there because RPCService.Runnable.run() is declared to return Object.)
Also note that any values captured by this lambda (e.g., local variables, or static fields of the enclosing class) must also be serializable.
If you're not using Java 8, your next best alternative is to use a static, nested class.
public class Caller {
static class StaticNested implements RPCService.Runnable {
#Override
public Object run() {
System.out.println("StaticNested worked!");
return null;
}
}
void call() {
getRpcService().call(new StaticNested());
}
}
The main difference here is that this lacks the ability to capture instance fields of Caller or local variables from the call() method. If necessary, these could be passed as constructor arguments. Of course, everything passed this way must be serializable.
A variation on this, if you really want to use an anonymous class, is to instantiate it in a static context. (See JLS 15.9.2.) In this case the anonymous class won't have an enclosing instance. The code would look like this:
public class Caller {
static RPCService.Runnable staticAnonymous = new RPCService.Runnable() {
#Override
public Object run() {
System.out.println("staticAnonymous worked!");
return null;
}
};
void call() {
getRpcService().call(staticAnonymous);
}
}
This hardly buys you anything vs. a static nested class, though. You still have to name the field it's stored in, and you still can't capture anything, and you can't even pass values to the constructor. But it does satisfy your the letter of your initial question, which is how to serialize an instance of an anonymous class without serializing an enclosing instance.
The answer is no. You cannot do that since Inner class will need outer class to be serialized. Also you would run into troubles when you'd try to call the instance method of the outer class within the inner class. Why don't you just have another top level class which you could send?
I'd like to add to this topic. There is a way to achieve what you want, but will require reflection.
Here is a good tutorial on implementing a custom serializable object using writeObject and readObject
And here is a good tutorial (website font is kind of an eyesore, but the content is worth it) on on how Reflection is used to for serialization. The tutorial refers to final fields, but applies to any field.
You'll have to use Reflections getDeclaredField
I'm reviewing some Java code written long ago and not being a Java developer, I have a question. I found the following lines in the body of a class. Someone is creating an instance of SearchQueryParameter however there are curly braces following "new SearchQueryParameter" and it appears that someone overrode some functions here.
My questions are the following.
1) Are these functions overwritten at an instance level?
2) Does this language feature have a name?
public static final SearchQueryParameter X_POSTDOC_WORKFLOW_STEP = new SearchQueryParameter(128,"XPOSTDOCWorkflowStep",AdvancedFields.X_EVENT_POSTDOC_WFSTEP,SearchTypes.XEVENT_DOCUMENTS) {
#Override
protected int getFilterType() {
return SEARCH_FILTER;
}
<<snip>>
};
Thanks, mj
Background:
This is called anonymous class. It is a class that extends a non final class or implements a single interface and you're creating a single instance of this class.
Now, to your questions:
1) Are these functions overwritten at an instance level?
No, they are at level class. You have a new subclass of the desired class and this subclass overrides the method. Then, you create a new instance of the subclass.
2) Does this language feature have a name?
Yes, it is anonymous class.
You probably should have done some research on your own first, but that is called an anonymous inner class.
The code creates an instance of an anonymous class (SearchQueryParameter) and then overrides one method in it.
Essentially, it creates something that extends the SearchQueryParameter class and which overrides the getFilterType() method.
Since only one instance of this particular class definition can ever be created (without reflection), the function may appear like it's being overridden at an instance level but is actually getting overridden at the class level (since it may replace the existing definition).
It's called an anonymous class.
I saw a class "AttributeSelectedClassifier" was once created in the following ways:
AttributeSelectedClassifier classifier = new AttributeSelectedClassifier();
classifier.setClassifier(base);
classifier.setEvaluator(eval);
This above one looks natural to me. But how about the following one.
classifier = new AttributeSelectedClassifier();
((AttributeSelectedClassifier)classifier).setClassifier(base);
((AttributeSelectedClassifier)classifier).setEvaluator(eval);
I think it should be right, but I am not quite sure about the way of of defining classifier as ((AttributeSelectedClassifier)classifier), how to understand this usage?
This means that the classifier variable is declared as a superclass or superinterface of AttributeSelectedClassifier, and that you need to call a method which is not defined in the class or interface, but only on AttributeSelectedClassifier. This notation casts the variable to AttributeSelectedClassifier:
Object classifier = new AttributeSelectedClassifier();
// classifier is a AttributeSelectedClassifier, but references as Object
// to call the following method, we need to cast it to AttributeSelectedClassifier
((AttributeSelectedClassifier)classifier).setClassifier(base);
((AttributeSelectedClassifier)classifier).setEvaluator(eval);
This is usually the sign of a design problem. Either the methods should be in the superclass or interface, or the variable should be declared as AttributeSelectedClassifier.
Look at the below code. Person implements the CanWalk interface. If you assign a Person to CanWalk interface as shown in the main method, which is a common practice, you can only invoke the methods that are specified in the CanWalk interface i.e. walk(). If you want to invoke f(), that isn't declared in the CanWalk interface, then you would use the 2nd mechanism you have specified in your post. i.e. cast it to Person class and then invoke the method.
It is a good practice for the user's of the API (main method here) to use the correct abstraction while working with an object. For e.g. if the client is mainly focused on moving Person's then it should use CanWalk. This way client is not effected by changes to the Person class that are not related to movement. Read this article for more details.
interface CanWalk
{
void walk();
}
class Person implements CanWalk
{
void walk()
{
System.out.println("I am walking");
}
void f()
{
///some arbitrary method
}
}
public stativ void main(String a[])
{
CanWalk cw=new Person();
((Person)cw).f();
}
This:
((AttributeSelectedClassifier)classifier)
isn't "defining" or "declaring" classifier - it's casting it. Presumably in this case classifier is declared as some superclass of AttributeSelectedClassifier. The code isn't particularly clear though. I'd rewrite the second bit of code (assuming you can't change the declaration of classifier) to:
AttributeSelectedClassifier temp = new AttributeSelectedClassifier();
temp.setClassifier(base);
temp.setEvaluator(eval);
classifier = temp;
That way you get to use all the methods of AttributeSelectedClassifier before assigning a value to the less-strongly-typed classifier variable.
(I'd probably use a clearer name than temp, but we don't have enough context to work out what such a name would be.)
By doing ((AttributeSelectedClassifier)classifier) you are casting ("forcing") the classifier object to behave like an instance of AttributeSelectedClassifier.
The classifier variable was probably previously declared as a superclass of AttributeSelectedClassifier.
I can see in couple of examples on the web a new syntax for me, here's an example:
Accumulator<Integer> sum = new Accumulator<Integer>(){
public Integer accumulate(Integer t1, Integer t2) {
return t1+t2;
}
};
In general, what does that mean when one writes { a method } after making an instance of a class? Is it some kind of old syntax for something?
Thanks
You're creating an Anonymous inner class.
new Accumulator<Integer>() {
#Override
public Integer accumulate(Integer t1, Integer t2) {
return t1 + t2;
}
};
Defines an anonymous implementation of Accumulator. You then go on to assign a reference to this anonymous class to sum.
Think of it as a convenient way of simultaneously defining and assigning an implementation. It's a syntactic sugar.
No, this is an anonymous inner class. It has the signature of the interface or class of it's type, but can override public methods.
This is called anonymous inner class, i.e. class that does not have name and therefore may be created together with its only one instance. This is the way to decrease number of visible classes in your project when you need to implement some interface and need only one instance of such implementation.
But do not abuse this feature. Use it only if the implementation is trivial (1-2 lines).
It's an anonymous inner class which is commonly used.
A quote "An anonymous class is essentially a local class without a name."
It is either creating an anonymous subclass with an overloaded method or an anonymous interface implementation (depending on if Accululator is a class or interface).
This is an example of an anonymous class declaration.
Section 15.9.5 of the Java Language Specification discusses these types of declarations.
It's been about 6 years since I've written Java, so please excuse the rust.
I'm working with a library method that requires that I pass it Class objects. Since I'll have to invoke this method a dynamic number of times, each time with a slightly different Class argument, I wanted to pass it an anonymous class.
However, all the documentation/tutorials I've been able to find so far only talk about instantiating anonymous classes, e.g.:
new className(optional argument list){classBody}
new interfaceName(){classBody}
Can I define an anonymous class without instantiating it? Or, perhaps more clearly, can I create a Class object for an anonymous class?
Unfortunately, there's no way you can dodge the instantiation here. You can make it a no-op, however:
foo((new Object() { ... }).getClass());
Of course, this might not be an option if you have to derive from some class that performs some actions in constructor.
EDIT
Your question also says that you want to call foo "each time with a slightly different Class argument". The above won't do it, because there will still be a single anonymous inner class definition, even if you put the new-expression in a loop. So it's not really going to buy you anything compared to named class definition. In particular, if you're trying to do it to capture values of some local variables, the new instance of your anonymous class that foo will create using the Class object passed to it will not have them captured.
short answer
you cannot (using only JDK classes)
long answer
give it a try:
public interface Constant {
int value();
}
public static Class<? extends Constant> classBuilder(final int value) {
return new Constant() {
#Override
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}.getClass();
}
let's creating two new class "parametric" classes:
Class<? extends Constant> oneClass = createConstantClass(1);
Class<? extends Constant> twoClass = createConstantClass(2);
however you cannot instantiate this classes:
Constant one = oneClass.newInstance(); // <--- throws InstantiationException
Constant two = twoClass.newInstance(); // <--- ditto
it will fail at runtime since there is only one instance for every anonymous class.
However you can build dynamic classes at runtime using bytecode manipulation libraries such ASM. Another approach is using dynamic proxies, but this approach as the drawback that you can proxy only interface methods (so you need a Java interface).
You can only reference an anonymous class ONCE. If you do not instantiate it there, you cannot instantiate it since you do not have a name for it.
Hence I believe that anonymous classes can only be used in conjunction with a "new BaseClass()".
In your situation you would pass a BaseClass object to your method doing the work, and instantiate the anonymous object in the source code when you need the object to pass.
You can't access the Class object of an anonymous class without instatiating it. However, if you only need access to the class, you could define local classes within your method and refer to these using the ClassName.class literal syntax.
You can assume the name of an anonymous class and call Class.forName("mypackage.MyBaseClass$1") to get a handle to an anonymous class. This will give you the first anonymous class defined in your MyBaseClass, so this is a rather fragile way to refer to a class.
I suspect whatever you are trying to do could be done a better way. What are you really trying to achieve? Perhaps we can suggest a way which doesn't require you to pass a Class this way.
You can access the class object of an anonymous class by calling .getClass() on it immediately after creation. But what good would that do?
I think the key is in this part of what you said:
I'm working with a library method that requires that I pass it Class
objects.
Why does it want you to pass it Class objects? What does this library do with the Class objects you pass it? Instantiate objects? But if so, what constructor does it use and how does it decide what arguments to pass? I don't know what library you are using or what it does, but I would guess that it always creates objects using the no-argument constructor. However, that will not work for anonymous classes anyway, since they have no public constructor (and in any case, to instantiate any non-static inner class, a reference to the outer instance must be provided, so there is no no-argument constructor).