Using existing instance if constructed with same values - java

I have to create a class/constructor which allows the following:
Object a = new Object("test");
Object b = new Object("test");
a == b // should be true
So Object a and b should not only be the same according to their values but also should use the same reference and reference the same memory.
The constructor should find out if an instance with the given values already exists and if yes just take the reference and point it to the existing object.
Is there some way to get all created instance of a specific class?
Can someone give me a short hint where to start? I have no idea...

This isn't possible using plain constructors, as these always entail a memory allocation. Typically, you would use a static factory method in order to have better control over object creation.

Use something similar to the Singleton pattern, but with an Object pool of its own type as a data member, and then go through getInstance() to make new instances. Within getInstance(), check the pool for matching Object already existing, and if so, just pull a reference to hand back; if not, call the private constructor to make a new one, add it to the pool, and then return it.
public class A {
static ArrayList<A> existingAs =new ArrayList<>();
private String val;
private A(String value)
{
this.val=value;
}
public A getInstance(String value)
{
A newA=null;
for(A a: existingAs)
{
if(a.getVal().equals(value))
return a;
}
newA=new A(value);
existingAs.add(newA);
return newA;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
}

new always creates a new instance. You could use a static factory method which internally pools the instances.

Related

Best Way to collect complex logging objects during task execution

I would like to discuss different ways to collect data that occurs during execution of (a lot) java code, that is not needed to proceed but shall be stored. Additional difficulty in my situation, storing the side Objects needs another object that would otherwise be unneccessary in all the sub methods.
Basically I have one class (TaskExecutor) delegating a coplex task to another component (Delegate). One Object (ImportantObject c) is only necessary to save the side objects (List<Hint>). These hints are not necessary to proceed task execution and are only for logging complex data to my database. But they are linked to this ImportantObject c.
#Component
public class TaskExecutor {
#Autowired
private Delegate delegate;
public void execute() {
Object a = new Object();
Object b = new Object();
ImportantObject c = new ImportantObject(); // only needed to save hints
Object result = delegate.performTask(a, b);
}
}
public class Delegate {
public Object performTask(Object a, Object b) {
method1(a);
Object result2 = method2(a);
Object result3 = method3(a, b, result2);
return result3;
}
private void method1(Object a) {
new Hint();
}
private Object method2(Object a) {
new Hint();
return new Object();
}
private Object method3(Object a, Object b, Object result2) {
new Hint();
return new Object();
}
}
public class DbService {
public void saveHints(List<Hint> hints, ImportantObject c) {
// How to call this?
}
}
What would be a nice codestyle solution for this problem?
Idea 1: Pass object everywhere
Trivial would be passing Object c into the TaskExecution and all its submethods, so I can save a Hint right when it occurs. Would work but I feel like its bad style.
private Object method3(Object a, Object b, Object result2, ImportantObject c) {
dbService.saveHint(new Hint(), c);
return new Object();
}
Idea 2: Pass List everywhere
I could also pass a list everywhere to collect the Hints. So I would have to only have to bring this list and ImportantObject c together. Also feels like bad coding style.
public class TaskExecution {
public Object performTask(Object a, Object b) {
List<Hint> hints = new ArrayList<>();
method1(a, hints);
Object result2 = method2(a, hints);
Object result3 = method3(a, b, result2, hints);
return result3;
}
Idea 3: Use some cache
I thought about putting the Hints to a cache and read them in the TaskExecutor. However if I don't cache them linked to the instance of ImportantObject c they loose their meaning. I could not determine if an object from cache is linked to my current instance of ImportantObject.
Idea 4: field variable (if no Spring)
If I wouldn't use spring and would always create a new instance of Delegate this would be a solution
public class Delegate {
private List<Hint> hints = new ArrayList<>();
// ...
}
But, well... Spring is there for a reason :-)

Static Factory Method is creating a new object everytime its invoked

In Effective Java its mentioned that "Unlike constructors static factory methods are not required to create a new object each time they're invoked".
class Car{
String color;
Boolean spoiler;
public Car(String s){
color=s;
spoiler = false;
}
public static Car redCar(){
return new Car("red");
}
}
In Main Class:
Car c2 = Car.redCar();
Car c3 = Car.redCar();
c2 and c3 are different objects. I did not get the context of "not required to create a new object each time invoked".
Because that's what you do:
public static Car redCar(){
return new Car("red");
}
// ^ here
If you want to return the same value you can do something like:
private static final Car RED_CAR = new Car("red");
public static Car redCar(){
return RED_CAR;
}
The point is that calling new Car() will always return a new instance. Calling Car.newInstance() means that the Car class can decide what to do.
For example:
private static final Map<String, Car> CARS = new HashMap<>();
public static Car newInstance(final String colour){
return CARS.computeIfAbsent(colour, Car::new);
}
This uses the Car constructor as a method reference to the new Map.computeIfAbsent method, which calls it if a Car of that colour is not already present in the Map. This is a naive (not threadsafe) cache implementation.
So:
final Car one = Car.newInstance("red");
final Car two = Car.newInstance("red");
System.out.println(one == two) // true
"Unlike constructors static factory methods are not required to create a new object each time they're invoked". This does not mean calling a static factory method will necessarily return the same object (as your example shows), only that it may (unlike a constructor).
You could, e.g., implement redCar() differently so it always returns the same object:
class Car{
/* snipped */
private static final RED = new Car("red");
public static Car redCar(){
return RED;
}
}
As in everything, programs do exactly what you ask them to do. If your static method uses "new" each time when it is called; then you create new object each time.
What is meant by unlike constructors static factory methods are not required to create a new object each time they're invoked" is the fact that your code can decide to not call new; but for example return a "cached" object.
Meaning: when you use "new"; you call constructors; and the semantics of Java lead to the creation of a new object. There is no way preventing had, it is hardwired into the language.
But when you use static methods, you define the semantics of that method.
Maybe cars are not the best example, but consider a requirement that says that your factory should produce only one car per color. You would implement it like this (omitting unnecessary attributes):
class Car {
String color;
public Car(String color) {
this.color = color;
}
public static Car car(String color) {
Car car = CARS.get(color);
if (car != null) return car;
car = new Car(color);
CARS.put(color, car);
return car;
}
private static final Map<String, Car> CARS = new HashMap<>();
}
Have a look at the Integer class and its factory method valueOf. Additionally, such a factory method is useful for singletons (although they have their own caveats).
Here you are creating new objects,
return new Car("red");
Static factory methods will be used to create object once for the first time and then return same instance next time when returned from static factory methods.
Factory's job is to create an object. If you don't want to expose how the object is created, you hide the creation under factory.
Lately I have happened to work on a use case where the concept of singleton is defined based on some added restrictions. E.g., All File objects that capture file1.txt are singleton (or are same object). Similarly File objects that capture file2.text are singleton. However File objects that capture file1.text and file2.text are different.
For this to work, create a static global list that add your so called static objects (e.g., based on file name). If you don't want Singleton (again file based) objects to add to this list override equals.
Now if someone asks the factory to give you an object that matches what you specified in equals (what ever parameters make two objects equal), search the global list and if that object exists return it, else create a new object, add it to the list and then return the object.
The moral of the story is, yo don't have to return new objects from factory. You can bend Singleton to your need (if you don't need pure Singleton). And by using static factory method, one can call ClassName.factory without having to instantiate it.
The idea Bloch describes is that a static factory can use a pool or cache of instances that it passes when requested or decide on its inner logic to create a new instance (which may make into the cache too). This usually works only for immutable objects as otherwise you'd have some hard-to-track cross object effects.
The implementation you have given is not a static factory. You have make the class as below:
class Car{
String color;
Boolean spoiler;
public static final Car car = new Car("name");
public Car getInstance(){
return car;
}
private Car(String s){
color=s;
spoiler = false;
}
public static Car redCar(){
return new Car("red");
}
}
and then in main you have to call
Car.getInstance();

