Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display object as a String properly

Tags:

java

tostring

Im working on this code and expecting a matrix to be printed but thats what came up Matrix@2c78bc3b Matrix@2a8ddc4c

This is a code example:

public class Matrix
{

    public static int rows;
    public static int colms;//columns
    public static int[][] numbers;

    public Matrix(int[][] numbers)
    {

        numbers = new int[rows][colms];

    }


    public static boolean isSquareMatrix(Matrix m)
    {
        //rows = numbers.length;
        //colms = numbers[0].length;

        if(rows == colms)
           return true;
        else
            return false;
    }

    public static Matrix getTranspose(Matrix trans)
    {
       trans = new Matrix(numbers);

        for(int i =0; i < rows; i++)
        {
            for(int j = 0; j < colms; j++)
            {
                trans.numbers[i][j] = numbers[j][i];
            }
        }
        return trans;
    }



    public static void main(String[] args)
    {
        int[][] m1 = new int[][]{{1,4}, {5,3}};
        Matrix Mat = new Matrix(m1);

        System.out.print(Mat);
        System.out.print(getTranspose(Mat));

    }
}
like image 628
W M Avatar asked Dec 03 '22 11:12

W M


2 Answers

You need to implement toString() in a meaningful way.

This toString() (below) is perhaps suitable for debugging, but will be ugly and confusing if you use it for real user output. An actual solution would probably use a Formatter in some complicated way to produce neatly tabular rows and columns.

Some additional recommendations based on your code:

  • Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the .length, and provide accessor methods if need be.
  • Use final in method args, it will eliminate bugs like you have above, aliasing numbers incorrectly int the constructor
  • Use an instance, not static
  • Paranoia is the programmer's lifestyle: I also modified my code to do a deepCopy of the provided int[][] array, otherwise there is reference leakage, and the Matrix class would be unable to enforce its own invariants if caller code later modified the int[][] they passed in.

  • I made my Matrix immutable (see final private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).

Here's some improved code:

public final class Matrix
{
    final private int[][] numbers;

    // note the final, which would find a bug in your cited code above...
    public Matrix(final int[][] numbers)
    {   
        // by enforcing these assumptions / invariants here, you don't need to deal 
        // with checking them in other parts of the code.  This is long enough that you might 
        // factor it out into a private void sanityCheck() method, which could be 
        // applied elsewhere when there are non-trivial mutations of the internal state

        if (numbers == null || numbers.length == 0) 
          throw new NullPointerException("Matrix can't have null contents or zero rows");
        final int columns = numbers[0].length;
        if (columns == 0) 
          throw new IllegalArgumentException("Matrix can't have zero columns");
        for (int i =1; i < numbers.length; i++) {
          if (numbers[i] == null) 
             throw new NullPointerException("Matrix can't have null row "+i);
          if (numbers[i].length != columns) 
             throw new IllegalArgumentException("Matrix can't have differing row lengths!");
        }
        this.numbers = deepCopy(numbers);
    }

    public boolean isSquareMatrix() { return rowCount() == columnCount(); }
    public int rowCount() { return numbers.length; }
    public int columnCount() {return numbers[0].length; }

    private static int[][] deepCopy(final int[][] source)
    {
       // note we ignore error cases that don't apply because of 
       // invariants in the constructor:
       assert(source != null); assert(source.length != 0);
       assert(source[0] != null); assert(source[0].length != 0);
       int[][] target = new int[source.length][source[0].length];
       for (int i = 0; i < source.length; i++) 
          target[i] = Arrays.copyOf(source[i],source[i].length);
       return target;
    }

  public Matrix getTranspose()
  {

    int[][] trans = new int[columnCount()][rowCount()];

    for (int i = 0; i < rowCount(); i++)
      for (int j = 0; j < columnCount(); j++)
        trans[i][j] = getValue(j, i);
    return new Matrix(trans);
  }

  @Override
  public String toString()
  {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < numbers.length; i++) 
    { 
      for (int j = 0; j < numbers[i].length; j++) 
        sb.append(' ').append(numbers[i][j]);
      sb.append('\n');
    }
    return sb.toString();
  }

  public static void main(String[] args)
  {
    final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } };
    Matrix mat = new Matrix(m1);
    System.out.print(mat);
    System.out.print(mat.getTranspose());
  }
}
like image 111
13 revs Avatar answered Jan 02 '23 20:01

13 revs


for a quick and dirty method:

public String toString() {
    return Arrays.deepToString(numbers);
}

On an unrelated note, the variables rows, colms, numbers and the methods isSquareMatrix should not be declared as static. Otherwise, when you get a transpose, you're going to end up with two matrix objects writing to the same class variables.

like image 27
robert_x44 Avatar answered Jan 02 '23 20:01

robert_x44