简体   繁体   中英

constructor for my class doesn't work

I have the following ArrayIntList class with constructors defined as below. In the last constructor, I want to have boolean, which if true, instantiates a new object with that particular element in it. If set to false, it should just instantiate a new object with that many capacity. kindly look at the client code for what I mean here. it works when boolean is true.

Class FILE:

public class ArrayIntList {
    private int[] elementData; // list of integers
    private int size;          // current number of elements in the list

    public static final int DEFAULT_CAPACITY = 100;

    // post: constructs an empty list of default capacity
    public ArrayIntList() {
        this(DEFAULT_CAPACITY);
    }

    // pre : capacity >= 0 (throws IllegalArgumentException if not)
    // post: constructs an empty list with the given capacity
    public ArrayIntList(int capacity) {
        if (capacity < 0) {
            throw new IllegalArgumentException("capacity: " + capacity);
        }
        elementData = new int[capacity];
        size = 0;
    }

    //takes input list and adds to arrayIntList
    public ArrayIntList(int[] elements) {
      this(Math.max(DEFAULT_CAPACITY,elements.length*2));
      for (int n: elements){
         this.add(n);
      }
    }

    //creates an arrayIntlist with data of element
    public ArrayIntList(int element,boolean notCapacity) {
      this();
      if (notCapacity) {
         add(element);
      }
   //returns the totalCapacity NOT SIZE
    public int getCapacity() {
  return elementData.length;
    }
}

Client code:

public class ArrayIntListExample {
    public static void main(String[] args) {
        // Create a new list and add some things to it.
        ArrayIntList list = new ArrayIntList();

        //*** here is my question about ****//
        ArrayIntList list1 = new ArrayIntList(2, false);//should give [] with capacity of two
        ArrayIntList list2 = new ArrayIntList(2, true);//should give [2] 
        //*** ****************************** ****//
        int[] array={2,3,4,5};
        ArrayIntList list3 = new ArrayIntList(array);
        list.add(12);
        list.add(3);
        list.add(3);
        System.out.println("list = " + list);
        System.out.println("list1 = " + list1);
        System.out.println("list2 = " + list2);
        System.out.println("list2 = " + list3);
        System.out.println("capacity of list1" + list1.getCapacity());//prints 100 but it must be 2
    }
}

To want it to behave the way you want, I imagine you want to pass element to the constructor with the lone int parameter:

public ArrayIntList(int element, boolean notCapacity) {
    this(element);
    if (notCapacity) {
         add(element);
    }
}

Previously you were simply calling this() , which initializes the array with the default capacity. If you step through your code manually or with a debugger, you can see this happening.

There are other problems with your design, however. Aside from an unwieldy and confusing interface/API (through your constructors), there is also a difference between the capacity of your array (ie, the total number of elements it can hold) and its size (ie, the number of elements in the array currently).

EDIT

One of the reasons why your API is confusing is that you have the following scenario:

-------------------------------------------------------------------
Constructor            | int | boolean | Behavior
-----------------------+-----+---------+---------------------------
(element)              |  2  |    x    | Array with capacity 2
(element, notCapacity) |  2  |  true   | Array with one element (2)
(element, notCapacity) |  2  |  false  | Array with capacity 2
-----------------------+-----+---------+---------------------------
  • You have two ways of doing the same thing.
  • You have an boolean argument that is given a negative name. It's easier to figure out the meaning of "capacity is false" than "notCapacity is false".
  • You introduced a feature with limited value (initializing an array with one element of arbitrary value) while introducing inconsistency and confusion. Essentially the only point that notCapacity serves is to distinguish the two behaviors that you want (initializing with capacity vs. initializing with one element of arbitrary value).
  • element has two, very different meanings: capacity vs. single element to be added to the array.
  • Changing the false to true is enough to invoke wildly-different behavior from the constructor.
  • Booleans in constructors are generally opaque and are of limited value. From seeing an invocation like new ArrayIntList(5, true) , is the intent obvious?

Lets look at your constructor:

public ArrayIntList(int element,boolean notCapacity) {
  this();
  if (notCapacity) {
     add(element);
  }
}

Now lets look at this line:

this();

This line will call your constructor with no arguments. That constructor looks like this:

public ArrayIntList() {
    this(DEFAULT_CAPACITY);
}

So this will call the constructor which takes a capacity and it will pass DEFAULT_CAPACITY to it. So adding some comments to the original:

public ArrayIntList(int element,boolean notCapacity) {

  this(); // initializes this object with a capacity of 100 and no elements

  if (notCapacity) {
     add(element); // if notCapacity is true, add the element
  }
}

As you can see, nowhere do you actually use the "element" variable if notCapacity is false (meaning it should be the capacity).

A very simple fix for this could be:

public ArrayIntList(int element,boolean notCapacity) {

  this(notCapacity ? DEFAULT_CAPACITY : element);

  if (notCapacity) {
     add(element);
  }
}

However, I think a better design would be to not have this constructor at all and instead provide the following static methods:

public static ArrayIntList createWithElement(int element) {
    ArrayIntList ret = new ArrayIntList();
    ret.add(element);
    return ret;
}

Then the caller has a clean and clear method to call to create a list with 1 element.

This should work, but I think your API is confusing..

public ArrayIntList(int element,boolean startElement) {
  this(startElement ? 1 : element);
  if (startElement) {
     add(element);
  }
}

I think you should remove this constructor and instead let users do new ArrayIntList(new int[] { 2 }) if they want a list with a specific element in.

If you follow through the code it is clear why the behavior is happening.

public ArrayIntList(int element,boolean notCapacity) {
  this();
  if (notCapacity) {
     add(element);
  }
}

This method will create a new Array of DEFAULT_CAPACITY and if its false it simply finishes the method and returns without anything else done.

The easiest solution would simply to add an else statement like this:

public ArrayIntList(int element,boolean notCapacity) {
  this();
  if (notCapacity) {
     add(element);
  } else {
     elementData = new int[element];
  }
}

Although, I would strongly suggest you rethink your class structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM