Inlining implementation of an interface - java

Is there a way to inline implementation of an interface without having its default constructor? To understand my question better, Lets say I have an interface MyInterface and one implementation of it called MyImplementation.
public interface MyInterface
{
void myFunction();
}
public MyImplementation implements MyInterface
{
private final String someString;
public MyImplementation(String someString)
{
this.someString = someString;
}
public void myFunction()
{
// do something.
}
}
Is there a way to inline MyImplementation? If I didn't have to pass someString to constructor of implementation I could just say -
MyInterface myInterface = new MyInterface() {
public void myFunction()
{
// do something
}
};

If your question is how to make an anonymous class that references objects that you set up in the constructor, you could "inline" an implementation by making an anonymous class and reference final local variables defined in the same method, like this:
private final String someString = ...; // That's the string that you used to init in the constructor; init it here
MyInterface myInterface = new MyInterface() { // That's the code that you wanted to have
public void myFunction()
{
System.out.println(someString); // This is allowed, because someString is final
}
};
Behind the scene, Java compiler would generate a class that looks very much like your MyImplementation class, make a constructor that looks like your MyImplementation constructor, and pass someString to it.

Anonymous classes are the "old" way to do this. The new way in Java 8, for an interface with exactly one method, is to use lambda expressions.
For instance, let's say you wanted to print someString. Old way:
MyInterface o = new MyInterface() {
#Override
public void myFunction() {
System.out.println(someString);
}
};
new way:
MyInterface o = () -> System.out.println(someString);
You don't even need to make someString final with lambdas! It's good enough that it's "effectively final," which basically means that it could have been marked final and still compiled.

Related

Is this interface being instantiated? (Java 8)

