Reflection: how to call superclass constructor which is hidden? - java

Re-edited...
I'd like to use a superclass constructor which is hidden by the "#hide" Android tag (or whatever it is).
I'm about to extend a class which has been already extended twice (within the Android OS). I'd like to create my own subclass (i.e. outside the Android OS). Example subclass, taken from Android sources:
public class WifiP2pDnsSdServiceInfo extends WifiP2pServiceInfo {
...
private WifiP2pDnsSdServiceInfo(List<String> queryList) {
super(queryList); // <-- this is what I'm trying to do, too
}
public static WifiP2pDnsSdServiceInfo newInstance(String instanceName,
String serviceType, Map<String, String> txtMap) {
...
ArrayList<String> queries = new ArrayList<String>();
...
return new WifiP2pDnsSdServiceInfo(queries);
}
}
The superclass looks like this:
public class WifiP2pServiceInfo implements Parcelable {
...
// this is marked as #hidden therefore inaccessible!
protected WifiP2pServiceInfo(List<String> queryList) {
if (queryList == null) {
throw new IllegalArgumentException("query list cannot be null");
}
mQueryList = queryList;
}
}
And all I want to do is to make another kind of WifiP2pServiceInfo, similar to the WifiP2pDnsSdServiceInfo example above. I can't just inherit & call super() because the superclass constructor is tagged by Android's "#hide", therefore unusable without reflection for non-system programmers.
So my question is how to access / call the superclass constructor if I can't do it by a plain super() call? Reflection should come handy here but I'm not very experienced in Java programming.

After some research I'm able to answer the question by myself.
Short answer: I can't do this because if the superclass constructor is protected and hidden, the compiler is going to complain even if I found a way how to call the constructor via reflection.
Long answer: it turns out it's not so complicated to "unhide" this stuff. Following this tutorial I'm able to extend the class to my needs.
See? A lot of noise for nothing, this is the answer I was looking for.

You want to find that constructor and set its availability to true.
But this is a dangerous operation that you should not attempt lightly. It's a dirty secret that private need not mean private, but I would still expect you to honor the wishes of the class designer and not circumvent.
Besides, you don't need to. If I understand your requirement, I've posted an example that will do what you want.
This works, because of this:
The protected modifier specifies that the member can only be accessed
within its own package (as with package-private) and, in addition, by
a subclass of its class in another package.
I think you've confused the meaning of the protected modifier.
Parent w/ protected ctor:
package foo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Parent with protected constructor
* User: MDUFFY
* Date: 3/27/14
* Time: 5:18 PM
* #link http://stackoverflow.com/questions/22698501/reflection-how-to-call-superclass-constructor-which-is-hidden/22698543?noredirect=1#comment34586243_22698543
*/
public class Foo {
private List<String> x;
protected Foo(List<String> y) {
this.x = ((y == null) ? new ArrayList<String>() : new ArrayList<String>(y));
}
public List<String> getX() {
return Collections.unmodifiableList(this.x);
}
#Override
public String toString() {
return "Foo{" +
"x=" + x +
'}';
}
}
Child extends Parent:
package bar;
import foo.Foo;
import java.util.Arrays;
import java.util.List;
/**
* Child of parent with protected ctor
* User: MDUFFY
* Date: 3/27/14
* Time: 5:22 PM
* #link http://stackoverflow.com/questions/22698501/reflection-how-to-call-superclass-constructor-which-is-hidden/22698543?noredirect=1#comment34586243_22698543
*/
public class Bar extends Foo {
public static void main(String[] args) {
Bar bar = new Bar(Arrays.asList(args));
System.out.println(bar);
}
public Bar(List<String> y) {
super(y);
}
}
This will compile and run.

Related

How to use reflection to get a constructor where you are passing in a super class as a paremeter

