I have a class that implements an interface. There's another class that implements this interface, too, and an instance of this second class backs my class's implementation.
For many of the methods specified by the interface, my class simply forwards them straight to the second class.
public class MyClass implements MyInterface
{
private OtherClass otherClassInstance; // Also implements MyInterface.
// ...
void foo() { otherClassInstance.foo(); }
void bar() { otherClassInstance.bar(); }
void baz() { otherClassInstance.baz(); }
// ...
}
Simply deriving my class from the second class would eliminate all of this, but it doesn't make sense because the two classes are unrelated to each other (besides implementing a common interface). They represent different things - it just so happens that a lot of my class's implementation copies that of the other class. In other words, my class is implemented atop the second class, but it is not itself a subset of the second class. As we know, inheritance is meant to express an "is-a" relationship, not to share implementation, so it's inappropriate in this case.
This portion of a talk by Joshua Bloch illustrates the situation well.
I know that Java doesn't have any language support for delegation. However, is there at least some way to clean up my class's implementation so it isn't so redundant?
An answer which is not really an answer to your actual question:
I'd say, live with the boilerplate. Let IDE generate it for you. Example: in Netbeans, add the private ArrayList field, set cursor to where you'd want the methods to appear, hit alt-insert, select "Generate Delegate Method...", click the methods you want to create a delegate for in the dialog opens, submit, go through the generated methods and make them do the right thing, you're done.
It is a bit ugly, but it is still preferable to starting to mess with reflection, when you are dealing with just one class, like it sounds. Your class is probably the kind of class, which you will complete and fully test, and then hopefully never touch again. Reflection creates runtime cost which does not go away. Suffering the auto-generated boilerplate in the source file is probably preferable in this case.
First way to use http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html see tutorial http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html
Second way using AOP you can create dispatcher that intercept all invocation of specific class
For both ways you need to manage methods processing using reflection API
EDITED TO SHOW IDEA
Following code taken from tutorial above just modified a little (see youListImpl.getRealArrayList() in invoke method)
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private YouListImpl youListImpl;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
System.out.println("before method " + m.getName());
result = m.invoke(youListImpl.getRealArrayList(), args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
} finally {
System.out.println("after method " + m.getName());
}
return result;
}
}
Related
I define an interface follow
interface SdkInterface {
void onPause();
void onResume();
void onStop();
}
then I define a abstract class implement the interface
abstract class BaseCore implements SdkInterface {
public static final byte[] lock = new byte[0];
private static final String TAG = "BaseCore";
public static Core instance;
#Override
public void onPause() {
Log.e(TAG, "onPause: ");
}
#Override
public void onResume() {
Log.e(TAG, "onResume: ");
}
#Override
public void onStop() {
Log.e(TAG, "onStop: ");
}
}
then I has a class extends the abstract class
class Core extends BaseCore {
private Core() {
}
public static Core getInstance() {
if (instance == null) {
synchronized (lock) {
if (instance == null) {
instance = new Core();
}
}
}
return instance;
}
}
now I want to generate a proxy for the instance field of the BaseCore class,I do this
public static void register() {
try {
Class<?> core = Class.forName("com.secoo.coobox.Core");
Field instance = core.getSuperclass().getDeclaredField("instance");
Method getInstance = core.getDeclaredMethod("getInstance");
Object invoke = getInstance.invoke(null);
Object o = Proxy.newProxyInstance(core.getClassLoader(), core.getInterfaces(), new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.e("BaseCore", "invoke: before " + method.getName());
Object invoke1 = method.invoke(invoke, args);
Log.e("BaseCore", "invoke: after " + method.getName());
return invoke1;
}
});
instance.set(invoke, o);
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
but I receive the exception
Caused by: java.lang.IllegalArgumentException: field com.secoo.coobox.BaseCore.instance has type com.secoo.coobox.Core, got $Proxy2
at java.lang.reflect.Field.set(Native Method)
at com.secoo.coobox.TestProxy.register(TestProxy.java:31)
at com.secoo.coobox.MainActivity.onCreate(MainActivity.kt:24)
at android.app.Activity.performCreate(Activity.java:8006)
at android.app.Activity.performCreate(Activity.java:7990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3584)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3775)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2246)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:233)
at android.app.ActivityThread.main(ActivityThread.java:8010)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
who can help me explain the excetion and how I can solve the problem? thanks
Your code has serious style issues, and it is broken. And we haven't even gotten to the error you're asking about yet. I suggest you skip the actual answer and instead read why you're barking up the wrong tree and need to rethink this code, making the actual answer irrelevant for you.
The actual answer
Proxy will make a new instance of a proxy class (that's where that $Proxy2 thing is coming from). Proxy cannot make an object that is an instance of that actual class: That's just not how java works. Thus, you have an instance of an unknown, effectively irrelevant class. However, that $Proxy2 class does implement whatever interfaces you want it to. It can't extend anything (other than, obviously, java.lang.Object). No final classes, no normal classes, not even abstract classes. That's just how it works: If you want a proxy that extends something specific, you're out of luck.
Thus: You can only proxy interfaces.
Had the field been:
public static SdkInterface instance;
instead, it would have worked fine; That $Proxy2 class is a class made on the fly by the Proxy.newProxyInstance call, and this class implements all the interface you passed in.
But, as I said, do not just start changing things, you need to rethink this code more fundamentally.
The more significant issues with your code
Your BaseCore class has a field of type Core, eliminating any point or purpose in the class hierarchy of it. Its type should possible be BaseCore, or the 'singleton holder' field should be in Core. Generally fields should have the least specific type that you want to use, e.g. we write List x = new ArrayList - because List is less specific. You've gone the other way, and made the field the most specific type you could find (Core, which is more specific than BaseCore, which is more specific than SdkInterface). If that static field's type is SdkInterface, you can assign a proxy object to it. But if the type of that field is a class (other than java.lang.Object), then that is impossible - as proxies implement whatever interfaces you want, but extend j.l.Object and can't be made to extend anything else.
Double checked locking does not work, so don't do it. Your getInstance() method is broken in a really nasty way: It is broken, but, most tests do not catch it. It requires a specific combination of hardware, android version, and phase of the moon for it to fail. There are only 2 sane ways to 'load' singletons: Generally, just initialize the field (and make it final), because java lazy loads; the only benefit to having an actual method that loads it only when you invoke .getInstance() or whatnot, is when it is plausible you will 'touch' the class (load a class that has a field of type Core, for example), but never actually need the instance. This happens, but it is rare. If it doesn't apply to you, there is no point to any of this, and you can just write public static final Core INSTANCE = new Core(); and be done with it all. If you really do need the getSingleton method, use the java classloader which is extremely good at efficient locking - at least as good as anything you can write in java and possibly better:
public static Core get() {
return CoreSingletonHolder.INSTANCE;
}
private static class CoreSingletonHolder {
static final Core INSTANCE = new Core();
}
This works because java doesn't load classes until it is needed, and nothing 'touches' CoreSingletonHolder (causing it to be loaded), except invoking the get() method. Hence, new Core() is executed exactly once, and only once, as per JVM guarantees, using ClassLoader's own locking mechanism, which is very efficient. It's efficient because java has to do this with every single last class your app ever loads. If it wasn't efficient, java/android would be dog slow, and we know it isn't, QED.
Your intended singleton instance is public and non-final; anything can overwrite it. The above strategies fix these issues; given that all access needs to go through get() in order to ensure its initialized, why make it public?
I am looking for a way to implement an abstract class (or effectively abstract) that enforces only one instance of each subclass.
I am fairly sure this would be pretty simple to implement with a Factory but I would be interested to know if it can be done without knowing all subclass types, i.e a generic singleton enforcer class.
Right now I am mostly just playing around with the idea for something like this, So I am not looking for feedback that questions the design choice here.
The language I am working in is Java, but right now I am not necessarily worried about implementation details, Unless it is not possible in Java, then, of course, provide evidence that it is not possible.
I'm wondering what it is you are trying to do. A couple of possibilities spring to mind and knowing where this is heading might help.
Option 1
So you could try to use an enum type as your abstract base class. Each enumeration constant is then guaranteed by the language to be a singleton. The enum can have abstract methods which the constants implement. This will work but compilation unit an get very big and hard to navigate if you have a lot of implementing constants and a lot of abstract methods to implement. You could of course delegate some of the work to helper classes if it starts to get out of hand.
Option 2
You could do is get the base class constructor to check it's actual type and store it in a static HashSet (or similar). If an entry already exists then you have two instances of the same singleton. Something like
public abstract class BaseClass {
private static HashSet<Class<?>> instances = new HashSet<>();
protected BaseClass() {
checkInstances();
}
private synchronized void checkInstances() {
boolean duplicate = instances.add(getClass());
if (duplicate) {
throw new RuntimeException("Duplicate class " + getClass().getName());
}
}
}
The disadvantage of this is that the error occurs at runtime and the code isn't especially pretty and as you can see you may need to consider synchronization of the set
Option 3
Your final option is simply not to ask the base class to enforce this restriction. It should probably the job of the derived classes to decided if they are singletons or not. A private constructor in the derived class is the easiest way to do that.
Conclusion
Personally I'd implement either option 1 or option 3 as you won't get run-time failures.
First, a generic singleton doesn't make sense.
A parent class should not be responsible of retrieving and managing instances of its subclasses.
It creates a strong coupling in both ways (parent->child and child->parent).
Second, as shmosel says, subclassing a singleton (without special artifact) is not possible.
The key of the singleton pattern is the lack of ability to instantiate the class outside the singleton class, so no public constructor has to be provided.
In these conditions, how subclass the singleton class ?
To allow subclassing a singleton class, you must have a public constructor while ensuring that you have no more than one instance of the class.
Inversion of control containers such as Spring may do that (It is an example of special artifact).
As a side note, I don't consider access modifier tweaking such as the package-private modifier that could allow to subclass a singleton but the limitation of it is that the singleton would be a singleton only outside the package.
I wanted to say, that singletons are bad. But found this problem interesting, So I created what you want.
Here is the code
public static abstract class SingletonBase {
private static HashSet<SingletonBase> instances = new HashSet<>();
{
for (SingletonBase sb : instances) {
if (sb.getClass() == this.getClass()) throw new RuntimeException("there is already 1 instance");
}
}
public static <E> E getInstance(Class<E> clazz) {
if (!SingletonBase.class.isAssignableFrom(clazz)) {
throw new RuntimeException();
}
for (SingletonBase sb : instances) {
if (sb.getClass() == clazz) return (E) sb;
}
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
private SingletonBase() {
instances.add(this);
}
}
static class SingletonTest extends SingletonBase{
}
static class SecondSingletonTest extends SingletonBase{
}
public static void main(String[] args) {
for(int i=0;i<=10;i++)
System.out.println( SingletonBase.getInstance(SingletonTest.class));
for(int i=0;i<=10;i++)
System.out.println( SingletonBase.getInstance(SecondSingletonTest.class));
//throws exception, because we try to create second instance here
new SingletonTest();
}
There are some problems with approach of creating generic class which are solved here:
first, you cannot create more than one instance, so base class has to keep track of all instances, and when you try to create another one using new, it will throw exception. Second, you need to get instance for a specific class. If you dont want to create instance like this:
SingletonBase.getInstance(SecondSingletonTest.class)
You can create subclasses like this:
static class SingletonTest extends SingletonBase{
public static SingletonTest getInstance(){
return getInstance(SingletonTest.class);
}
}
There was also suggested to use ENUM approach, it is easy to implement, but breakes open closed principle from SOLID
I am writing a utility which uses some classes defined in a 3rd party library which i do not control.
I would like the to know what would be a good way to handle situations like the one described below :
3rd party library has a base abstract class 'Food' which is extended by 'Appetizer','Entree',"Beverage' and 'Dessert'. (all part of 3rd Party Library)
I am writing a 'WaiterUtility' which has methods to serve each type of food.
I want to avoid an endless chain of instanceof checks .
`
Class WaiterUtility{
public serveItems(Food[] items)
{
for(Food aFood : items){
//how do i call the sub-class specific methods i wrote below?
}
}
private void serve(Appetizer aFood){//somecode}
private void serve(Entree aFood){//somecode}
private void serve(Beverage aFood){//somecode}
private void serve(Dessert aFood){//somecode}
}
`
If at all possible, I would implore you NOT to use reflection as TBotV63 does in his answer (he even says to avoid it). From the Oracle documentation:
If it is possible to perform an operation without using reflection, then it is preferable to avoid using it.
So, obviously we're inclined to say that all Foods can be served, and that any Waiter can serve any kind of Food. Ideally a good API would therefore expose methods that would be sufficient for a serve(Food) method to do the job without knowledge of what kind of food it is. It seems like your question implies that this is not the case, and therefore something more needs to be done.
If the 3rd party library accepts community input then you should try to open an issue or a pull request to add the functionality.
Obviously that's not always possible, so the next best thing to do would be to create an interface (something like Serveable) which defines the methods you would need, and then subclass the different types of food while implementing that interface. Then you would have Waiter.serve(Serveable).
This is more work than reflection or many uses of instanceof, but it is better OO design.
Why reflection is bad
The documentation for reflection points out 3 drawbacks of reflection
exposure of internals
performance
security
While you might not care about 2 or 3, 1 is especially bad.
... use of reflection can ... render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.
Why instanceof is bad (in this case)
serveItems(Food[]) implies to the caller that if you pass it several Food items, it will serve each of them. However this is not really the case. We can only serve certain sub-classes of Food, and we will have run-time errors if we try anything else. Java is a nice typesafe language, we like compile-time errors much more than run-time errors.
Another downside is that additional code needs to be added to Waiter every time a new sub-class of Food is added or changed. This becomes a cross-cutting concern and makes the code unscalable from a development perspective.
These are by no means the only downsides/issues, just a couple examples.
You can try following code:
Class WaiterUtility{
private Map<Class<? extends Food>, Waiter> waiters = new HashMap<>();
WaiterUtility() {
waiters.put(Appetizer.class, new AppetizerWaiter());
waiters.put(Entree.class, new EntreeWaiter());
waiters.put(Beverage.class, new BeverageWaiter());
waiters.put(Dessert.class, new DessertWaiter());
}
public serveItems(Food[] items)
{
for(Food aFood : items){
waiter.get(aFood.getClass()).serve(aFood);
}
}
private static abstract interface Waiter {
private void serve(Food aFood);
}
private static class AppetizerWaiter implements Waiter {
private void serve(Food aFood){
Appetizer appetizer = (Appetizer) aFood;
//somecode
}
}
private static class EntreeWaiter implements Waiter {
private void serve(Food aFood){//somecode}
}
private static class BeverageWaiter implements Waiter {
private void serve(Food aFood){//somecode}
}
private static class DessertWaiter implements Waiter {
private void serve(Food aFood){//somecode}
}
}
Try something similar to the following:
public serveItems(Food[] items)
{
for(Food aFood : items){
Class<?> foodClass = aFood.getClass(); // Get the food's class
Method serve = WaiterUtility.class.getMethod("serve", foodClass); // Get the method by name and argument types
try {
serve.invoke(this, aFood);
} catch (IllegalArgumentException e) { // Should never occur, we're matching it up.
} catch (IllegalAccessException e) { // Shouldn't occur, we're in the same class.
} catch (InvocationTargetException e) {
// Handle errors possibly thrown by the serve method.
}
}
Haven't tested this tho.
Note that you should however avoid this, it's terrible design.
I have a little problem with default methods in Interface and BeanInfo Introspector.
In this example, there is interface: Interface
public static interface Interface {
default public String getLetter() {
return "A";
}
}
and two classes ClassA and ClassB:
public static class ClassA implements Interface {
}
public static class ClassB implements Interface {
public String getLetter() {
return "B";
}
}
In main method app prints PropertyDescriptors from BeanInfo:
public static String formatData(PropertyDescriptor[] pds) {
return Arrays.asList(pds).stream()
.map((pd) -> pd.getName()).collect(Collectors.joining(", "));
}
public static void main(String[] args) {
try {
System.out.println(
formatData(Introspector.getBeanInfo(ClassA.class)
.getPropertyDescriptors()));
System.out.println(
formatData(Introspector.getBeanInfo(ClassB.class)
.getPropertyDescriptors()));
} catch (IntrospectionException e) {
e.printStackTrace();
}
}
And the result is:
class
class, letter
Why default method "letter" is not visible as property in ClassA? Is it bug or feature?
I guess, Introspector does not process interface hierarchy chains, even though with Java 8 virtual extention methods (aka defenders, default methods) interfaces can have something that kinda sorta looks like property methods. Here's a rather simplistic introspector that claims it does: BeanIntrospector
Whether this can be considered a bug is somewhat of a gray area, here's why I think so.
Obviously, now a class can "inherit" from an interface a method that has all the qualities of what's oficially considered a getter/setter/mutator. But at the same time, this whole thing is against interface's purpose -- an interface can not possibly provide anything that can be considered a property, since it's stateless and behaviorless, it's only meant to describe behavior. Even defender methods are basically static unless they access real properties of a concrete implementation.
On the other hand, if we assume defenders are officially inherited (as opposed to providing default implementation which is a rather ambiguous definition), they should result in synthetic methods being created in the implementing class, and those belong to the class and are traversed as part of PropertyDescriptor lookup. Obviously this is not the way it is though, otherwise the whole thing would be working. :) It seems that defender methods are getting some kind of special treatment here.
Debugging reveals that this method is filtered out at Introspector#getPublicDeclaredMethods():
if (!method.getDeclaringClass().equals(clz)) {
result[i] = null; // ignore methods declared elsewhere
}
where clz is a fully-qualified name of the class in question.
Since ClassB has custom implementation of this method, it passes the check successfully while ClassA doesn't.
I think also that it is a bug.
You can solve this using a dedicated BeanInfo for your class, and by providing somthing like that :
/* (non-Javadoc)
* #see java.beans.SimpleBeanInfo#getAdditionalBeanInfo()
*/
#Override
public BeanInfo[] getAdditionalBeanInfo()
{
Class<?> superclass = Interface.class;
BeanInfo info = null;
try
{
info = Introspector.getBeanInfo(superclass);
}
catch (IntrospectionException e)
{
//nothing to do
}
if (info != null)
return new BeanInfo[] { info };
return null;
}
This is because you only have your method on Interface and ClassB, not on ClassA directly. However it sounds to me like a bug since I'd expect that property to showup on the list. I suspect Inrospector did not catch up with Java 8 features yet.
I have a factory method that creates objects to be used in unit tests. These objects all derive from the same base class:
public static <T extends BaseEntity> T modMake(Class<T> clazz)
{
try {
return clazz.newInstance();
} catch (InstantiationException e) {
// Should never happen
throw new AssertionError(e);
} catch (IllegalAccessException e) {
// Should never happen
throw new AssertionError(e);
}
}
Now I want to override a getter method from that base class, but just for the tests. I would usually do that with an anonymous class, for example (Node being one of the subtaypes of BaseEntity):
public static Node nodMake()
{
return new Node() {
#Override
public long ixGet() { return 1; }
};
}
Can I do that in the function using the Class argument, too?
Lose your factory method and use a mocking API like EasyMock to achieve the behavior you describe.
Your code will then end up something like this:
long returnValue = 12;
Node nodeMock = createMock(Node.class);
expect(nodeMock.ixGet()).andReturn(returnValue);
replay(nodeMock);
//add test code here
verify(nodeMock);
To answer Hanno's question on how this works:
It depends on whether your mocking an interface or a class.
The case of the interface is simple (code-wise), it uses what's called a dynamic proxy, which is part of core Java.
In the case of the class it's doing the bytecode manipulation that #Jonathan mentions in his answer, just behind a nice API.
Both the above mechanisms allow the method calls to be intercepted and EasyMock simply responds based on the expectations you've setup.
I don't think there is any way to do that. You probably need to look into bytecode manipulators if you really need to go that route. Javassist and BCEL are a couple of choices.