As far as I know, interfaces cannot be instantiated directly. However, whenever I compile the following code:
interface A {};
public class Test {
public static void main(String[] args){
A a = new A() {};
system.out.println(a);
it outputs the toString() of an object of class Test:
Test$16d06d69c
And when I change
A a = new A() {};
to
A a = new A();
it doesn't compile. Why is this happening? Is the interface being instantiated, or is something else happening behind the scenes?
You are defining a new anonymous inline class that implements interface A with the statement:
A a = new A() {};
And in the same statement you are constructing a new instance of your new anonymous class definition.
So no you are not instantiating an interface.
Just to expound on #bhspencer's answer in the case when A has defined methods:
An interface has no constructor and cannot be instantiated directly. it can however be implemented inline. Consider the following implementation of A:
public class B implements A {
#Override
public void printMyName() {
System.out.println("B");
}
}
And code that instantiates an instance of B:
public A a = new B();
This is equivalent syntax to an anonymous inline implementation of interface A that reads as follows:
public A a = new A() {
#Override
public void printMyName() {
System.out.println("B");
}
}
Java allows us to implement interfaces inline and instantiate them without creating an explicit separate class.

Java: share object reference without passing as parameter

I have an ObjectFactory and a specialized case of implementation of that factory. I can't change the interface, that has 0 argument.
In one of the implementation I have to read a file and load some data. To pass the filename I can use the system properties because all I need to share is a string.
But in the other implementation I must start not from a file but from a memory structure. How can I do to pass the object (then I think the object reference) to the factory? Other methods? No way I serialize the object on a file and after I read it again because what I want to avoid is right the I/O footprint.
Thanks
OK, more informations:
This is the interface and the abstract factory I have to implement
public abstract interface A
{
public abstract Set<Foo> getFoo();
public abstract Set<Bar> getBar();
}
//this is otherpackage.AFactory
public abstract class AFactory
{
public static AccessFactory newInstance()
{
return a new built instance of the factory
}
public abstract A newA();
}
This is my implementation with my problem:
public class AFactory extends otherpackage.AFactory
{
#Override
public Access newA()
{
return new AA();
}
}
public class AA implements A
{
protected AA()
{
this.objectReferenceIWantToSaveHere = I retrieve from the shared memory zone;
use the object
}
}
Now I'd like to do something like this:
B b = something I built before
save b in a shared memory zone or something like that
otherpackage.AFactory f = mypackage.AccessFactory.newInstance();
A a = f.newA();
And inside the f.newA() call I'd like to access to the b object
Can't you simply use a constructor?
interface ObjectFactory { Object create(); }
class SpecialFactory implements ObjectFactory {
private final Object data;
public SpecialFactory(Object data) { this.data = data; }
#Override public Object create() { return somethingThatUsesData; }
}
Ass assylias proposes, you can pass the reference to the constructor. Or if you know where to find the reference, you could just ask for it before you use it? E.g. data = dataBank.giveMeTheData()
Agree it would help to get some more context around what you are doing... but could you use a shared static class in which your calling code places info into the static class, and your interface implementation references this same static class to obtain either the object and/or instructions?
So here's a client class. It has the entry point..and wants to pass an object to the interface implementer but it can't pass it directly...So it set's object it wants to pass in the MyStaticHelper.SetSharedObject method.
public class Client {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String mySharedObject = "Couldbeanyobject, not just string";
// Set your shared object in static class
MyStaticHelper.SetSharedObject(mySharedObject);
InterferfaceImplementer myInterfaceImplementer = new InterferfaceImplementer();
//
myInterfaceImplementer.RunMyMethod();
}
Here is the code for the static helper...
public class MyStaticHelper {
private static Object _insructionsObject;
public static void SetSharedObject(Object anObject)
{
_insructionsObject = anObject;
}
public static Object GetSharedObject()
{
return _insructionsObject;
}
}
and finally the the class that you call that uses the static helper to get the same object.
public class InterferfaceImplementer {
// no objects
public void RunMyMethod()
{
System.out.println(MyStaticHelper.GetSharedObject());
}
}
Again this works in a very simple scenario and wouldn't stand up if more than one implementer needs to be called simultaneously as this solution would only allow one obj to be in the static helper class.

Call method not defined in interface from implemented interface in Java

I have the following scenario in Java. Let's say I have an interface, and two classes that implement this interface. As follows:
public interface myInterface {
public String printStuff();
}
public class A implements myInterface {
#Override
public String printStuff(){
return "Stuff";
}
}
public class B implements myInterface {
#Override
public String printStuff(){
return "Stuff";
}
public String printOtherStuff(){
return "Other Stuff";
}
}
How do I call the printOtherStuff method above if I define it as follows:
public static void main(String... args) {
myInterface myinterface = new B();
String str = myinterface.printOtherStuff(); // ? This does not work
}
The above calling code does not seem work. Any ideas?
myInterface myinterface = new B();
The reference type of myinterface is myInterface. That means you can only access the methods defined in the interface. You can cast it to type B in order to make the method call.
NOTE: From here on out I'll be using the proper naming conventions.
Example
MyInterface myInterface = new B();
String str = ((B)myInterface).printOtherStuff();
Just a note on this
If you need to do this, then you need to have a look at your class design. The idea of using an interface in this way is to abstract away from the details of the object's concrete implementation. If you're having to perform an explicit cast like this, then you might want to look into either changing your interface to accommodate the necessary methods, or change your class so that the method is moved into a global location (like a util file or something).
Extra Reading
You should read about reference types here, and you should have a look at casting here. My answer is a combination of the understanding of both of these things.
As an added note, take a look at the Java Naming Conventions. This is a vital piece of information for any Java developer to make understandable code.
Surely this wouldn't work because you have reference type of Interface MyInterface. At the time of method binding compiler would try to find this method in your Interface MyInterface which is not available. So you need to cast it to your class like this.
MyInterface myInterface = new B();
B newB=(B) myInterface ;//casting to class
newB.printOtherStuff();// would work fine
change myInterface
public interface myInterface {
public String printStuff();
public String printOtherStuff();
}
If you cant change myInterface, then extends myInterface
public interface myOtherInterface extends myInterface {
public String printOtherStuff();
}
Then Implements myOtherInterface
public class B implements myOtherInterface {
#Override
public String printStuff(){
return "Stuff";
}
#Override
public String printOtherStuff(){
return "Other Stuff";
}
}
public static void main(String... args) {
myOtherInterface myotherinterface = new B();
String str = myotherinterface.printOtherStuff();
}

Guice: injecting a parameter used in implementation of abstract method

Here is an example of the issue I've come across:
public interface IFoo { ... }
public abstract class Helper implements IFoo {
public Helper() { ... }
protected abstract X helperMethod();
}
public class Foo extends Helper {
private final String aaa;
#Inject
public Foo(String aaa) { this.aaa = aaa; }
#Override
X helperMethod() { doSomethingUsingWhatsInjected(aaa); }
}
The issue is that when I bind IFoo to Foo like this:
bind(IFoo.class).to(Foo.class).in(Singleton.class);
it appears like helperMethod() is being called before the aaa has been Injected since I'm seeing aaa as null. But if I instead don't use the class Helper and in-line all of its code directly in Foo, guice doesn't struggle.
What's the difference between these two approaches? Why is helperMethod() called before we know from where we're getting the implementation of IFoo? Can we use Helper along with injection?
Are you sure you're not calling helperMethod from within Helper's constructor? You omitted that part from the code you posted, but it would match the behavior you're seeing.
public class Test {
interface IFoo { }
static abstract class Helper implements IFoo {
Helper() { helperMethod(); }
abstract void helperMethod();
}
static class Foo extends Helper {
private final String aaa;
Foo(String aaa) { this.aaa = aaa; }
#Override
void helperMethod() { System.out.println(String.valueOf(aaa)); }
}
public static void main(String[] args) {
// Call helperMethod twice:
// once in the Helper.Helper(), once right here.
new Foo("expected").helperMethod();
// output:
// null
// expected
}
}
The first thing Foo does is implicitly call its superclass constructor, as if you typed super(); this necessarily happens as the very first statement in the subclass constructor. Consequently, this happens even before final variables like aaa are set, so your overridden method in Foo sees aaa as null. As in my example, this is not specific to Guice, but Guice injection can trigger the constructor just like anything else can.
This StackOverflow answer offers a more thorough discussion of this problem.

Replace/override method of an object which is an implementation of an interface in Java

I have an interface which has only one method. I have a static function which receives objects (these objects implement the interface), and I want to override/replace implementation of the method, that is defined in the interface, in objects. What is the best way to do this in Java
public class MyClass {
public interface MyInterface {
Object myMethod (Object blah);
}
public static MyInterface decorator(MyInterface obj) {
//I want to return a version of obj
//with a different implementation of myMethod
//everything else in obj should be same, except myMethod
}
}
You can create a class with the same interface that delegates all the methods calls yo your object, then you create an anonymous class extending it and override whatever you want
Intercace:
Interface MyInterface {
void m1();
void m2();
}
Delegating class:
class MyDelegate implements MyInterface {
private MyInterface delegate;
MyDelegate(MyInterface delegate) {
this.delegate = delegate;
}
void m1() {
delegate.m1();
}
void m2() {
delegate.m2();
}
}
In the static method you create an instance of an anonymous class extending MyDelegate and override whatever you want, the rest will be run by obj
static MyInterface wrap(MyInterface obj) {
return new MyDelegate(obj) {
void m1() {
// overrided m1
}
// my will eventually get to obj
};
}
You can't do that generally, without the knowledge of the exact object type you are decorating. If you know it, then you can create a subclass of that particular class with the implementation changed. Java's type system just isn't flexible enough to mix and match interface implementation like you need.
You could resort to dynamic class definition techniques, which would create a dynamic proxy for every object you pass into your decorate method, but there's an order of magnitude more complexity in such an approach.
Such kind of dynamic behavior is not directly supported in Java. But you can achieve something like this when the object cooperates. I.e. it could provide a method to change the implementation of myMethod:
void changeMethod(MyInterface other) {
realImpl = other;
}
Object myMethod (Object obj) {
return realImpl.myMethod(obj);
}
Using CGLib you can implements interfaces at runtime.
Example -
public class KeySample {
private interface MyFactory {
public Object newInstance(int a, char[] b, String d);
}
public static void main(String[] args) {
MyFactory f = (MyFactory)KeyFactory.create(MyFactory.class);
Object key1 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
Object key2 = f.newInstance(20, new char[]{ 'a', 'b' }, "hello");
Object key3 = f.newInstance(20, new char[]{ 'a', '_' }, "hello");
System.out.println(key1.equals(key2));
System.out.println(key2.equals(key3));
}
}
You are looking for a dynamic proxy if we can restrict it to interfaces (any number of them).
So your problem: If you call the method in that interface first without calling the decorator and then with the decorator you want different behavior, so given this interface implementation:
MyInterface o = new MyInterface() {
public Object myMethod(Object blah) {
return "bar";
}
};
This should do different things, for example alter the return value (and/or something else):
System.out.println(o.myMethod(null));
o = decorator(o);
System.out.println(o.myMethod(null));
Output:
bar
foo
This can be done with a dynamic proxy in java:
public static MyInterface decorator(final MyInterface obj) {
InvocationHandler handler = new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("myMethod")) {
//do something special
return "foo";
}
return method.invoke(obj, args);
}
};
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
MyInterface.class.getClassLoader(),
obj.getClass().getInterfaces(), //all or limit it to just one or a few
handler);
return proxy;
}
Update:
If you want to involve more interfaces (updated proxy instance code above to get the interfaces implemented instead of hard coding it):
Now makes this work:
public static void main(String[] args) {
A o = new A();
System.out.println(o.myMethod(null));
System.out.println(o.myOtherMethod(1));
Object o2 = decorator(o);
System.out.println(((MyInterface) o2).myMethod(null));
System.out.println(((MyInterface2) o2).myOtherMethod(1));
}
With output:
bar
2
foo <-- changed
2 <- the same behavior
Given:
class A implements MyInterface, MyInterface2 {
#Override
public Object myMethod(Object blah) {
return "bar";
}
#Override
public int myOtherMethod(int a) {
return a+1;
}
}

Categories