Today while coding I began a deep dive into the world of reflection. I have messed with it in small bits and pieces before but never to this extent and no matter where I look I can find no answer to my question and so here I am! Currently what I am trying to do is use reflection with a class whose constructor requests a parameter but for ease of use I wish to use the super class of the parameter.
Here is the code causing problems with some explanations:
this.listener = (MyListener) listenerClass.getConstructor(MyAppState.class).newInstance(this);
The thing is that MyAppState is the class that all of my appstates extend from and each listener takes in its own specific AppState that extends MyAppState but has extra features different from each other. What I need to know is what I can put in my .getConstructor() to specify that the class I am passing in is the super of the parameter it wants.
Here is a theoretical example of the code:
this.listener = (MyListener) listenerClass.getConstructor(Class extends MyAppState.class).newInstance(this);
So is this possible or should I just work with my code to have a second constructor that accepts the MyAppState class, or something else along those lines.
Also, sorry if this is off topic but to prevent problems in the future, I am being told this question is subjective. Is there any way to word future questions to not be as subjective or is the method to figure out whether the question is subjective just a bit flawed?
[EDIT] As requested, a few more examples related to the question:
public MyAppState(Node screen, Class listenerClass)
{
this.screen = screen;
try
{
this.listener = (MyListener) listenerClass.getConstructor(MyAppState.class).newInstance(this);
}
catch (Exception e)
{
Logger.getLogger(MyAppState.class.getName()).log(Level.SEVERE, "The listener for the {0} appstate could not be created using reflection.", new Object[]{this.getClass().getName()});
System.exit(-1);
}
}
Above is the full parent class's constructor, the said class extends one more class but it contains no constructor and so I am not sure if it is needed. If it is please feel free to ask for it.
public class OptionsMenuState extends MyAppState
{
public OptionsMenuState()
{
super(new Node("Options Screen"), OptionsMenuStateListener.class);
}
That is one class and its constructor with pieces cut off to keep it short.
public class MainMenuState extends MyAppState
{
public MainMenuState()
{
super(new Node("Start Screen"), MainMenuStateListener.class);
}
Here is another class and its constructor.
[EDIT] As suggested, I created a program that roughly mimics what I am attempting to do.
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
//This is what I want to do but I don't know how to have java allow me to pass in Greeting.
createObject(SimpleSentence.class);
createObject(DifferentSentence.class);
}
public static void createObject(Class theClass)
{
theClass.getConstructor(Greeting.class).newInstance(new Hello());
}
class SimpleSentence
{
Hello firstWord;
public SimpleSentence(Hello word)
{
firstWord = word;
}
}
class DifferentSentence
{
Howdy firstWord;
public DifferentSentence(Howdy word)
{
firstWord = word;
}
}
class Greeting
{
}
class Hello extends Greeting
{
}
class Howdy extends Greeting
{
}
}
Short answer is you can't. getConstructor(Class<?>...parametertypes) is very explicit because it needs to match exactly zero or one constructor only.
You will need to go through all the constructors to find one, that has a parameter that is assignable from MyAppState
e.g. outline:
final Constructor<?>[] ctrs = listenerClass.getConstructors();
for (Constructor<?> constructor : ctrs) {
if (constructor.getParameterTypes()[0].isAssignableFrom(MyAppState.class)) {
// use this one?
}
}

How to create a method in a Java class that is accesible from only one other class

