Cloning an object defined by inner class - java

I have this vector that I am defining as an instance variable and also as an inner class:
private Vector<MATIdentifier> matIds = new Vector<MATIdentifier>(){
#Override
public boolean add(MATIdentifier mi){
if(this.contains(mi)){
return false;
}
super.add(mi);
return true;
}
#Override
public boolean contains(Object o){
if(o instanceof MATIdentifier){
for(MATIdentifier mi: this){
if(mi.getIdValue().equals(((MATIdentifier)o).getIdValue())){
return true;
}
}
}
return false;
}
};
Later on in the program, I want to populate this vector from the database. And it would be better to create a new instance of this Vector class, as opposed to simply removing all the elements and reusing the same object - I suppose I could do that, but I still want to know about cloning the object.
The only way I know how to do this would be to clone() this object. Is this safe? Will it clone the overridden methods add(MATIdentifier) and contains(Object) ?
Maybe I should override clone() also...? Or is the predefined clone() method in Vector sufficient?
Note: I put the #Override annotations in myself, the Java compiler (Eclipse) did not make me do that for some reason.

This question deals with several concepts in Java.
Firstly, I'd like to ask why, if you want to guarantee uniqueness, you aren't using a java.util.Set?
Next, the clone method. Is the clone a shallow copy or a deep copy of the original data structure? If we look at the Vector API documentation from Oracle, it tells us:
Returns a clone of this vector. The copy will contain a reference to a
clone of the internal data array, not a reference to the original
internal data array of this Vector object.
So we can learn from this that, firstly, it also clones the internal data, so this suggests a deep copy. Now, does it also copy the overridden methods? A quick test of this tells me that, yes, it does.
Finally, how to test this? I suggest you use a unit testing framework like junit.
Following is an example of how to use this framework to ensure your assumptions are correct:
package test.good;
import static org.junit.Assert.*;
import java.util.Vector;
import org.junit.Before;
import org.junit.Test;
public class CloneTest {
private Vector<MATIdentifier> matIds;
MATIdentifier id1 = new MATIdentifier("first");
MATIdentifier id2 = new MATIdentifier("second");
MATIdentifier id3 = new MATIdentifier("third");
MATIdentifier idDuplicate = new MATIdentifier("first");
#Before
public void prepare() {
matIds = new Vector<MATIdentifier>() {
#Override
public boolean add(MATIdentifier mi) {
if (this.contains(mi)) {
return false;
}
super.add(mi);
return true;
}
#Override
public boolean contains(Object o) {
if (o instanceof MATIdentifier) {
for (MATIdentifier mi : this) {
if (mi.getIdValue().equals(((MATIdentifier) o).getIdValue())) {
return true;
}
}
}
return false;
}
};
}
private void populateVector(Vector<MATIdentifier> vector) {
vector.add(id1);
vector.add(id2);
vector.add(id3);
}
/**
* Tests that adding new values returns true, and adding duplicates returns
* false, and that the duplicates are not actually added
*/
#Test
public void testDuplicateFails() {
boolean added;
added = matIds.add(id1);
assertTrue(added);
added = matIds.add(id2);
assertTrue(added);
added = matIds.add(idDuplicate);
assertFalse(added);
assertEquals(2, matIds.size());
}
#Test
public void testDeepCopy() {
// Start with by pupulating our customized vector
populateVector(matIds);
assertEquals(3, matIds.size());
// Clone the vector
Vector<MATIdentifier> clone = (Vector<MATIdentifier>) matIds.clone();
assertEquals(3, clone.size());
// remove something from the original
matIds.remove(2);
assertEquals(3, clone.size());
assertEquals(2, matIds.size());
// add something to the original
matIds.add(new MATIdentifier("New Value"));
assertEquals(3, clone.size());
assertEquals(3, matIds.size());
// add a duplicate to the clone, to ensure that the overridden behavior
// is present in the clone
boolean added = clone.add(id1);
assertFalse(added);
}
}
class MATIdentifier {
private String idValue;
public MATIdentifier(String idValue) {
this.idValue = idValue;
}
public String getIdValue() {
return idValue;
}
public void setIdValue(String idValue) {
this.idValue = idValue;
}
}
PS, it's probably better practice to either override the equals operation on MATIdentifier or to create a MATIdentifier Comparator than to create a custom contains and add impl for your Vector. I'd really suggest you use a java.util.Set.
Also, creating anonymous inner types like this with what I assume is important functionality is not a good practice, as it makes your code more difficult to test. If you insist on continuing with a specialized Vector implementation, you should move it into a class.

