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
Related
This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 8 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
The very common beginner mistake is when you try to use a class property "statically" without making an instance of that class. It leaves you with the mentioned error message:
You can either make the non static method static or make an instance of that class to use its properties.
What the reason behind this? Am not concern with the solution, rather the reason.
private java.util.List<String> someMethod(){
/* Some Code */
return someList;
}
public static void main(String[] strArgs){
// The following statement causes the error.
java.util.List<String> someList = someMethod();
}
You can't call something that doesn't exist. Since you haven't created an object, the non-static method doesn't exist yet. A static method (by definition) always exists.
The method you are trying to call is an instance-level method; you do not have an instance.
static methods belong to the class, non-static methods belong to instances of the class.
The essence of object oriented programming is encapsulating logic together with the data it operates on.
Instance methods are the logic, instance fields are the data. Together, they form an object.
public class Foo
{
private String foo;
public Foo(String foo){ this.foo = foo; }
public getFoo(){ return this.foo; }
public static void main(String[] args){
System.out.println( getFoo() );
}
}
What could possibly be the result of running the above program?
Without an object, there is no instance data, and while the instance methods exist as part of the class definition, they need an object instance to provide data for them.
In theory, an instance method that does not access any instance data could work in a static context, but then there isn't really any reason for it to be an instance method. It's a language design decision to allow it anyway rather than making up an extra rule to forbid it.
I just realized, I think people shouldn't be exposed to the concept of "static" very early.
Static methods should probably be the exception rather than the norm. Especially early on anyways if you want to learn OOP. (Why start with an exception to the rule?) That's very counter-pedagogical of Java, that the "first" thing you should learn is the public static void main thing. (Few real Java applications have their own main methods anyways.)
I think it is worth pointing out that by the rules of the Java language the Java compiler inserts the equivalent of "this." when it notices that you're accessing instance methods or instance fields without an explicit instance. Of course, the compiler knows that it can only do this from within an instance method, which has a "this" variable, as static methods don't.
Which means that when you're in an instance method the following are equivalent:
instanceMethod();
this.instanceMethod();
and these are also equivalent:
... = instanceField;
... = this.instanceField;
The compiler is effectively inserting the "this." when you don't supply a specific instance.
This (pun intended) bit of "magic help" by the compiler can confuse novices: it means that instance calls and static calls sometimes appear to have the same syntax while in reality are calls of different types and underlying mechanisms.
The instance method call is sometimes referred to as a method invocation or dispatch because of the behaviors of virtual methods supporting polymorphism; dispatching behavior happens regardless of whether you wrote an explicit object instance to use or the compiler inserted a "this.".
The static method call mechanism is simpler, like a function call in a non-OOP language.
Personally, I think the error message is misleading, it could read "non-static method cannot be referenced from a static context without specifying an explicit object instance".
What the compiler is complaining about is that it cannot simply insert the standard "this." as it does within instance methods, because this code is within a static method; however, maybe the author merely forgot to supply the instance of interest for this invocation — say, an instance possibly supplied to the static method as parameter, or created within this static method.
In short, you most certainly can call instance methods from within a static method, you just need to have and specify an explicit instance object for the invocation.
The answers so far describe why, but here is a something else you might want to consider:
You can can call a method from an instantiable class by appending a method call to its constructor,
Object instance = new Constuctor().methodCall();
or
primitive name = new Constuctor().methodCall();
This is useful it you only wish to use a method of an instantiable class once within a single scope. If you are calling multiple methods from an instantiable class within a single scope, definitely create a referable instance.
If we try to access an instance method from a static context , the compiler has no way to guess which instance method ( variable for which object ), you are referring to. Though, you can always access it using an object reference.
A static method relates an action to a type of object, whereas the non static method relates an action to an instance of that type of object. Typically it is a method that does something with relation to the instance.
Ex:
class Car might have a wash method, which would indicate washing a particular car, whereas a static method would apply to the type car.
if a method is not static, that "tells" the compiler that the method requires access to instance-level data in the class, (like a non-static field). This data would not be available unless an instance of the class has been created. So the compiler throws an error if you try to call the method from a static method.. If in fact the method does NOT reference any non-static member of the class, make the method static.
In Resharper, for example, just creating a non-static method that does NOT reference any static member of the class generates a warning message "This method can be made static"
The compiler actually adds an argument to non-static methods. It adds a this pointer/reference. This is also the reason why a static method can not use this, because there is no object.
So you are asking for a very core reason?
Well, since you are developing in Java, the compiler generates an object code that the Java Virtual Machine can interpret. The JVM anyway is a binary program that run in machine language (probably the JVM’s version specific for your operating system and hardware was previously compiled by another programming language like C in order to get a machine code that can run in your processor). At the end, any code is translated to machine code. So, create an object (an instance of a class) is equivalent to reserve a memory space (memory registers that will be processor registers when the CPU scheduler of the operating system put your program at the top of the queue in order to execute it) to have a data storage place that can be able to read and write data. If you don’t have an instance of a class (which happens on a static context), then you don’t have that memory space to read or write the data. In fact, like other people had said, the data don’t exist (because from the begin you never had written neither had reserved the memory space to store it).
Sorry for my english! I'm latin!
The simple reason behind this is that Static data members of parent class
can be accessed (only if they are not overridden) but for instance(non-static)
data members or methods we need their reference and so they can only be
called through an object.
A non-static method is dependent on the object. It is recognized by the program once the object is created.
Static methods can be called even before the creation of an object. Static methods are great for doing comparisons or operations that aren't dependent on the actual objects you plan to work with.
When lambda expression is used Java actually creates an anonymous (non-static) class. Non-static inner classes always contain references their enclosing objects.
When this lambda expression is called from another library that may invoke lambda in a different process that invocation crashes with class not found exception because it cannot find enclosing object's class in another process.
Consider this example:
public class MyClass {
public void doSomething() {
remoteLambdaExecutor.executeLambda(value -> value.equals("test"));
}
}
Java will create an anonymous inner class that implements certain functional interface and pass it as a parameter to executeLambda(). Then remoteLambdaExecutor will take that anonymous class across the process to run remotely.
Remote process knows nothing about MyClass and will throw
java.lang.ClassNotFoundException: MyClass
Because it needs MyClass for that enclosing object reference.
I can always use a static implementation of the functional interface expected by an API, but that defeats the purpose and doesn't utilize lambda functionality.
Is there way to solve it using lambda expressions?
UPDATE: I cannot use static class either unless it's somehow exported to that other process.
Your initial premise is wrong. The JRE will not generate an anonymous inner class. It may generate a class, but if your lambda expression does not access this or a non-static member of the class, it will not keep a reference to the this instance.
However, this does not imply that the class itself is unnecessary. Since the class hosts the code of the lambda expression, it will always be needed. In this regard, your solution of using a static nested class doesn’t change anything about it, as then, it’s the static nested class that is needed for the execution of the code.
There is no way to transfer an object to a remote execution facility without transferring the class that contains the code to execute (unless the class already exists at the remote site).
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());
}
};
}
}
I am looking at a codebase and I often see something like:
public class SomeClass
{
protected static SomeClass myObject;
//...
public static SomeClass getObject()
{
return myOjbect
}
}
I'd like to make sure I understand the purpose behind this. Is it to ensure one instance of the class gets shared even if it is instantiated multiple times? I am not sure about the vocabulary here, or else I'd search for the answer, so if this pattern has a name, please let me know.
Also, this seems a little chicken-and-egg definition because the class includes an object of the type of the class. Why isn't this actually paradoxical?
Thanks!
This is really only common with the Singleton Pattern where there is only this one instance of the class. While it has its uses, Singleton is over- and misused more often than not (usually to disguise procedural programming as OO). It also occurs very often in example code for Java AWT or Swing, where you typically subclass Frame / JFrame, and create an instance in a main method inside the same class.
Also, this seems a little
chicken-and-egg definition because the
class includes an object of the type
of the class. Why isn't this actually
paradoxical?
Why do you think it is? The class mainly describes what members instances of this type have - but a static member does not belong to an instance, it belongs to the class itself, so it doesn't have anything to do with the "blueprint" role of the class. Static members are really somewhat un-OO because of that.
But even on the instance level you can have references of the same type. For example, an entry in a linked list would typically have two references to the next and previous entries, which are of the same class.
This is called the Singleton design pattern.
You are correct in stating that the purpose is to ensure only one instance of the class gets created.
Wikipedia has a preyty good article on the pattern.
The pattern you mentioned is called "Singleton", but from your code sample it is not clear if this is really what is intended. Due to the fact that the member is protected, I would guess not - if there are subclasses, then there would probably not be a single instance.
It's called Singleton. You ensure the creation of just ONE (1) object of a given class.
You should add a private Constructor, so the only one who create the object is the class.
public class SomeClass
{
// Using private constructor
protected static SomeClass myObject = new SomeClass();
private SomeClass(){
//...
}
public static SomeClass getObject()
{
return myOjbect
}
}
Much much more here, in Wikipedia
You may want to take a look to Factory Pattern
It's not all that uncommon; it can be a good way to implement the Singleton pattern. There can be other uses as well - sometimes you will want a handful - and no more - of objects of a given class; that class is a good place to hang onto them. In the event that you don't want other classes to be able to create objects of this class, it is common to give the class a private constructor as well.
It's not paradoxical, because the compiler can be aware of a reference to the class before it has fully compiled the class. Later - if you like to think of it this way - it can "fill in the blanks".
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).