0

I want to design a builder pattern with 2 constructors. One of the parameters needs to be compulsory and either a string or an array string.

All of the following code is for testing. It doesn't do anything useful.

This first chunk of code calls two classes. The calls to the first class demonstrate that the builder pattern can have 2 different constructors. In this test example, the first call has two compulsory parameters.

The 2nd call has only optional parameters. This code works and proves that builder will work with 2 constructors.

package flag.panel.bx6;

public class TestBuilderPattern {
        private static String[] anArray = new String[20];

    public static void main(String[] args) {
    TestBuilder comp = new TestBuilder.SampleBuilder(
            "500 GB", "2 GB").setBluetoothEnabled(true)
            .setGraphicsCardEnabled(true).build();
            System.out.print("Gfx card : " + comp.isGraphicsCardEnabled() + "\n");                
    TestBuilder comp2 = new TestBuilder.SampleBuilder().setBluetoothEnabled(true)
            .setGraphicsCardEnabled(true).build();
             System.out.print("HDD : " + comp2.getHDD() + "\n");                
             System.out.print("RAM : " + comp2.getRAM() + "\n");                


            anArray[0] = "text";

    TestBuilderArray comp3 = new TestBuilderArray.SampleBuilder(
            "500 GB", "2 GB").setBluetoothEnabled(true)
            .setGraphicsCardEnabled(true).build();
            System.out.print("Gfx card : " + comp.isGraphicsCardEnabled() + "\n");  

            System.out.print("HDD : " + comp3.getHDD() + "\n");  

            TestBuilderArray comp4 = new TestBuilderArray.SampleBuilder("3TB",anArray).setBluetoothEnabled(true)
            .setGraphicsCardEnabled(true).build();

             System.out.print("RAM : " + comp4.getRAM() + "\n");                

}

}

Here is the code for the class with 2 constructors. This code works.

package flag.panel.bx6;
public class TestBuilder {

//required parameters
private final String HDD;
private final String RAM;

//optional parameters
private final boolean isGraphicsCardEnabled;
private final boolean isBluetoothEnabled;

public String getHDD() {
        return HDD;
}
public String getRAM() {
        return RAM;
}
public boolean isGraphicsCardEnabled() {
        return isGraphicsCardEnabled;
}
public boolean isBluetoothEnabled() {
        return isBluetoothEnabled;
}
private TestBuilder(SampleBuilder builder) {
        this.HDD=builder.HDD;
        this.RAM=builder.RAM;
        this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
        this.isBluetoothEnabled=builder.isBluetoothEnabled;
}
//Builder Class
public static class SampleBuilder{
    // required parameters
    private String HDD;
    private String RAM;

    // optional parameters
    private boolean isGraphicsCardEnabled;
    private boolean isBluetoothEnabled;

    //Contructor 1
    public SampleBuilder(String hdd, String ram){
        this.HDD=hdd;
        this.RAM=ram;
    }
    //Constructor 2
    public SampleBuilder(){
        this.HDD = "HDD1";
        this.RAM = "RAM1";
    }
    public SampleBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
        this.isGraphicsCardEnabled = isGraphicsCardEnabled;
        return this;
    }
    public SampleBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
        this.isBluetoothEnabled = isBluetoothEnabled;
        return this;
    }
    public TestBuilder build(){
        return new TestBuilder(this);
    }
}

}

Now for the code that doesn't work. I want the constructor to accept as a compulsory parameter either a String or a String array. If the call includes a String, that value needs to be stored in the constructor in the String array. Internally, all processing will be done on the String array.

package flag.panel.bx6;
public class TestBuilderArray {

    //required parameters
    private final String HDD;
    private final String RAM;

    private final String[] testArray;

    //optional parameters
    private final boolean isGraphicsCardEnabled;
    private final boolean isBluetoothEnabled;

    public String getHDD() {
            return HDD;
    }
    public String getRAM() {
            return RAM;
    }
    public boolean isGraphicsCardEnabled() {
            return isGraphicsCardEnabled;
    }
    public boolean isBluetoothEnabled() {
            return isBluetoothEnabled;
    }
    private TestBuilderArray(SampleBuilder builder) {
            this.HDD=builder.HDD;
            this.RAM=builder.RAM;
            this.testArray = builder.testArray;
            this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
            this.isBluetoothEnabled=builder.isBluetoothEnabled;
    }
    //Builder Class
    public static class SampleBuilder{
        // required parameters
        private String HDD;
        private String RAM;

        private String[] testArray;
        // optional parameters
        private boolean isGraphicsCardEnabled;
        private boolean isBluetoothEnabled;

        //Contructor 1
        public SampleBuilder(String hdd, String ram){
            testArray = new String[10]  //##### This was the missing statement.
            this.HDD=hdd;
            this.RAM=ram;
            this.testArray[0]="ram";
        }
        //Constructor 2
        public SampleBuilder(String hdd, String[] tstArray){
            testArray = new String[10]  //##### This was the missing statement.
            this.HDD = hdd;
            this.RAM = "RAM1";
            //System.arraycopy( src, 0, dest, 0, src.length );
            //System.arraycopy( tstArray, 0, this.testArray, 0, tstArray.length );
        }
        public SampleBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
            this.isGraphicsCardEnabled = isGraphicsCardEnabled;
            return this;
        }
        public SampleBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
            this.isBluetoothEnabled = isBluetoothEnabled;
            return this;
        }
        public TestBuilderArray build(){
            return new TestBuilderArray(this);
        }
    }
}

When I try and run this code, Netbeans gives the following output:

    run:
Gfx card : true
HDD : HDD1
RAM : RAM1
Exception in thread "main" java.lang.NullPointerException
    at flag.panel.bx6.TestBuilderArray$SampleBuilder.<init>(TestBuilderArray.java:61)
    at flag.panel.bx6.TestBuilderPattern.main(TestBuilderPattern.java:27)
C:\Users\darren\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)

This indicates an error on line 61 of the TestBuilderArray method. I have tried a range of different things but I can't figure out what I am doing wrong. I suspect this has nothing to do with the dual constructors.

I have also commented out another statement causing problems:

                //System.arraycopy( tstArray, 0, this.testArray, 0, tstArray.length );

So basically I can't get a String array to work in this class. Any suggestions would be welcome.

dazz
  • 119
  • 2
  • 14
  • You should use `testArray = tstArray.clone();` instead of `System.arraycopy()`. –  Aug 06 '17 at 22:33
  • I found a post somewhere that said System.arraycopy was the preferred method. Would you mind explaining why clone would be better in this app? – dazz Aug 07 '17 at 02:09
  • The answer was in the answers to the other question. I have modified the faulty code above to include the missing statements in the constructors. It now compiles and runs. – dazz Aug 07 '17 at 02:17
  • I found a post here https://stackoverflow.com/questions/4592478/clone-arraylist-clone-i-thought-does-a-shallow-copy) that said System.arraycopy was the preferred method. – dazz Aug 07 '17 at 02:23

0 Answers0