Is reference to an instance method serializable in Java 8? - java-8

I want to know if reference to an instance method of an arbitrary object of a particular type is serializable or not?
Example:
public class MyClass {
public void foo() {
System.out.println("Serializable");
}
}
SerializableConsumer
#FunctionalInterface
public interface SerializableConsumer<T> extends Consumer<T>, Serializable {
}
and field is:
SerializableConsumer<MyClass> serializableMethod = MyClass::foo;
EDITED

Assuming that SerializableFunction refers to a type that extends Serializable, the method reference will be serializable. There is nothing special about the particular type of method reference your are asking for.
Most notably, the “reference to an instance method of an arbitrary object” is not capturing any instance of MyClass, hence, the fact that MyClass isn’t Serializable is not important. It would be different if you were referring to an instance method of a particular instance like object::foo, as in that case, the object had to be serialized as well, which will fail at runtime, if its class doesn’t implement Serializable.
What will not work, is to refer to a void method as a Function of return type Void. I don’t know how your SerializableFunction<MyClass, Void> is defined, but if it is equivalent to Function<MyClass, Void>&Serializable, it will not work.
When you have an appropriate functional interface, serializing the method reference is no problem:
import java.io.*;
import java.util.function.Consumer;
public class MyClass {
public void foo() {
System.out.println("Serializable");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Consumer<MyClass> consumer = (Consumer<MyClass>&Serializable)MyClass::foo;
byte[] serialized;
try(ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(consumer);
oos.flush();
serialized=baos.toByteArray();
}
Consumer<MyClass> deserialized;
try(ByteArrayInputStream bais=new ByteArrayInputStream(serialized);
ObjectInputStream ois=new ObjectInputStream(bais)) {
deserialized = (Consumer<MyClass>)ois.readObject();
}
deserialized.accept(new MyClass());
}
}
As said, references to a specific instance have to serialize the target instance, hence, depend on the serializability of that instance so
import java.io.*;
import java.util.function.Consumer;
public class MyClass {
public void foo() {
System.out.println("Serializable");
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Runnable runnable = (Runnable&Serializable)new MyClass()::foo;
byte[] serialized;
try(ByteArrayOutputStream baos=new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(runnable);
oos.flush();
serialized=baos.toByteArray();
}
Runnable deserialized;
try(ByteArrayInputStream bais=new ByteArrayInputStream(serialized);
ObjectInputStream ois=new ObjectInputStream(bais)) {
deserialized = (Runnable)ois.readObject();
}
deserialized.run();
}
}
will fail at runtime with a java.io.NotSerializableException: MyClass, unless you change MyClass to implement Serializable.

I know you can serialize a lambda expresion (as you can see here)
Now, what you want to do is only serialize a the variable by itself? or the method?... I don't know why, but I don't think you can. Maybe you can go for other way, like creates a lambda and serialize it, like in the post above:
Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");

Related

What does ContainingType mean in java method reference