Does modifying the result of a getter affect the object itself?

I have a question about using getter methods in java.
Suppose I had this class:
class Test {
private ArrayList<String> array = new ArrayList<String>();
public ArrayList getArray() {
return this.array;
}
public void initArray() {
array.add("Test 1");
array.add("Test 2");
}
}
class Start {
public static void main(String args[]) {
initArray();
getArray().remove(0);
}
}
My question is:
Would the actual arraylist object be modified ("Test 1" removed from it)? I think I have seen this in places, but I thought that getters were simply providing a copy of that object. Not a reference to it. If it did work that way (as a reference), then would this work as well (Would the arraylist object of the class Test be altered by this as well)?:
class Start {
public static void main(String args[]) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
}
}
Java returns references to the Array, so it won't be a copy and it will modify the List. In general, unless its a primitive type (int,float,etc) you will be getting a reference to the object.
You have to explicitly copy the array yourself if you want a duplicate to be returned.
The way I understand it, Object reference variables are little more than memory addresses of the objects themselves. So what is returned from getArray() is a reference variable to that ArrayList. An object may have many reference variables, but it is still the same object that gets modified.
Java does everything pass by value. So anytime you pass an object reference variable as a parameter or return it's value, you are passing or returning the value of the object reference variable.
As others said, unless it's a primitive type, you get a reference to the object. It is similar to a pointer in C++, it allows you to access the object, but unlike C++ reference (pointer to the memory address of a variable) it doesn't allow you to replace it with another object. Only setter can do that.
I see two variants in your question, test.getArray().remove(0) and aVar.remove(0). There is no difference in the results of those, it's still just some pointer-like reference and it modifies the original.
You never get a clone by just calling a getter, so unless the object is immutable, you can modify the object that the getter gave you access to. For example, String is immutable, any basic Collection (including ArrayList) is mutable. You can call Collections.unmodifiable*(...) to make a collection unmodifiable. However, if the items of collection are mutable, they can still be changed.
In some cases, getting a clone is a good idea, in most cases it's not. A getter shouldn't clone anything at all, it shouldn't even modify data unless it initializes a possibly null collection or something like that. If you want an unmodifiable collection containing immutable objects, try to do it this way. In this example we have a class FooImpl that implements interface Foo, the reasons to be explained later.
public interface Foo {
int getBar();
}
public class FooImpl Foo {
private int bar;
#Override
public int getBar() {
return bar;
}
public void setBar(int newValue) {
this.bar = newValue;
}
}
As you see, Foo has no setter. If you create some ArrayList<Foo> and pass it from some getter as Collections.unmodifiableList(myArrayList), it almost seems you did it. But the work is not done yet. If the class FooImpl is public (which it is in this case), someone might try if that foo he found in the list is an instanceof FooImpl and then cast it as (FooImpl) foo making it mutable. However, we can wrap any Foo into a wrapper called FooWrapper. It implements Foo as well:
public class FooWrapper implements Foo {
private Foo foo;
public FooWrapper(Foo foo) {
this.foo = foo;
}
public int getBar() {
return foo.getBar();
}
// No setter included.
}
Then we can put a new FooWrapper(myFoo) into a Collection<FooWrapper>. This wrapper doesn't have any public setter and the foo inside is private. You cannot modify the underlying data. Now about that Foo interface. Both FooImpl and FooWrapper implement it, if any method doesn't intend to modify the data, it can ask for Foo on input. It doesn't matter which Foo you get.
So, if you want unmodifiable collection containing unmodifiable data, make a new Collection<Foo>, feed it with FooWrapper objects and then call Collections.unmodifiable*(theCollection). Or make a custom collection that wraps the whole collection of Foo, returning FooWrappers, for example this list:
public MyUnmodifiableArrayList implements List<Foo> {
ArrayList<Foo> innerList;
public get(int index) {
Foo result = innerList.get(index);
if (!(result instanceof FooWrapper)) {
return new FooWrapper(result);
}
return result; // already wrapped
}
// ... some more List interface's methods to be implemented
}
With wrapped collection, you don't have to iterate through the original collection and make its clone with wrappers of data. This solution is much better when you don't read it whole, but it creates a new FooWrapper every time you call get() on it, unless the Foo on that index is already a FooWrapper. In a long running thread with millions of calls to get(), this could become an unnecessary benchmark for the garbage collector, making you use some inner array or map containing already existing FooWrappers.
Now you can return the new, custom List<Foo>. But again, not from a plain getter. Make it something like getUnmodifiableFooList() for your private ArrayList<FooImpl> fooList field.
As pointed out, your getter does not modify the list, it returns an modifiable reference to the list. Tools like Findbugs will warn you about that... you may either live with that and trust the users of your class to not clobber your list, or use this to return an unmodifiable reference to your list:
public static List<String> getArray() {
return Collections.unmodifiableList(array);
}
To answer your question, with a getter you get direct access to a variable.
Run this code and you can see that the String in the ArrayList is removed. But don't use a static ArraList like in this example in your code.
public class Test {
private static ArrayList<String> array = new ArrayList<String>();
public static ArrayList<String> getArray() {
return array;
}
public static void initArray() {
array.add("Test 1");
array.add("Test 2");
}
public static void main(String[] args) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
System.out.println(aVar.size());
}
}
That a getter does not modify the object you call it upon is purely a matter of convention. It certainly does not change the target's identity, but it can change its internal state. Here's a useful example, if a bit sketchy:
public class Fibonacci {
private static ConcurrentMap<Integer, BigInteger> cache =
new ConcurrentHashMap<>();
public BigInteger fibonacci(int i) {
if (cache.containsKey(i)) {
return cache.get(i);
} else {
BigInteger fib = compute(i); // not included here.
cache.putIfAbsent(i, fib);
return fib;
}
}
So, calling Fibonacci.fibonacci(1000) may change the internal state of the target, but it's still the same target.
Now, here's a possible security violation:
public class DateRange {
private Date start;
private Date end;
public DateRange(final Date start, final Date end) {
if (start.after(end)) {
throw new IllegalArgumentException("Range out of order");
}
this.start = start;
this.end = end;
}
public Date getStart() {
return start;
}
// similar for setStart, getEnd, setEnd.
}
The problem is that java.lang.Date is mutable. Someone can write code like:
DateRange range = new DateRange(today, tomorrow);
// In another routine.
Date start = range.getStart();
start.setYear(2088); // Deprecated, I know. So?
Now range is out of order. It's like handing the cashier your wallet.
This is why it is best to do one of these, the earlier ones being preferable.
Have as many objects as possible be immutable. This is why Joda-Time was written, and why dates will chnage yet again in Java 8.
Make defensive copies of items one sets or gets.
Return an immutable wrapper of an item.
Return collections as iterables, not as themselves. Of course, someone might cast it back.
Return a proxy to access the item, that can't be cast to its type.
I know, I know. if I want C or C++, I know where to find them.
1. Return

Share a single instance of an object if fields are the same

I am familiar with static variables and singletons, but I haven't seen any information on this:
public class MyImmutableClass {
private final String string;
public static final MyImmutableClass getInstance(String s) {
if( a MyImmutableClass already exists with that string as its field)
return (that instance);
else
return a new instance;
}
...
}
No duplicates of MyImmutableClass could exist. Does this make sense and if so, how would you implement this?
public final class MyImmutableClass {
private MyImmutableClass(){}
private final String string;
private static Map<String,MyImmutableClass> map = new WeakHashMap<String,MyImmutableClass>();
public static final MyImmutableClass getInstance(String s) {
if(map.containsKey(s))
return (map.get(s));
else{
MyImmutableClass temp = new MyImmutableClass(s);
map.put(s,temp);
return temp;
}
}
...
}
Something like this should work for you.
This is called the flyweight pattern.
The simplest implementation is to:
implement hashCode() and equals() that agree
use a Map of your key to your class to determine if you've already got one and to store the instances
I think what you're looking for is the Static Factory Pattern, not the Singleton pattern. There's lots of examples of this in the Java classes themselves. For example, if you call the method Integer.valueOf(myString); it may be doing something similar. If you pass in "1" over and over again, it may return the same Integer object every time.
You would need to keep e.g. a Set containing the objects you might reuse. The main complication is that, if it were done naively, you would prevent garbage collection.
Consider using a WeakHashMap so that your references can be dropped automatically.
In the case you give, you would map a String to the object.

Why can final object be modified?

I came across the following code in a code base I am working on:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
...
INSTANCE is declared as final. Why can objects be added to INSTANCE? Shouldn't that invalidate the use of final. (It doesn't).
I'm assuming the answer has to do something with pointers and memory but would like to know for sure.
final simply makes the object reference unchangeable. The object it points to is not immutable by doing this. INSTANCE can never refer to another object, but the object it refers to may change state.
Being final is not the same as being immutable.
final != immutable
The final keyword is used to make sure the reference is not changed ( that is, the reference it has can't be substituted with a new one )
But, if the attribute is self is modifiable it is ok to do what you have just described.
For instance
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
If we instantiate this class, we won't be able to assign other value to the the attribute someFinalObject because it is final.
So this is not possible:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
But if the object it self is mutable like this:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Then, the value contained by that mutable object may be changed.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal ); // prints 3
This has the same effect that your post:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Here you are not changing the value of INSTANCE, your are modifying its internal state ( via, providers.add method )
if you want to prevent that the class definition should be changed like this:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
// Avoid modifications
//public static void addProvider(ConfigurationProvider provider) {
// INSTANCE.providers.add(provider);
//}
// No mutators allowed anymore :)
....
But, it might not make much sense :)
By the way, you also have to synchronize access to it basically for the same reason.
The key to the misunderstanding is in your question's title. It's not the object which is final, it's the variable. The variable's value can't change, but the data within it can.
Always remember that when you declare a reference type variable, the value of that variable is a reference, not an object.
final just means the reference can't be changed. You can't reassign INSTANCE to another reference if it's declared as final. The internal state of the object is still mutable.
final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;
would throw a compilation error
Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if a final variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.
Source
Here's a guide on making an object immutable.
Final and immutable are not the same thing. Final means the reference cannot be reassigned so you can't say
INSTANCE = ...
Immutable means that the object itself cannot be modified. An example of this is the java.lang.String class. You cannot modify the value of a string.
Java doesn't have the concept of immutability built into the language. There is no way to mark methods as a mutator. Therefore the language has no way to enforce object immutability.

Categories