Trouble deep cloning an array object - java

I believe my code is wrong but could someone correct me on my error. I am trying to deep clone an array of objects but class A doesn't seem to be a deep copy as i am having trouble with it. Could some please help. I have trouble copying the array A.
Class A implements Cloneable{
private int year;
private double data;
A(int year, double data)
{
setInt(year);
setDouble(data);
}
public void setInt(int year)
{
this.year = year;
}
public void setDouble(double data)
{
this.data = data;
}
public int getYear()
{
return year;
}
public double getData()
{
return data;
}
public Object clone()
{
A clonedA = new A(this.getYear(), this.getData());
return clonedA;
}}
class B implements Cloneable{
private A[] a;
private String name;
private int arraylength;
private int index;
public B(String name, int length)
{
this.name = name;
this.arraylength = length;
a = new A[array.length];
index = 0;
}
public void addToA(int year, double data)
{
a[index] = new A(year, data);
index++;
}
public String getName(){
return name; }
public int getLength(){
return array length;}
public void setName(String name)
{
this.name= name
}
public Object clone()
{
B clonedB = new B(this.getName(), this.getLength());
for(A clonedArray: a)
{
clonedB.addToA(clonedArray.getYear(), clonedArray.getData());
}
return clonedB;
}

Your clone method in class B seems to be wrong:
I suggest you do sth like
public Object clone()
{
B newB = new B(this.getName(), this.getLength());
for(int i =0;i<newB.a.length;i++)
{
newB.a[i] = a[i];
}
return newB;
}
You could also try a copy constructor;

Related

Refactor a stateful class

I have a stateful class in java
class Container {
int capacity;
String name;
public int getCapacity() {
return capacity;
}
public void consumeContainer(int numberOfUnits) {
this.capacity = this.capacity - numberOfUnits;
}
}
I am looking for options to refactor this so I don't have to mutate the class everytime the container is consumed. Can the experts throw in ideas on how to do that?
Thanks
If you want to make your class immutable, this is an option:
class ImmutableContainer {
final int capacity;
final String name;
public ImmutableContainer(int capacity, String name) {
this.capacity = capacity;
this.name = name;
}
public int getCapacity() {
return capacity;
}
public ImmutableContainer consumeContainer(int numberOfUnits) {
return new ImmutableContainer(this.capacity - numberOfUnits, name);
}
}
Or, even simpler, as a record:
record ImmutableContainer(int capacity, String name) {
public ImmutableContainer consumeContainer(int numberOfUnits) {
return new ImmutableContainer(this.capacity - numberOfUnits, name);
}
}

Have a Queue with Generics implementation print specific Object attributes

I have created a simple Queue of type which is also contains a print() function to it.
public class ArrayQueue implements Queue {
private T[] theArray;
private int currentSize;
private int front;
private int back;
private static final int DEFAULT_CAPACITY = 10;
public ArrayQueue() {
theArray = (T[]) new Object[DEFAULT_CAPACITY];
currentSize = 0;
front = 0;
back = -1;
}
public boolean isEmpty() {
return currentSize == 0;
}
public T dequeue() throws EmptyQueueException {
if (isEmpty())
throw new EmptyQueueException("ArrayQueue dequeue error");
T returnValue = theArray[front];
front = increment(front);
currentSize--;
return returnValue;
}
public void enqueue(T x) {
if (currentSize == theArray.length)
doubleQueue();
back = increment(back);
theArray[back] = x;
currentSize++;
}
private int increment(int x) {
if (++x == theArray.length)
x = 0;
return x;
}
public void print() {
if (isEmpty()) {
System.out.printf("Empty queue\n");
return;
}
System.out.printf("The queue is: ");
for (int i = front; i != back; i = increment(i)) {
System.out.print(theArray[i] + " ");
}
System.out.print(theArray[back] + "\n");
}
I have also created a Song object with 3 variables
public class Song {
private int id;
private String name;
private int likes;
public Song() {
this(1,"Test",10);
}
public Song(int id,String name, int likes) {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLikes() {
return likes;
}
public void setLikes(int likes) {
this.likes = likes;
}
Is there a way modify this function in order to print a specific object's information or do i need to write a different print method during my implementation?
For example i would like my Print method to show all the objects variables , if i call just like this is will only get the object pointer
ArrayQueue<Song> arrayQueue = new ArrayQueue<Song>();
Queue<Song> queue = arrayQueue; //arrayQueue instance is also a Queue
Song s = new Song();
arrayQueue.enqueue(s);
arrayQueue.print();
Result is
The queue is: Song#15db9742
My modification would print :
The queue is : 1 Test 10
You need to override the toString() method of Song.
For example, add this to Song:
#Override
public String toString() {
return id + " " + name + " " + likes;
}

Can't instantiate parceable Object

I created a parceable class and wanted to use it for data transfer from fragment A to B. I did it like in many other tutorials but I can't instantiate from parceable object class. it always says, that I have to put in 'Parcel in' as parameter.
Here my object class:
public class DataObject implements Parcelable {
private int number1 = 0;
private int number2 = 0;
private String name = "";
public int getNumber1() {
return number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber2() {
return number2;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected DataObject(Parcel in) {
number1 = in.readInt();
number2 = in.readInt();
name = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(number1);
dest.writeInt(number2);
dest.writeString(name);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<DataObject> CREATOR = new Parcelable.Creator<DataObject>() {
#Override
public DataObject createFromParcel(Parcel in) {
return new DataObject(in);
}
#Override
public DataObject[] newArray(int size) {
return new DataObject[size];
}
};
}
And here is how I use objects from this type:
DataObject bla = new DataObject();
bla.setNumber1(1);
bla.setNumber2(2);
bla.setName("TestName");
When I hover the red highlighted constructor it says:
DataObject (Parcel) in DataObject cannot be applied
and compiler says:
Error:(30, 50) error: constructor PointCardMainData in class
PointCardMainData cannot be applied to given types;
required: Parcel
found: no arguments
reason: actual and formal argument lists differ in length
Has anybody an idea what is missing? Do I have to set something in the manifest- oder gradle-file? do I have to do something before building the project?
best regards
You've written just one constructor in the DataObject class, and it specifies how to make a DataObject from a Parcel. Now you're trying to make a DataObject without a parcel. You need to either add a Parcel to the line DataObject bla = new DataObject(); or add a new constructor.
So you might write
Parcel theParcel = new Parcel();
DataObject bla = new DataObject(theParcel);
Or you might have a constructor in your DataObject class like
public DataObject(){
}
Add a constructor in your DataObject class
public DataObject()
{}

Java performing code only from constructor's subclass

Is it possible to protect from performing code placed in superclass constructor? In this example the output is
From Person
From Student
but I don't need to print out From Person. If I delete super(a, n); then program will not compile. Is it possible to print out only message from subclass?
class Person {
private int age;
private String name;
public Person(int a, String n) {
this.age = a;
this.name = n;
System.out.println("From Person");
}
public int getAge() {
return age;
}
public void setAge(int a) {
this.age = a;
}
public String getName() {
return name;
}
public void setName(String n) {
this.name = n;
}
}
class Student extends Person {
private String specialization;
public Student(int a, String n, String s) {
super(a, n);
specialization = s;
System.out.println("From Student");
}
public String getSpecialization() {
return specialization;
}
public void setSpecialization(String s) {
this.specialization = s;
}
}
public class Classes {
public static void main(String[] args) {
Student student_Jack = new Student(20, "Jack", "IT");
}
}
Instead of using super(a,n) you should use your methods for setting those variables that you have made.
public Student(int a, String n, String s) {
setAge(a);
setName(n);
specialization = s;
System.out.println("From Student");
}
You must also add an empty constructor in person.
public Person(){}
This will give you the same functionality, without needing to call the super constructor.

how to Externalise Java enums with Attributes into XML

i have a Java Enum like below
public enum TestEnum{
{
A("a","b","c"),
B("a1","b1","c1"),
C("a2","b2","c2");
TestEnum(String a,String b,String c){
}
private String a;
private String b;
private String c;
}
I want to externalize this config to an XML file but XSDs donot seem to support attributes on Enum Element type. Is there a way to work this around or an alternate to it.
You could do something like this (even though for enum, this looks too verbose)
#XmlJavaTypeAdapter(CountXmlAdapter.class)
public enum Count {
ONE(1, "one"),
TWO(2, "two"),
THREE(3, "three");
private final int index;
private final String name;
private Count(int index, String name) {
this.index = index;
this.name = name;
}
#XmlAccessorType(XmlAccessType.FIELD)
public static class CountWrapper {
private int index;
private String name;
public CountWrapper() {
}
public CountWrapper(int index, String name) {
this.index = index;
this.name = name;
}
}
public static class CountXmlAdapter extends XmlAdapter<CountWrapper, Count> {
#Override
public Count unmarshal(CountWrapper v) throws Exception {
return v != null ? Count.valueOf(v.name.toUpperCase()) : null;
}
#Override
public CountWrapper marshal(Count v) throws Exception {
return v != null ? new CountWrapper(v.index, v.name) : null;
}
}
}

Categories