In Java Method References
ContainingClass::staticMethodName - means that a class can refer the static method (Reference to a Static Method )
containingObject::instanceMethodName - means that a class object is created first and then that object is used to refer the instanceMethod .
My doubt is
ContainingType::methodName - what does the ContainingType mean ?
Is ContainingType a predefined class in java like String or something else ?
Java Language Specification, §4.3. Reference Types and Values:
There are four kinds of reference types: class types (§8.1), interface types (§9.1), type variables (§4.4), and array types (§10.1).
Array type don't have static methods, so that doesn't apply to static method reference, but you can do the other 3:
class MyClass {
static void doIt() {/*doing it*/}
}
interface MyInterface {
static void doIt() {/*doing it*/}
}
class Test<T extends MyClass> {
void test() {
Runnable m1 = MyClass::doIt; // class type
Runnable m2 = MyInterface::doIt; // interface type
Runnable m3 = T::doIt; // type variable
}
}
Now that link is provided in a comment, it says:
Reference to a static method
ContainingClass::staticMethodName
Reference to an instance method of a particular object
containingObject::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type
ContainingType::methodName
Reference to a constructor
ClassName::new
Here, again, ContainingType refers to any of the 3 reference types mentioned above: Class, Interface, and Type Variable.
You can then make a method reference for any instance method of such a type.
class MyClass {
void doIt() {/*doing it*/}
}
interface MyInterface {
void doIt();
}
class Test<T extends MyClass> {
void test() {
Consumer<MyClass> m1 = MyClass::doIt;
Consumer<MyInterface> m2 = MyInterface::doIt;
Consumer<T> m3 = T::doIt;
}
}
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
In the document you gave,there is a example of the ContainingType:
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);
and explains:
The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).
I think,the element of the stringArray dosen't have a name (eg: String s1 = "Barbara"),so you can't refer it by containingObject::instanceMethodName(eg:s1::compareToIgnoreCase). That's why it uses ContainingType.
I think your ContainingType::methodName is a general/common form of the 2 forms above...
Think about the below code. You can replace the <methodReference> width
InterfaceA::method (for ContainingType::methodName)
ClassA::method (for also ContainingType::methodName)
ClassB::instanceMethod (for ContainingObject::instanceMethodName) or
ClassB::staticMethod (for ContainingClass::staticMethodName)
to demonstrate the mentioned cases:
public class App {
interface InterfaceA {
String method();
}
static class ClassA implements InterfaceA {
public String method() {
return "ContainingType::methodName";
}
}
static class ClassB extends ClassA {
public String instanceMethod() {
return "ContainingObject::instanceMethodName";
}
public static String staticMethod(ClassB classB) {
return "ContainingClass::staticMethodName";
}
}
public static void main(String[] args) {
System.out.println(((Function<ClassB, String>) <methodReference>).apply(new ClassB()));
}
}

JNA : Error when to call natives functions with pointer to struture as parameters

I tested this int EMV_Init(EMV_PARAMS *params, EMV_HANDLE *hEMV) in C, it works well.
Now i want to call it in my java application by means of jna. This function is in a native library under windows (dll file).
EMV_PARAMS is a structure
typedef struct
{
HAL_UI_HANDLE ui;
HAL_SCR_HANDLE card;
HAL_PROPERTY_HANDLE property;
HAL_DATE_HANDLE date;
HAL_CRYPTO_HANDLE crypto;
HAL_CHV_HANDLE chv;
} EMV_PARAMS;
Note that all attributes in EMV_PARAMS is is an opaque structure like this typedef void * HAL_UI_HANDLE;
EMV_HANDLE is also an opaque structure : typedef void *EMV_HANDLE;
I need your help to fix the following error:
Exception in thread "main" java.lang.NullPointerException at
com.sun.jna.Structure.getFields(Structure.java:895)
at com.sun.jna.Structure.deriveLayout(Structure.java:1042)
at com.sun.jna.Structure.calculateSize(Structure.java:966)
at com.sun.jna.Structure.calculateSize(Structure.java:933)
at com.sun.jna.Structure.allocateMemory(Structure.java:360)
at com.sun.jna.Structure.<init>(Structure.java:184)
at com.sun.jna.Structure.<init>(Structure.java:172)
at com.sun.jna.Structure.<init>(Structure.java:159)
at com.sun.jna.Structure.<init>(Structure.java:151)
I created a Java interface named "CInterface" which contains "EMV_PARAMS" class.
public interface CInterface extends Library
{
CInterface INSTANCE = (CInterface) Native.loadLibrary("path to dll", CInterface.class);
public int EMVCT_Init(EMV_PARAMS.ByReference params, Pointer hEMV);
public static class PARAMS extends Structure
{
public static class ByReference extends PARAMS implements Structure.ByReference {}
Pointer ui;
Pointer card;
Pointer property;
Pointer date;
Pointer crypto;
Pointer chv;
#Override
protected List getFieldOrder() {
// TODO Auto-generated method stub
return null;
}
}
}
java test class
public static void main(String[] args)
{
CInterface.EMV_PARAMS.ByReference emv_param = new
CInterface.EMV_PARAMS.ByReference();
int test= 0;
Pointer hEMV = null;
test=CInterfaceEMV.INSTANCE.EMVCT_Init(emv_param, hEMV);
System.out.println("test="+test);
}
Thank you for your attention
Your structure fields must be public, and you need to implement getFieldOrder().

