Service Loader implementations needing default public constructors
constructor, externalizable, java, static
Solution
That's because it's required to create a new instance via reflection.
I guess here's relevant code, line 362:
S p = service.cast(Class.forName(cn, true, loader).newInstance());
Thus it invokes "parameterless" constructor since `Class.newInstance()` can only invoke the zero-argument constructor.
Edit:
Actually, it's not required to create a zero-argument constructor for `public class` unless you define another constructor.
javadoc:
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors.
So, the following code is perfectly correct:
public final class MyServiceImpl implements MyService {
@Override
public long getTime() {
return System.currentTimeMillis();
}
}
Default constructor for `MyServiceImpl` will be the same as:
public MyServiceImpl() { }
Since `MyServiceImpl` is a public class:
if the class is declared public, then the default constructor is implicitly given the access modifier public
Thus constructor in `MyServiceImpl` is redundant.
My guess is that author of the blog post just wanted to make sure that `ServiceLoader` will be able to instantiate service provider even when it contains some explicit constructors with arguments.
Conclusion: Service provider should have explicit no-argument constructor only if it contains explicit constructors with arguments. Default constructor will suffice otherwise.
Problem
I was trying to understand how in Java Service Loader works? I came across this blog: Could you please help me understand why the author claims: The implementation must have a public parameterless constructor. Okay I get the first part. Now a follow up question. I can post it as a follow up a question but thought it would be better to have it as part of the same question. Consider the java doc: It says: In addition, the constructor of a non-private inner member class must be compiled such that it has as its first parameter, an additional implicit parameter representing the immediately enclosing instance (§8.1.3). So does that mean I cannot externalize a inner class. Please consider the following code: ``` import java.io.*; class Y { class ABC { ABC() { System.out.println("ABC Constructor"); } public void writeExternal(ObjectOutput out) throws IOException { System.out.println("ABC.writeExternal"); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("ABC.readExternal"); } } public void foo() throws IOException, ClassNotFoundException { System.out.println("Constructing objects:"); ABC abc = new ABC(); ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("InnerClass.out")); System.out.println("Saving objects:"); o.writeObject(abc); o.close(); // Now get them back: ObjectInputStream in = new ObjectInputStream( new FileInputStream("InnerClass.out")); System.out.println("Recovering abc:"); // OOPS! Throws an exception: abc = (ABC)in.readObject(); } } public class InnerClass { public static void main(String[] args) throws IOException, ClassNotFoundException { System.out.println("Hello World\n"); Y y = new Y(); System.out.println(y); y.foo(); } } ``` It fails at runtime: ``` Hello World Y@6bc7c054 Constructing objects: ABC Constructor Saving objects: Exception in thread "main" java.io.NotSerializableException: Y$ABC at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346) at Y.foo(InnerClass.java:24) at InnerClass.main(InnerClass.java:40) ``` How can I use Externalize class ABC? Thanks