I currently have two classes that I create objects from. I need an array that will store references (pointers) to these objects. Of what type should the array be?
ArrayList<Class1> visableObjs = new ArrayList<Class1>();
Will of course only store pointers to objects that stem from Class1. If I had an object from Class2 could I store it's pointer in the same array?
if you mean that the objects you store are instances of those two classes, you should make those classes inherit from a (custom?) class or interface and use that class/interface as the type to store in your array.
We can do like this. Its not good practice at all if objects are from different classes.
ArrayList<Object> visableObjs = new ArrayList<Object>();
or
ArrayList visableObjs = new ArrayList();
You could perhaps use generics to create a Choice class to hold a reference to one or other type, but not both:
public final class Choice<A,B> {
private final A a;
private final B b;
private final boolean isA;
private Choice(A a, B b, boolean isA) {
this.a = a; this.b = b; this.isA = isA;
}
public static <A,B> Choice<A,B> ofA(A a) {
return new Choice<>(a, null, true);
}
public static <A,B> Choice<A,B> ofB(B b) {
return new Choice<>(null, b, false);
}
public boolean isA() { return isA; }
public A getA() {
if(!isA) throw new IllegalStateException("Not a!");
return a;
}
public boolean isB() { return !isA; }
public B getB() {
if(isA) throw new IllegalStateException("Not b!");
return b;
}
// Purely for demo purposes...
public static void main(String[] args) {
Choice<Integer,String> ich = Choice.ofA(42);
Choice<Integer,String> sch = Choice.ofB("foo");
// This is why the isA is included; so we can tell a null A from a null B.
Choice<Integer,String> nil = Choice.ofA(null);
//
List<Choice<Boolean,String>> xs = new ArrayList<Choice<Boolean,String>>();
xs.add(Choice.ofA(true));
xs.add(Choice.ofB("neep"));
}
}
This should work for two unrelated classes. Or for two out of many related subclasses, where you want to restrict to only those two possibilities - and not any subclass of a more general class/interface.
Such a class should probably be extended to properly implement equals()/hashCode(), toString(), etc. (For some definition [documented] of 'properly'.)
Caveat: this may not compile first try - I don't have a javac handy to test it. But the idea should be clear.
Related
I am using DI to pass around my dependencies. But in some scenarios we need to create objects dynamically and do need to provide parameters during initialization. Code sample -a tries to explain the scenario.
In order to initialize such type of objects and hide new operator, I created simple factories. Code sample -b.
Code sample -a
int are used for simplicity they will/can actually be some real objects
public class Sample {
private final int c;
public Sample(int c){
this.c = c;
}
public void doSomething(SomeCommand command, Request request, Context context){
DynamicDependency dynamicDependency = new DynamicDependency(command.getA(), command.getB(), c);
dynamicDependency.doSomeWork(request, context);
}
}
class DynamicDependency{
private final int a;
private final int b;
private final int c;
public DynamicDependency(int a, int b, int c){
this.a = a;
this.b = b;
this.c = c;
}
public void doSomeWork(Request request, Context context){
/*
Do work
*/
}
}
class SomeCommand {
private int a;
private int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
Code sample -b
public interface IParameterizedObjectFactory<T> {
T getInstance(Object... arguments) throws ClassCastException;
}
public class DynamicDependency implements IParameterizedObjectFactory<DynamicDependency> {
#Override
public DynamicDependencyFactory getInstance(Object... arguments) throws ClassCastException {
Validate.notNull(arguments);
if(arguments.length > 0){
final int a = (Integer) arguments[0];
final int b = (Integer) arguments[1];
final int c = (Integer) arguments[2];
return new DynamicDependency(a, b,c);
}
return null;
}
}
This does the job as I can now inject factory and then use it to get the new object as:
DynamicDependency dynamicDependency = dynamicDependencyFactory.getInstance(a,b,c);
Question(s):
Though, it does the job but we need to pass around list of Object[s] and and we loose strong typing. Casting also will eat up some execution time. How can it be improved?
Another approach could be to not to use the interface at all and use concrete classes which have getInstance method with appropriate parameter list. Sounds reasonable to me.
public class DynamicDependencyFactory {
public DynamicDependency getInstance(int a, int b, int c) {
return new DynamicDependency(a, b,c);
}
}
What else can be done to hide new? Or should I use second approach to create concrete factories?
Note: I am trying to stay away from reflection
The second approach you suggested is much better than the first. You still have the option to extract an interface from that factory if required:
public interface IDynamicDependencyFactory {
DynamicDependency getInstance(int a, int b, int c);
}
Note the lack of generic type parameters. Your first suggestion of the following interface:
public interface IParameterizedObjectFactory<T> {
T getInstance(Object... arguments) throws ClassCastException;
}
seems completely unnecessary according to your example, and, as you have noted, the Object[] as the arguments makes it a very unpleasant and non-type safe API to work with.
If you really need to pass different argument types to the methods on the factory, then define an overload for each valid signature instead of just accepting an Object[]:
public interface IDynamicDependencyFactory {
DynamicDependency getInstance(int a, int b, int c);
DynamicDependency getInstance(double a, int b, BigDecimal c);
}
Better yet, if you can refactor your code so that it does not require such a factory then that could be beneficial (unless you do not have access to the Request and Context objects at the same time as the a, b, and c int values). For example, you can pull up the constructor arguments to be method parameters and treat your DynamicDependency more like a service (or singleton):
class DynamicDependencyService {
public void doSomeWork(Request request, Context context, int a, int b, int c){
//Do work
}
}
This way, an instance of DynamicDependencyService can be passed to your Sample object via the constructor.
I decided to go with a mixed approach, using factories where I do not have control on the runtime object being created and passing runtime data via methods where the control is with me.
Steven shared couple of good articles in the comments, posting here.
Factories are a code smell
runtime values should not be injected into a component's constructor
Fortunately I was already avoiding the constructor injection in case of runtime values. The problem was with the legacy code and the code which is not owned by our team. For now, for the code which is not owned by us we have to use constructor even though it will smell a bit :)
When I want to return a ArrayList of C2, it's not possible, because the return types are incompatible.
package a;
class C1 {
private final ArrayList<C2> c2s = new ArrayList<C2>();
protected ArrayList<C2> getC2() { return c2s; }
}
class C2 {}
package b;
class C1 extends a.C1 {
private final ArrayList<C2> c2s = new ArrayList<C2>();
#Override
protected ArrayList<C2> getC2() { return c2s; } // won't work
}
class C2 extends a.C2 {}
Update: Why doesn't this work, when following works (in a.C1 and b.C1):
private final C2 c2 = new C2();
public C2 getC2() { return c2; }
You've got two different C2 classes - an ArrayList<a.C2> isn't the same as an ArrayList<b.C2>. They're incompatible to avoid this sort of thing:
ArrayList<b.C2> listB = new ArrayList<b.C2>();
ArrayList<a.C2> listA = listB; // This is invalid...
listA.add(new a.C2());
b.C2 firstElement = listB.get(0); // To stop this from causing problems.
That has nothing to do with overriding, it's just normal generics. You could change your declaration in a.C1 to:
protected ArrayList<? extends C2> getC2() { return c2s; }
Then it would work, because the types will be compatible. That prevents the above abuse because you can't call add on an ArrayList<? extends a.C2>.
As an aside, I would strongly discourage you from having class names which are only distinguished by package. It's a recipe for unreadable code and painful debugging sessions. It's also a recipe for hard-to-read questions, so if your real code doesn't use this nasty naming scheme, please don't make your sample code use it either.
I'm working with the Java AWS API to monitor some EC2 instances and on every refresh I need to query the service which returns a bunch of Instance objects (freshly constructed). I want to extend the functionality of these objects, I figure I can maintain a map of MyInstance objects which can be refreshed with the new Instances on each poll.
Now I could easily do this with a simple wrapper class that holds the original Instance as a property the issue is I would like to keep access to the base Instance API as I already use these functions in my code. Would it be possible to replace only the super-class parts of an instantiated object? Contrived example of what I'm going for:
class Instance {
protected int prop;
public Instance(int prop) {
this.prop = prop;
}
}
class MyInstance extends Instance {
protected int prop2;
public MyInstance(int prop, int prop2) {
super(prop);
this.prop2 = prop2;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.prop == 3
Obviously this example would be trivial to transform but in my actual case there are far more properties that need to be transferred. Can Reflection do this? What kind of performance impact am I looking at if I use Reflection for 10 of these every second? Thanks for reading!
The best solution is to combine both your ideas:
Wrap the original Instance in a class that extends the Instance class. (In the constructor of the child class, you can create a new Instance object and set it)
Delegate all methods to the wrapped instance (and add new properties)
In your foster method, you simply change the wrapped Instance.
class Instance {
private int prop;
public Instance(int prop) {
this.prop = prop;
}
public int getProp() {
return prop;
}
}
class MyInstance extends Instance {
private Instance delegate;
private int prop2;
public MyInstance(Instance delegate, int prop2) {
super(prop);
this.delegate = delegate;
this.prop2 = prop2;
}
#Override
public int getProp() {
return delegate.getProp();
}
public int getProp2() {
return prop2;
}
public void foster(Instance i) {
delegate = i;
}
}
MyInstance foo = new MyInstance(1, 2);
Instance foster = new Instance(3);
//what i want to do
foo.adoptedBy(foster);
//with the result that foo.getProp() == 3
This question already has answers here:
Is there a way to simulate the C++ 'friend' concept in Java?
(18 answers)
Closed 8 years ago.
How does one implement the friend concept in Java (like C++)?
Java does not have the friend keyword from C++. There is, however, a way to emulate that; a way that actually gives a lot more precise control. Suppose that you have classes A and B. B needs access to some private method or field in A.
public class A {
private int privateInt = 31415;
public class SomePrivateMethods {
public int getSomethingPrivate() { return privateInt; }
private SomePrivateMethods() { } // no public constructor
}
public void giveKeyTo(B other) {
other.receiveKey(new SomePrivateMethods());
}
}
public class B {
private A.SomePrivateMethods key;
public void receiveKey(A.SomePrivateMethods key) {
this.key = key;
}
public void usageExample() {
A anA = new A();
// int foo = anA.privateInt; // doesn't work, not accessible
anA.giveKeyTo(this);
int fii = key.getSomethingPrivate();
System.out.println(fii);
}
}
The usageExample() shows how this works. The instance of B doesn't have access to the private fields or methods of an instance of A. But by calling the giveKeyTo(), class B can get access. No other class can get access to that method, since it a requires a valid B as an argument. The constructor is private.
The class B can then use any of the methods that are handed to it in the key. This, while clumsier to set up than the C++ friend keyword, is much more fine-grained. The class A can chose exactly which methods to expose to exactly which classes.
Now, in the above case A is granting access to all instances of B and instances of subclasses of B. If the latter is not desired, then the giveKeyTo() method can internally check the exact type of other with getClass(), and throw an exception if it is not precisely B.
Suppose A.foo() should only be called by B. This can be arranged by a token that can only be generated by B.
public class B
{
public static class ToA { private ToA(){} }
private static final ToA b2a = new ToA();
void test()
{
new A().foo(b2a);
}
}
public class A
{
public void foo(B.ToA b2a)
{
if(b2a==null)
throw new Error("you ain't B");
// ...
}
}
Only B can generate a non-null B.ToA token. If both A and B do not leak this token to the 3rd party,
nobody else can invoke A.foo()
If A2 wants to friend B too, it needs a different token type. If it's the same token type, since A got a token of the type from B, A can pretend to be B to A2.
The check is done at runtime, not compile time, that is not perfect. Not a big deal though, since any 3rd party can only invoke A.foo() with a null, it can't be an innocent mistake which we want to check at compile time; it's probably malicious so we don't care to warn the caller at compile time.
In Java you can put both (or more) classes into the same package. All methods and fields with the protected qualifier can directly be accessed by all classes in that package.
I figured out another way to achieve the same. Basically you check the fully qualified name of the invoking class name. If it matches your "friend" function, then you give access, else you return null.
public class A {
private static int privateInt = 31415;
public static int getPrivateInt() {
if(Throwable().getStackTrace()[1].getClassName().equals(new String("example.java.testing.B")))
{
return privateInt;
}
else
{
return null;
}
}
}
package example.java.testing;
public class B {
public void usageExample() {
int foo = A.getPrivateInt; // works only for B
System.out.println(foo);
}
}
Ive been searching for a robust way to compare my objects, I came across the ObjectUtils , and had the immidiate doubt that would it be able to compare it efficiently or not as I do not know how it works internally and documentation on apache org site about this is scarce.
Can someone please help me with this??
EDIT:
When I say compare , all I really need to to compare for equality of MYOBJ, where MYOBJ is a custom object I have defined , which has various variables in it(all these vars are primitive data types like int,long,float String which can be compares in a straightforward manner if they are not null), but this might change in the future.
I was not sure would BeanUtils.areEqual method be able to handle such a case and what if I include my own datatypes(non -primitives) inside this MYOBJ.
Thanks
Your Question is very vague, I don't really know what you are talking about, so I'll go in several Directions.
"compare my Objects" can mean several things. In Java, this usually means comparing them for sorting, i.e. through the Comparable / Comparator interfaces. While ObjectUtils does provide a null-safe compare method, it won't help you beyond that. What you need is either a custom Comparator or for your objects to implement Comparable. CompareToBuilder can help you with both, to a certain extent:
public class SomeBean implements Comparable<SomeBean>{
private String foo;
private int bar;
private List<String> baz;
public int compareTo(SomeBean other) {
return new CompareToBuilder()
.append(foo, other.foo)
.append(bar, other.bar)
.append(baz, other.baz)
.toComparison();
}
}
If, on the other hand, you want to compare the properties of different object types, then you are looking in the totally wrong direction. Have a look at Commons / BeanUtils instead. Sample code:
public class BeanUtilsTester {
public static class Foo{
private String foo="foo";
public String getFoo() {return foo;}
public void setFoo(String foo) {this.foo = foo;}
private Integer bar=123;
public Integer getBar() {return bar;}
public void setBar(Integer bar) {this.bar = bar;}
private List<String> squoggle=Arrays.asList("abc","def");
public List<String> getSquoggle() {return squoggle;}
public void setSquoggle(List<String> squoggle) {this.squoggle = squoggle;}
}
public static class Bar{
private String foo="bar";
public String getFoo() {return foo;}
public void setFoo(String foo) {this.foo = foo;}
private Integer bar=456;
public Integer getBar() {return bar;}
public void setBar(Integer bar) {this.bar = bar;}
private String[] fiddle=new String[]{"abc","def"};
public String[] getFiddle() {return fiddle;}
public void setFiddle(String[] fiddle) {this.fiddle = fiddle;}
}
public static void main(String[] args) throws Exception{
Foo foo = new Foo();
Bar bar = new Bar();
Map<String,Object> fooProps = BeanUtils.describe(foo);
Map<String,Object> barProps = BeanUtils.describe(bar);
fooProps.keySet().retainAll(barProps.keySet());
BeanUtils.populate(bar, fooProps);
assertEquals(foo.getFoo(),bar.getFoo());
assertEquals(foo.getBar(), bar.getBar());
}
}
And if you just want to implement equals() correctly, look at EqualsBuilder:
#Override
public boolean equals(Object obj) {
if (obj instanceof SomeBean) {
SomeBean other = (SomeBean) obj;
return new EqualsBuilder()
.append(foo, other.foo)
.append(bar, other.bar)
.append(baz, other.baz)
.isEquals();
}
return false;
}
ObjectUtils will work just fine with comparing user defined objects. Of course you'll need to implement the Comparable interface in any object that you'd like to compare using the library functions.
Just made a simple test
User user1 = new User();
User user2 = new User();
Assert.assertEquals(true,ObjectUtils.equals(user1, user2));
The test here displays false. It's not equal.
User user1 = new User();
User user2 = user1;
Assert.assertEquals(true,ObjectUtils.equals(user1, user2));
The previous test displays true.
I believe you want to test similarly like the first test without changing the user defined class. If I am right, you can't use this library to do comparison.
However if you implement the compare() method in the every bean that you want to compare, I believe you are able to use this.