How to call private method by other methods?

I am confused of calling a private method by another method(public) belonging to the same class.Once I have been told I gotta create an object of that class and then call the private method via this object but in one of my questions in this forum I have been told that I dont need to use object.
public class Train() {
private void method1{......method definition..... }
public void method2{......how to invoke method1??}
}
Can I simply call the first method inside the second method by using method1(); or should I invoke it by creating an object of the class and Object_of_Train.method1();.
Which one should I use?
Within the class you should be able to call method1();
Outside the class you will need to call it from an instance of that class and will have access to public methods only
Use this.method1(); to call from method2() or any other non-static method in the class.
You can access the private methods of a class using java reflection package.
**Step1 − Instantiate the Method class of the java.lang.reflect package by passing the method name of the method which is declared private.
Step2 − Set the method accessible by passing value true to the setAccessible() method.
Step3 − Finally, invoke the method using the invoke() method.**
Example
import java.lang.reflect.Method;
public class DemoTest {
private void sampleMethod() {
System.out.println("hello");
}
}
public class SampleTest {
public static void main(String args[]) throws Exception {
Class c = Class.forName("DemoTest");
Object obj = c.newInstance();
Method method = c.getDeclaredMethod("sampleMethod", null);
method.setAccessible(true);
method.invoke(obj, null);
}
}
Source : Tutorialpoint

Spring: How to inject a value to static field?