I was wondering if anyone had a pattern that would help me achieve the following:
We have a JPA entity called Employee and on it there is a setLineManager method. We also have a separate updateLineStructureService, which is a Spring-managed service bean. We want to try and ensure that this setLineManager method can only be called from updateLineStructureService and not directly from any other class.
Is there a way to allow the service access to this method without exposing it to any other classes? I am aware that I could give the method package level access and put the service in the same package as Employee, but that will not fit our package structure so I would prefer not to do that. I am also aware that I could make the method private and just access it through reflection in this one place, but I do not like that solution at all.
Any ideas?
You can inspect the stacktrace (using Throwable#getStackTrace()) and see if it contains the allowed method on specified position.
In the following code snippet, System.PrivateEmployee is not visible outside the System class. Thus effectively privateMethod is private and can only be called from within the System class. Since System.PrivateEmployee extends System.PublicEmployee it can be used outside the System class as System.PublicEmployee
public class System
{
public static interface PublicEmployee { void publicMethod ( ) ; }
private static interface PrivateEmployee extends PublicEmployee { void privateMethod ( ) ; }
}
Use an inner class only available to the other service class:
public class Employee
{
static {
LineStructureService.registerEmployeeHelper(new EmployeeHelper() {
#Override
public void setLineManager(Employee emp, Object foo) {
emp.setLineManager(foo);
}
});
}
public static void init() {}
private void setLineManager(Object foo) { }
}
public class LineStructureService
{
private static volatile EmployeeHelper _helper;
static {
// ensure that Employee class is loaded and helper registered
Employee.init();
}
public static synchronized void registerEmployeeHelper(EmployeeHelper helper) {
_helper = helper;
}
public void doSomething(Employee emp)
{
// now this class can call setLineManager on Employee
_helper.setLineManager(emp, blah);
}
public interface EmployeeHelper {
public void setLineManager(Employee emp, Object foo);
}
}
The only way that a class can access private methods of other classes is with inner classes. If that is not an option, this can't be done.
One approach is to make two forms of Employee.
"BasicEmployee" has all the methods except setLineManager(). "ExtendedEmployee" extends BasicEmployee and adds a public void setLineManager(). (I'm assuming these are classes, but they could also be interfaces instead) Underneath the hood, everything is really a FullEmployee (for clarity, you could make BasicEmployee abstract). But, in the code, in all the classes except UpdateLineStructureService, you declare it as a BasicEmployee. Only in UpdateLineStructureService is it declared as a FullEmployee. So, only UpdateLineStructureService has easy access to setLineManager()
Now, a rogue coder could always cast their BasicEmployee to an ExtendedEmployee to access setLineManager(), so this isn't totally secure. But it's a reasonable pattern to limit access.
You could use AOP (e.g. AspectJ or CDI) to intercept the call to setLineManager(); if the caller is updateLineStructureService() call the method; if not do nothing, or raise an exception or whatever.

Java - Statements / Conversions | Pulpcore

[please note this may require AS3 + Java knowledge]
Background Information:
I'm trying to build a game using Java + Pulpcore, but I'm fairly new to the scene. The game I'm building could possibly be more performance intensive than I thought, and I know Java would solve my problems with this, but there are a couple questions I have dealing with strict-types, etc.
Here is my code in AS3:
Main.as3
import org.tbmb.champions.Container;
import org.tbmb.zombies.ZContainer;
public class Main extends MovieClip {
// ******* temporary properties ******* /
private var blunder:Container = null;
// ******* ******* /
public function Main() {
init(); // initialize objects
}
public function init():void {
blunder = new Container(Blunder as Class);
} // end of class
}
Container.as3
package org.tbmb.champions {
import flash.display.MovieClip;
public class Container extends MovieClip {
public function Container(champ:*) {
} // end of constructor
} // end of class
} // end of package
Blunder.as3
package org.tbmb.champions.blunder {
import flash.display.MovieClip;
public class Blunder extends MovieClip {
public function Blunder() {
} // end of constructor
} // end of class
} // end of constructor
1.) How would I rewrite in Java?
blunder = new Container(Blunder as Class);
2.) How would I be able to accept any Classes in Java for the above line within my Container class?
public function Container(champ:*) {
I need to do this because I'm sending different champion classes (depending on what the user picks) to a containing class that will hold all their other classes (health, etc). I need my Container class to accept any Class rather than just one; what type would I use?
Here is what I have in Java so far:
ZomboPulp.java (Main Class)
import pulpcore.scene.Scene2D;
import org.tnpfk.champions.Container;
import org.tnpfk.champions.blunder.Blunder;
import pulpcore.sprite.FilledSprite;
import pulpcore.image.Colors;
public class ZomboPulp extends Scene2D {
FilledSprite background = new FilledSprite(Colors.WHITE);
Container container = null; // Container that contain's blunder,
// and all his objects (health, mana, etc)
public void load() {
this.initScreen(); // initialize main screen.
this.initObjects(); // initialize our objects.
} // end of load();
public void initScreen() {
add(background);
} // end of initScreen();
public void initObjects() {
container = new Container(Blunder as Class); // ERROR HERE
} // end of initObjects();
}
Container.java
package org.tnpfk.champions;
public class Container {
public Container(Object champ) {
} // end of constructor
} // end of class
Sorry for the lengthy post, and thanks for any help. By the way, I did check StackOverflow; and Google, but I was unable to find anything about this.
Thanks,
jvmpulp
Alrighty! I have no experience with PulpCore, but I do know both AS3 and Java, so I think I can answer your question. First off, I guess I don't 100% understand what you need to do with the champ object in the Container class, and I really don't understand why you were doing Blunder as Class instead of just passing an instance of Blunder. Either way, here's what I'd recommend with what you have as of now:
public void initObjects() {
container = new Container(Blunder.class);
}
As you can see, you can get a Class instance just by getting the class property of any class. Now, you have the right idea with using Object as the type for the Container constructor for any type. However, using Object is bad practice (use method overloading/more specific types instead), and it's not even required here. Getting the class property will always be of type Class, even though they represent different classes. So, rewrite the constructor as this:
public Container(Class champ) {
}
Then, do whatever you need to do with the class.
Now, that's basically a direct port, but it seems some of the things you're doing are bad practice. The whole system of passing a Class object seems irrelevant and unnecessary; why not just pass an instance of the object? For example, like so:
public class Container {
protected Champion champ;
public Container(Champion champ) {
this.champ = champ;
}
}
Now, make Champion an abstract class that contains the common methods for all the champions:
public abstract class Champion {
protected Something something;
abstract Something getSomething();
}
(Obviously, the variable/method shown here are just examples.) Then, have your individual Champion classes subclass Champion:
public class Blunder extends Champion {
public Something getSomething() {
return this.something;
}
}
Etc. Then, finally, do this:
public void initObjects() {
container = new Container(new Blunder());
}
Obviously, this is a basic example, and you don't have to take my advice. But it would probably be easier to do than the system you already had in AS3.

Is it a bad idea to declare a final static method?

I understand that in this code:
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
.. the static method in Bar 'hides' the static method declared in Foo, as opposed to overriding it in the polymorphism sense.
class Test {
public static void main(String[] args) {
Foo.method();
Bar.method();
}
}
...will output:
in Foo
in Bar
Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:
in Foo
in Foo
(Edit: Compilation fails when you mark the method as final, and only runs again when I remove Bar.method())
Is it considered bad practice to declare static methods as final, if it stops subclasses from intentionally or inadvertantly re-defining the method?
(this is a good explanation of what the behaviour of using final is..)
I don't consider it's bad practice to mark a static method as final.
As you found out, final will prevent the method from being hidden by subclasses which is very good news imho.
I'm quite surprised by your statement:
Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:
in Foo
in Foo
No, marking the method as final in Foo will prevent Bar from compiling. At least in Eclipse I'm getting:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Cannot override the final method from Foo
Also, I think people should always invoke static method qualifying them with the class name even within the class itself:
class Foo
{
private static final void foo()
{
System.out.println("hollywood!");
}
public Foo()
{
foo(); // both compile
Foo.foo(); // but I prefer this one
}
}
Static methods are one of Java's most confusing features. Best practices are there to fix this, and making all static methods final is one of these best practices!
The problem with static methods is that
they are not class methods, but global functions prefixed with a classname
it is strange that they are "inherited" to subclasses
it is surprising that they cannot be overridden but hidden
it is totally broken that they can be called with an instance as receiver
therefore you should
always call them with their class as receiver
always call them with the declaring class only as receiver
always make them (or the declaring class) final
and you should
never call them with an instance as receiver
never call them with a subclass of their declaring class as receiver
never redefine them in subclasses
NB: the second version of you program should fails a compilation error. I presume your IDE is hiding this fact from you!
If I have a public static method, then it's often already located in a so-called utility class with only static methods. Self-explaining examples are StringUtil, SqlUtil, IOUtil, etcetera. Those utility classes are by itselves already declared final and supplied with a private constructor. E.g.
public final class SomeUtil {
private SomeUtil() {
// Hide c'tor.
}
public static SomeObject doSomething(SomeObject argument1) {
// ...
}
public static SomeObject doSomethingElse(SomeObject argument1) {
// ...
}
}
This way you cannot override them.
If yours is not located in kind of an utility class, then I'd question the value of the public modifier. Shouldn't it be private? Else just move it out to some utility class. Do not clutter "normal" classes with public static methods. This way you also don't need to mark them final.
Another case is a kind of abstract factory class, which returns concrete implementations of self through a public static method. In such case it would perfectly make sense to mark the method final, you don't want the concrete implementations be able to override the method.
Usually with utility classes - classes with only static methods - it is undesirable to use inheritence. for this reason you may want to define the class as final to prevent other classes extending it. This would negate putting final modifiers on your utility class methods.
The code does not compile:
Test.java:8: method() in Bar cannot
override method() in Foo; overridden
method is static final
public static void method() {
The message is misleading since a static method can, by definition, never be overridden.
I do the following when coding (not 100% all the time, but nothing here is "wrong":
(The first set of "rules" are done for most things - some special cases are covered after)
create an interface
create an abstract class that implements the interface
create concrete classes that extend the abstract class
create concrete classes that implements the interface but do not extend the abstract class
always, if possible, make all variables/constants/parameters of the interface
Since an interface cannot have static methods you don't wind up with the issue. If you are going to make static methods in the abstract class or concrete classes they must be private, then there is no way to try to override them.
Special cases:
Utility classes (classes with all static methods):
declare the class as final
give it a private constructor to prevent accidental creation
If you want to have a static method in a concrete or abstract class that is not private you probably want to instead create a utility class instead.
Value classes (a class that is very specialized to essentially hold data, like java.awt.Point where it is pretty much holding x and y values):
no need to create an interface
no need to create an abstract class
class should be final
non-private static methods are OK, especially for construction as you may want to perform caching.
If you follow the above advice you will wind up with pretty flexible code that also has fairly clean separation of responsibilities.
An example value class is this Location class:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Location
implements Comparable<Location>
{
// should really use weak references here to help out with garbage collection
private static final Map<Integer, Map<Integer, Location>> locations;
private final int row;
private final int col;
static
{
locations = new HashMap<Integer, Map<Integer, Location>>();
}
private Location(final int r,
final int c)
{
if(r < 0)
{
throw new IllegalArgumentException("r must be >= 0, was: " + r);
}
if(c < 0)
{
throw new IllegalArgumentException("c must be >= 0, was: " + c);
}
row = r;
col = c;
}
public int getRow()
{
return (row);
}
public int getCol()
{
return (col);
}
// this ensures that only one location is created for each row/col pair... could not
// do that if the constructor was not private.
public static Location fromRowCol(final int row,
final int col)
{
Location location;
Map<Integer, Location> forRow;
if(row < 0)
{
throw new IllegalArgumentException("row must be >= 0, was: " + row);
}
if(col < 0)
{
throw new IllegalArgumentException("col must be >= 0, was: " + col);
}
forRow = locations.get(row);
if(forRow == null)
{
forRow = new HashMap<Integer, Location>(col);
locations.put(row, forRow);
}
location = forRow.get(col);
if(location == null)
{
location = new Location(row, col);
forRow.put(col, location);
}
return (location);
}
private static void ensureCapacity(final List<?> list,
final int size)
{
while(list.size() <= size)
{
list.add(null);
}
}
#Override
public int hashCode()
{
// should think up a better way to do this...
return (row * col);
}
#Override
public boolean equals(final Object obj)
{
final Location other;
if(obj == null)
{
return false;
}
if(getClass() != obj.getClass())
{
return false;
}
other = (Location)obj;
if(row != other.row)
{
return false;
}
if(col != other.col)
{
return false;
}
return true;
}
#Override
public String toString()
{
return ("[" + row + ", " + col + "]");
}
public int compareTo(final Location other)
{
final int val;
if(row == other.row)
{
val = col - other.col;
}
else
{
val = row - other.row;
}
return (val);
}
}
It might be a good thing to mark static methods as final, particularly if you are developing a framework that you expect others to extend. That way your users won't inadvertently end up hiding your static methods in their classes. But if you are developing a framework you might want to avoid using static methods to begin with.
Most of this final issue dates back to the time when VM-s were quite dumb/conservative. Back then if you marked a method final it meant (among other things), that the VM can inline it, avoiding method calls. That is not case since a long-long (or long double :P ) time: http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html .
I guess that Idea/Netbeans inspection warns you, because it thinks that you want to use the final keyword for optimization and they think that you are unaware of the fact that it is unneeded with modern VMs.
Just my two cents...
I encountered one detriment to using final methods using Spring's AOP and MVC. I was trying to use spring's AOP put in security hooks around one of the methods in the AbstractFormController which was declared final. I think spring was using the bcel library for injection in classes and there was some limitation there.
When I create pure utility classes, I declare then with a private constructor so they cannot be extended. When creating normal classes, I declare my methods static if they are not using any of the class instance variables (or, in some cases, even if they were, I would pass the arguments in the method and make it static, it's easier to see what the method is doing). These methods are declared static but are also private - they are there just to avoid code duplication or to make the code easier to understand.
That being said, I don't remember running into the case where you have a class that has public static methods and that can/ should be extended. But, based on what was reported here, I would declare its static methods final.
Because static methods are the properties of the class and they are called with the name of the class rather than of object. If we make the parent class method final as well it will not be overloaded as final methods does not allow to change its memory location but we can update the final data member at the same memory location...

override java final methods via reflection or other means?

This question arise while trying to write test cases. Foo is a class within the framework library which I dont have source access to.
public class Foo{
public final Object getX(){
...
}
}
my applications will
public class Bar extends Foo{
public int process(){
Object value = getX();
...
}
}
The unit test case is unable to initalize as I can't create a Foo object due to other dependencies. The BarTest throws a null pointer as value is null.
public class BarTest extends TestCase{
public testProcess(){
Bar bar = new Bar();
int result = bar.process();
...
}
}
Is there a way i can use reflection api to set the getX() to non-final? or how should I go about testing?
As this was one of the top results for "override final method java" in google. I thought I would leave my solution. This class shows a simple solution using the example "Bagel" class and a free to use javassist library:
/**
* This class shows how you can override a final method of a super class using the Javassist's bytecode toolkit
* The library can be found here: http://jboss-javassist.github.io/javassist/
*
* The basic idea is that you get the super class and reset the modifiers so the modifiers of the method don't include final.
* Then you add in a new method to the sub class which overrides the now non final method of the super class.
*
* The only "catch" is you have to do the class manipulation before any calls to the class happen in your code. So put the
* manipulation as early in your code as you can otherwise you will get exceptions.
*/
package packagename;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
/**
* A simple class to show how to use the library
*/
public class TestCt {
/**
* The starting point for the application
*/
public static void main(String[] args) {
// in order for us to override the final method we must manipulate the class using the Javassist library.
// we need to do this FIRST because once we initialize the class it will no longer be editable.
try
{
// get the super class
CtClass bagel = ClassPool.getDefault().get("packagename.TestCt$Bagel");
// get the method you want to override
CtMethod originalMethod = bagel.getDeclaredMethod("getDescription");
// set the modifier. This will remove the 'final' modifier from the method.
// If for whatever reason you needed more than one modifier just add them together
originalMethod.setModifiers(Modifier.PUBLIC);
// save the changes to the super class
bagel.toClass();
// get the subclass
CtClass bagelsolver = ClassPool.getDefault().get("packagename.TestCt$BagelWithOptions");
// create the method that will override the super class's method and include the options in the output
CtMethod overrideMethod = CtNewMethod.make("public String getDescription() { return super.getDescription() + \" with \" + getOptions(); }", bagelsolver);
// add the new method to the sub class
bagelsolver.addMethod(overrideMethod);
// save the changes to the sub class
bagelsolver.toClass();
}
catch (Exception e)
{
e.printStackTrace();
}
// now that we have edited the classes with the new methods, we can create an instance and see if it worked
// create a new instance of BagelWithOptions
BagelWithOptions myBagel = new BagelWithOptions();
// give it some options
myBagel.setOptions("cheese, bacon and eggs");
// print the description of the bagel to the console.
// This should now use our new code when calling getDescription() which will include the options in the output.
System.out.println("My bagel is: " + myBagel.getDescription());
// The output should be:
// **My bagel is: a plain bagel with cheese, bacon and eggs**
}
/**
* A plain bagel class which has a final method which we want to override
*/
public static class Bagel {
/**
* return a description for this bagel
*/
public final String getDescription() {
return "a plain bagel";
}
}
/**
* A sub class of bagel which adds some extra options for the bagel.
*/
public static class BagelWithOptions extends Bagel {
/**
* A string that will contain any extra options for the bagel
*/
String options;
/**
* Initiate the bagel with no extra options
*/
public BagelWithOptions() {
options = "nothing else";
}
/**
* Set the options for the bagel
* #param options - a string with the new options for this bagel
*/
public void setOptions(String options) {
this.options = options;
}
/**
* return the current options for this bagel
*/
public String getOptions() {
return options;
}
}
}
you could create another method which you could override in your test:
public class Bar extends Foo {
protected Object doGetX() {
return getX();
}
public int process(){
Object value = doGetX();
...
}
}
then, you could override doGetX in BarTest.
Seb is correct, and just to ensure that you get an answer to your question, short of doing something in native code (and I am pretty sure that would not work) or modifying the bytecode of the class at runtime, and creating the class that overrides the method at runtime, I cannot see a way to alter the "finalness" of a method. Reflection will not help you here.
If your unit test case can't create Foo due to other dependencies, that might be a sign that you're not making your unit test right in the first place.
Unit tests are meant to test under the same circumstances a production code would run, so I'd suggest recreating the same production environment inside your tests. Otherwise, your tests wouldn't be complete.
If the variable returned by getX() is not final you can use the technique explained in What’s the best way of unit testing private methods? for changing the value of the private variable through Reflection.
public class Bar extends Foo{
public int process(){
Object value = getX();
return process2(value);
}
public int process2(Object value){
...
}
}
public class BarTest extends TestCase{
public testProcess(){
Bar bar = new Bar();
Mockobj mo = new Mockobj();
int result = bar.process2(mo);
...
}
}
what i did eventually was the above. it is a bit ugly... James solution is definitely much better than this...

Categories

Resources