Related

C# equivalent for these JAVA Collections methods

hi I'm rewriting a java code in C# and I'm stuck here:
public void printSolveInstructions() {
System.out.print(getSolveInstructionsString());
}
public String getSolveInstructionsString() {
if (isSolved()) {
return historyToString(solveInstructions);
} else {
return "No solve instructions - Puzzle is not possible to solve.";
}
}
public List<LogItem> getSolveInstructions() {
if (isSolved()) {
return Collections.unmodifiableList(solveInstructions);
} else {
return Collections.emptyList();
}
}
I know how to rewrite the first two methods (it's for referencing the last one) but I don't know the equivalent for Collections.unmodifiableList() and Collections.emptyList()
solveInstructions is of type List here's the declaration in java and C#:
private ArrayList<LogItem> solveInstructions = new ArrayList<LogItem>() // java
private List<LogItem> solveInstructions = new List<LogItem>() // c#
update
I rewrote the getSolveInstructions() method in this way:
public List<LogItem> getSolveInstructions()
{
if (isSolved())
{
return solveInstructions.AsReadOnly();
}
else
{
return new List<LogItem>();
}
}
Now the problem is ide gives me an error when I use .AsReadOnly()
Your method returns either a List<LogItem>, or an IReadOnlyCollection<LogItem> (produced by call to List<T>.AsReadOnly() method; however, your return type is List<LogItem>, which is incompatible with the IReadOnlyCollection<LogItem>. Change your method return type to IList<LogItem>, which works for both types.
Note, since this method can return either a read-only or a read-write list, calling code should check the returned collection's IsReadOnly property, before attempting to modify it.

Java changing a property of one instance of class also changes another instance

Summary Question: Do different instances of a sub-class inherit the same parent class instance?
I would have thought that two instances of a sub-class also have different parent class instances, but perhaps I am not understanding something about inheritance. Hopefully someone can explain why I am seeing this behavior.
Here is the class where I see the "problem":
#Entity
#Table(name="inventory.parts_fstnr_capscrews")
public class FastenerCapScrew implements PartInterface {
...
private Dimension length;
private Dimension threadLength;
...
#ManyToOne
#JoinColumn(name="fk_lengthid")
#JsonView(View.CommodityPartPOView.class)
public Dimension getLength() {
return length;
}
public void setLength(Dimension length) {
this.length = length;
}
#ManyToOne
#JoinColumn(name="fk_threadlengthid")
#JsonView(View.CommodityPartPOView.class)
public Dimension getThreadLength() {
return threadLength;
}
public void setThreadLength(Dimension threadLength) {
this.threadLength = threadLength;
}
#Override
#Transient
public List<FiltersInterface> getFilters() {
List<FiltersInterface> filters = new ArrayList<>();
LOGGER.debug(filters.toString());
LOGGER.debug(length.toString());
LOGGER.debug(threadLength.toString());
if (length!=null) {
length.setDbColumnName("FK_LengthID");
filters.add(length);
}
LOGGER.debug(filters.toString());
LOGGER.debug(length.toString());
LOGGER.debug(threadLength.toString());
if (threadLength!=null) {
threadLength.setDbColumnName("FK_ThreadLengthID");
filters.add(threadLength);
}
LOGGER.debug(filters.toString());
LOGGER.debug(length.toString());
LOGGER.debug(threadLength.toString());
return filters;
}
}
And here is the Dimension class:
#Entity
#Table(name="utilities.dimensions")
public class Dimension extends FiltersExtension implements FiltersDimensionInterface {
...
}
And the extended class:
public class FiltersExtension {
protected String dbColumnName;
public String getDbColumnName() {
return dbColumnName;
}
public void setDbColumnName(String dbColumnName) {
this.dbColumnName = dbColumnName;
}
}
When I call the getFilters() method in FastenersCapScrew, the initial output for length and threadLength is as expected, and both have dbColumnName=null. Then it runs length.setDbColumnName("FK_LengthID");, but both length and threadLength are changed and both show dbColumnName=FK_LengthID. Then it runs threadLength.setDbColumnName("FK_ThreadLengthID");, and again both items are changed so that dbColumnName=FK_ThreadLengthID.
Initially, I thought it must have something to do with the hashCode and equals methods in Dimension, so I changed them to include dbColumnName as below:
#Override
public int hashCode() {
LOGGER.debug("First compare hashCode with dbColumnName="+this.dbColumnName);
int hash = 3;
hash = 37 * hash + this.dimID;
hash = 37 * hash + Objects.hashCode(this.dbColumnName);
return hash;
}
#Override
public boolean equals(Object obj) {
LOGGER.debug("Now compare equals with dbColumnName="+this.dbColumnName);
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Dimension other = (Dimension) obj;
if (this.dimID != other.dimID) {
return false;
}
LOGGER.debug("Now compare the column name: "+this.dbColumnName+" vs. "+other.dbColumnName);
if (!Objects.equals(this.dbColumnName,other.dbColumnName)) {
return false;
}
return true;
}
Can anyone explain to me why changing one Dimension instance changes the other one as well? And what would be the way to fix this so that I do have two totally separate instances? Thanks!
For what it is worth, I am using Java 8 and Spring Boot 2.0.3 with Hibernate, but I don't think that has any bearing on this problem.
Definitely two instances of a sub-class do not share memory for their parent fields. Maybe the cause of this behavior is just a Hibernate's cache. Hibernate does create a new instance of Dimension for one of the fields of FastenerCapScrew class loading it from cache instead. Try to enable logging of SQL-queries to investigate what happens when you call getFilters method.
EDIT
The simplest way to get different instances of essentially the same entity is to use defensive copying in setters. As long as you do not apply this technique to collections Hibernate should still be able to perform dirty checking since it compares objects by value. In contrast collections are compared by identity and dirty checking will not work for them.

Mockito : Testing void methods gives InvalidUseOfMatchersException

I'm having problems with two void methods. In encouragedVenturesScoring I've followed this answer mocking an arraylist that will be looped in a for loop and haven't mocked the list, but passed a real list and added mocked objects.
Mockito gives me an InvalidUseOfMatchersException on this line
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
There are lots of questions on SO on this exception , and I think it's because of anyInt(). Anyway I changed it to
verify(effectList.get(0)).execute(playerHandler);
And now it's saying Wanted but not invoked effect.execute(playerHandler)
Actually there were zero interactions with this mock
Is it because I put doNothing ?
doNothing().when(effect).execute(playerHandler);
In my second method militaryStrengthScoring() method is there a way to skip the first chunk of code and just test the if..else condition? What would be the best approach to test this method?
Thank you for your time.
This is the class to be tested
public class EndGameScoringBaseController implements EndGameScoringHandler {
private static final int[] TERRITORIES_REWARD = {0,0,1,4,10,20};
private static final int[] CHARACTERS_REWARD = {1,3,6,10,15,21};
private static final int RESOURCES_RATE = 5;
private static final int FIRST_MILITARY_REWARD = 5;
private static final int SECOND_MILITARY_REWARD = 2;
private PlayerHandler player;
public EndGameScoringBaseController(PlayerHandler player) {
super();
this.player = player;
}
#Override
public void encouragedVenturesScoring() {
for (DevelopmentCard card : player.getPlayer().getPersonalBoard().getVentures()) {
for (Effect e : card.getPermanentEffects())
e.execute(player);
}
}
#Override
public void militaryStrengthScoring(GameController game) {
Set<Integer> points = new HashSet<>();
int myPoints = this.player.getPointsHandler().getMilitaryPoints();
for (PlayerHandler p: game.getPlayers()) {
points.add(p.getPointsHandler().getMilitaryPoints());
}
int[] rank = new int[points.size()];
int j = 0;
for (Integer i : points) {
rank[j] = i;
j++;
}
Arrays.sort(rank);
if (rank[rank.length-1] == myPoints) {
player.getPointsHandler().winMilitaryPoints(FIRST_MILITARY_REWARD);
}
else if (rank[rank.length-2] == myPoints) {
player.getPointsHandler().winVictoryPoints(SECOND_MILITARY_REWARD);
}
}
Tested method for encouragedVenturesScoring
#Test
public void encouragedVenturesScoringTest() {
//given
List<DevelopmentCard> ventureList;
ventureList = Arrays.asList(developmentCard, developmentCard);
when(playerHandler.getPlayer().getPersonalBoard().getVentures()).thenReturn(ventureList);
List<Effect> effectList;
effectList = Arrays.asList(effect, effect);
when(developmentCard.getPermanentEffects()).thenReturn(effectList);
doNothing().when(effect).execute(playerHandler);
//when
endgameController.encouragedVenturesScoring();
//then
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
}
Incomplete tested method for militaryStrengthScoring
#Test
public void militaryStrengthScoringTest() {
//given
when(playerHandler.getPointsHandler().getMilitaryPoints()).thenReturn(4);
doNothing().when(playerHandler.getPointsHandler()).winMilitaryPoints(FIRST_MILITARY_REWARD);
//when
endgameController.militaryStrengthScoring(gameController);
//then
/../
}
You're right that this is the problem:
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
Mockito only allows for calls like any() and anyInt() to stand in for parameters to the mock themselves, due to the internal implementation of matchers.
/* OK */ when(yourMock.yourMethod(anyInt())).thenReturn(42);
/* BAD */ when(yourList.get(anyInt()).yourMethod(0)).thenReturn(42);
/* OK */ verify(yourMock).yourMethod(anyInt());
/* BAD */ verify(yourList.get(anyInt())).yourMethod(0);
The failure with get(0) is likely an actual failure, and may be related to the fact that your encouragedVenturesScoringTest is actually not calling encouragedVenturesScoring, it's calling influencedCharactersScoring. If this continues to give you trouble after fixing that error, in ways related to Mockito, please edit your question.
You can only verify mock objects created by Mockito.
But effectList is a "real" list. Therefore Mockito knows nothing about that object. Thus any attempt to verify that list must fail.
If you want to verify that object - then you have to mock it!
Of course, this means that you have specify all calls that will go to the mocked list.

How to do refactoring to eliminate type-code if it is used in validation rules?

Let's say we have to check some set of rules before adding a new element in a collection. Elements are objects of a few similar types. All type specific features are encapsulated in subclasses of an abstract class. Collection contains objects of this abstract class. The rules apply conditions for types along with other constraints. For that reason the abstract superclass of items has additional type code. New element can be added to collection but due to additional rules other elements in collection can be removed or replaced.
In the code that needs to be refactored, validation of the rules is implemented as one long block of code with nested control flow statements. Validation of the type code breaks encapsulation. Separate branches of the control flow statements cannot be defined as method of corresponding subclasses of collection elements because them need to check type and make changes to collection.
additional facts regarding type code in my case:
type code does not affect the behaviour of class
type code is immutable
type code is used by ItemsManager to resolve some rules before to add
new element to collection.
How to eliminate type code and separate rules from types?
Here is example of such problem:
Type specific features of Items are encpsulated in AbstractItem subclasses.add method of ItemManager class breaks encapsulation.Rule: item of Type2 must be removed if new item of Type1 with the same value of SomeUsefull property is adding to collection.
For simplicity implementation of ICloneable and IComparable interfaces is omitted. In real world items in collection are immutable and cloneable and the system of rules is quite tangled.
abstract class AbstractItem {
private int Type; // this would like to eliminate
private int SomeUseful;
protected AbstractItem(int Type, int Value) {
this.Type = Type;
this.SomeUseful = Value;
}
public int getType() { return this.Type; }
public int getSomeUseful() { return this.SomeUseful; }
#Override
public String toString() {
return String.format("Item{Type=%d, Value=%d}", Type, SomeUseful);
}
}
class ItemType1 extends AbstractItem {
ItemType1(int Value) { super(1, Value); }
}
class ItemType2 extends AbstractItem {
ItemType2(int Value) { super(2, Value); }
}
class ItemManager {
private java.util.ArrayList<AbstractItem> ListOfItems;
public ItemManager(){
this.ListOfItems = new java.util.ArrayList<AbstractItem>();
}
public void add(final AbstractItem newItem) {
// this code breaks encapsulation
switch (newItem.getType()) {
case 1:
// do some type dependent operations
for(AbstractItem i: this.ListOfItems) {
if (i.getType()==2 && i.getSomeUseful()==newItem.getSomeUseful()) {
this.ListOfItems.remove(i);
break;
}
}
break;
case 2:
// do some other type dependent operations
break;
default:
// throw error
}
this.ListOfItems.add(newItem);
}
#Override
public String toString() {
String str = String.format("ItemsManager content");
for(AbstractItem i: this.ListOfItems) {
str += String.format("\n\tType = %d, Value = %d", i.getType(), i.getSomeUseful());
}
return str;
}
}
public class Example1 {
public static void main(String[] arg) {
System.out.println("Example 1");
ItemManager im = new ItemManager();
im.add(new ItemType1(1));
im.add(new ItemType2(2));
im.add(new ItemType2(3));
im.add(new ItemType1(3));
System.out.println(im.toString());
}
}
/*
Example 1
ItemsManager content
Type = 1, Value = 1
Type = 2, Value = 2
Type = 1, Value = 3
*/
Starting from #dbugger's answer you can push it further.
You can use Double Dispatch to hide the type code. Still not a perfect solution because the parent knows too much about its children, but the type code is gone now.
It is hard to tell what a better solution might be with the example code you have given, because when you simplified, you removed all the information about the items involved. There might be something there that could be used for discrimination in some other way, allowing you to get rid of the double dispatch with shoudBeRemovedBecauseType1.
Here is the altered onAdd method from type 1
#Override
public List<AbstractItem> onAdd(List<AbstractItem> list) {
for (AbstractItem item : list) {
if (item.shoudBeRemovedBecauseType1(this)) {
list.remove(item);
break;
}
}
return list;
}
A new method in the base class
public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return false;
}
overridden in the type 2 subclass
#Override
public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return getSomeUseful() == itemType1.getSomeUseful();
}
It's not ideal, but it's a step towards getting some encapsulation and killing the switch statement...
add an onAdd method to the base class that takes the list as a parameter.
public java.util.ArrayList<AbstractItem> onAdd(java.util.ArrayList<AbstractItem> list) { return list; }
then override it in the sub classes, for example...
#Override
public java.util.ArrayList<AbstractItem> onAdd(java.util.ArrayList<AbstractItem> list) {
for(AbstractItem i: this.ListOfItems) {
if (i.getType()==2 && i.getSomeUseful()==this.getSomeUseful()) {
list.remove(i);
break;
}
}
return list;
}
then rewrite the ItemManager add method to just call the sub classes' onAdd methods...
public void add(final AbstractItem newItem) {
this.ListOfItems = newItem.onAdd(this.ListOfItems);
this.ListOfItems.add(newItem);
}

Comparing dynamic fields of objects using equals and hashCode methods

To compare the different objects of the same class with their contents like jobTitleId, classificationId, deptId & classificationId was to be done and do some manipulations later using Set and Map. I was able to do that by simply overriding the equals and hashCode methods of Object class and was able to fetch the information (like in the following Map).
Map<LocationData, List<LocationData>>
The following is the class I used (its been shown to you so that it can be referred for my problem statement):
LocationData class
package com.astreait.bulkloader;
public class LocationData {
String locId, deptId, jobTitleId, classificationId;
#Override
public boolean equals(Object obj) {
LocationData ld = (LocationData)obj;
return this.deptId.equals(ld.deptId) && this.jobTitleId.equals(ld.jobTitleId) && this.classificationId.equals(ld.classificationId) &&
this.locId.equals(ld.locId);
}
#Override
public int hashCode() {
return deptId.hashCode() + jobTitleId.hashCode() + classificationId.hashCode() +locId.hashCode();
}
}
Problem:
I'm already known to which all fields of this object I need to make the comparison.
i.e I'm bound to use the variables named classificationId, deptId, jobTitleId & locId etc.
Need:
I need to customize this logic such that the fields Names (classificationId, deptId, jobTitleId & locId etc) can be pulled dynamically along with their values. So, as far as my understanding I made use of 2 classes (TableClass and ColWithData) such that the List of ColWithData is there in TableClass object.
I'm thinking what if I override the same two methods equals() & hashCode();
such that the same can be achieved.
TableClass class #1
class TableClass{
List<ColWithData> cwdList;
#Override
public boolean equals(Object obj) {
boolean returnVal = false;
// I need to have the logic to be defined such that
// all of the dynamic fields can be compared
return returnVal;
}
#Override
public int hashCode() {
int returnVal = 0;
// I need to have the logic to be defined such that
// all of the dynamic fields can be found for their individual hashCodes
return returnVal;
}
}
ColWithData class #2
class ColWithData{
String col; // here the jobTitleId, classificationId, deptId, locId or any other more fields info can come.
String data; // The corresponding data or value for each jobTitleId, classificationId, deptId, locId or any other more fields.
}
Please let me know if I'm proceeding in the right direction or I should make some any other approach. If it is ok to use the current approach then what should be performed in the equals and hashCode methods?
Finally I need to make the map as: (Its not the concern how I will make, but can be considered as my desired result from this logic)
Map<TableClass, List<TableClass>> finalMap;
EDIT I have been down voted. So, I made some modifications for my requirements again. (Please help me out solving this)
Using this class ColWithData is kind of ugly. You should be using a Map<String,String> :
package mypack;
import java.util.*;
public class TableClass {
/* HashMap containing your values:
map.put("locId", [data]);
...
*/
public Map<String,String> cwdMap;
public Map<String,String> getCwdMap() {
return cwdMap;
}
public void setCwdMap(Map<String,String> cwdMap) {
this.cwdMap = cwdMap;
}
#Override
public boolean equals(Object obj) {
TableClass tClass = (TableClass) obj;
for(String col: this.cwdMap.keyset()){
if (! tClass.cwdMap.get(col).equals(this.cwdMap.get(col)){
return false;
}
}
return true;
}
#Override
public int hashCode() {
int hCode = 0;
for(String col: this.cwdMap.keyset()){
hCode = hCode+cwdMap.get(col).hashCode();
}
return hCode;
}
}
In this code I never check for null values but your probably should.
There is another thing that confuse me in your code:
why use getter/setter if your property (cwdList) is public?
I think I have found the solution and its working for me.
Please let me know if there could be the simple or any other way out finding the solution for this problem.
The code snippet is:
package mypack;
import java.util.*;
public class TableClass {
public List<ColWithData> cwdList;
public List<ColWithData> getCwdList() {
return cwdList;
}
public void setCwdList(List<ColWithData> cwdList) {
this.cwdList = cwdList;
}
#Override
public boolean equals(Object obj) {
TableClass tClass = (TableClass) obj;
boolean returnVal = true;
for(ColWithData cwd: this.getCwdList()){
for(ColWithData innerCwd: tClass.getCwdList()){
if(cwd.getCol().equalsIgnoreCase(innerCwd.getCol())){
if(!cwd.getData().equalsIgnoreCase(innerCwd.getData()))
returnVal = false;
}
}
}
return returnVal;
}
#Override
public int hashCode() {
int hCode = 0;
for(ColWithData cwd: this.getCwdList()){
hCode = hCode+cwd.getData().hashCode();
}
return hCode;
}
}
And finally made a map as said:
Map<TableClass, List<TableClass>> map = new LinkedHashMap<TableClass, List<TableClass>>();
displaying the things as desired.

Categories