With this class
#Component
public class Sample {
#Value("${my.name}")
public static String name;
}
If I try Sample.name, it is always 'null'. So I tried this.
public class Sample {
public static String name;
#PostConstruct
public void init(){
name = privateName;
}
#Value("${my.name}")
private String privateName;
public String getPrivateName() {
return privateName;
}
public void setPrivateName(String privateName) {
this.privateName = privateName;
}
}
This code works. Sample.name is set properly. Is this good way or not? If not, is there something more good way? And how to do it?
First of all, public static non-final fields are evil. Spring does not allow injecting to such fields for a reason.
Your workaround is valid, you don't even need getter/setter, private field is enough. On the other hand try this:
#Value("${my.name}")
public void setPrivateName(String privateName) {
Sample.name = privateName;
}
(works with #Autowired/#Resource). But to give you some constructive advice: Create a second class with private field and getter instead of public static field.
Soruce of this info is this: https://www.baeldung.com/spring-inject-static-field
Spring uses dependency injection to populate the specific value when it finds the #Value annotation. However, instead of handing the value to the instance variable, it's handed to the implicit setter instead. This setter then handles the population of our NAME_STATIC value.
#RestController
//or if you want to declare some specific use of the properties file then use
//#Configuration
//#PropertySource({"classpath:application-${youeEnvironment}.properties"})
public class PropertyController {
#Value("${name}")//not necessary
private String name;//not necessary
private static String NAME_STATIC;
#Value("${name}")
public void setNameStatic(String name){
PropertyController.NAME_STATIC = name;
}
}
This is my sample code for load static variable
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class OnelinkConfig {
public static int MODULE_CODE;
public static int DEFAULT_PAGE;
public static int DEFAULT_SIZE;
#Autowired
public void loadOnelinkConfig(#Value("${onelink.config.exception.module.code}") int code,
#Value("${onelink.config.default.page}") int page, #Value("${onelink.config.default.size}") int size) {
MODULE_CODE = code;
DEFAULT_PAGE = page;
DEFAULT_SIZE = size;
}
}
For those who want to use ApplicationContext in the main class of a Spring Boot application, you can just use the return value of SpringApplication.run.
Although workarounds may need to be implemented, one should try to avoid them in most scenarios if possible. Spring is great at handling dependency injection and treats most objects as Singletons. This means that Spring can handle the creation of objects for you, and the injection of these objects at runtime. When combining this with the fact that your Spring managed bean is likely a Singleton, the use of static methods and variables is largely unnecessary. You can simply autowire in an instance of the object you are looking for at the constructor level or variable level and reference the non-static version of the method or variable. This is ideal and behaves similarly to a static reference. Non static variables are basically static because you are only ever using one instance of the object in every part of the code and because of dependency injection you are never handling the instantiation of the object, just like with a static reference! Great! Now I'm sure there are instances where you need the work around (i.e. you aren't using dependency injection or class is not a singleton), but try to not use workarounds if possible. Also this is just my 2 cents. Someone may be able to offer 3. (:
public class InjectableClass{
#Value("${my.value}")
private String myString;
public String nonStaticMethod(){
return myString;
}
}
public class LogicClass{
private InjectableClass injectableClass;
#Autowire
public LogicClass(InjectableClass injectableClass){
this.injectableClass = injectableClass;
}
public void logicClassMethod(){
System.out.println("Hey! Here is the value I set on myString: " +
injectableClass.nonStaticMethod() + ". That was
basically like using a static method!");
}
}

Gson.toJson() and inheriting from a generic class

I have the following class:
public static class TestSomething {
Integer test;
public TestSomething(Integer test) {
this.test = test;
}
// getter and setter for test
}
Ok, now create a collection of this class and serialize it with Gson:
Collection<TestSomething> tests = Arrays.asList(
new TestSomething(1),
new TestSomething(2),
new TestSomething(3)
);
String json = new Gson().toJson(tests, new TypeToken<Collection<TestSomething>>() {}.getType());
After this, the String json is set to
[{"test":1},{"test":2},{"test":3}]
Which is great.
But now, all of my model classes inherit from a generic type Identifiable<T> which provides just two methods T getId() and void setId(T). So I change the TestSomething-class from above to
public static class TestSomething extends Identifiable<Long> {
// same as above
}
When I try to put this through Gson.toJson(), Gson ends up with the following Exception:
java.lang.UnsupportedOperationException: Expecting parameterized type, got class path.to.TestSomething.
Are you missing the use of TypeToken idiom?
See http://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener
at com.google.gson.TypeInfoFactory.getActualType(TypeInfoFactory.java:97)
...
So, what do I have to do to get this work?
I don't know the answer, but I know that generic type resolution is a tricky thing to get right: specifically full type resolution from interface with type parameter T up through to generic parameter declaration (T=Long). In these cases it is not enough to check for Method object's parameters but also resolve generic type parameters. This is most likely what causes issues; it may be a bug in Gson.
Since you are serializing things, perhaps you could just omit any type declarations? Although your TypeToken is correct for the use case, maybe it confuses Gson.
But just in case you could not make Gson work with this, I know that of other JSON libraries Jackson can handle such cases correctly.
Perhaps this issue was resolved in one of the Gson releases newer than what the original questioner was using, because the example in the original question now serializes as expected.
// output:
// [{"test":1},{"test":2},{"test":3}]
import java.util.Arrays;
import java.util.Collection;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args)
{
Collection<TestSomething> tests = Arrays.asList(
new TestSomething(1),
new TestSomething(2),
new TestSomething(3));
String json = new Gson().toJson(tests, new TypeToken<Collection<TestSomething>>() {}.getType());
System.out.println(json);
}
}
class TestSomething extends Identifiable<Long>
{
Integer test;
public TestSomething(Integer test)
{
this.test = test;
}
#Override
Long getId()
{
return new Long(test);
}
#Override
void setId(Long t)
{
this.test = (int)(t.longValue());
}
}
abstract class Identifiable<T>
{
abstract T getId();
abstract void setId(T t);
}

Resources