Как получить объект, а не адрес без использования String / toString? - PullRequest
0 голосов
/ 27 октября 2018

Мне нужно создать свой собственный класс String с именем MyString без использования стандартного класса String / векторного API.Я должен поработать над некоторыми обязательными методами, и их возвращаемые типы предопределены.Я могу добавить другие методы, если String не используется.

Ожидаемое использование будет:

(в основном) System.out.println(str.toLowerCase()) - возвращает нижний регистр str

Когда я хочу работать с toLowerCase() методом с типом возврата MyString, я не могу вернуть содержимое объекта, а только вернуть адрес.

Обычно эта проблема требует изменения toString(), но, поскольку этот метод требует возвращаемого типа String по умолчанию, я не могу использовать модификацию toString() для назначения.

Задание должно быть не таким сложным и не должно требовать сложных расширений.Мой конструктор может быть проблемой, но я не могу указать, какая часть.

Код

public class MyString {
private char value[];

MyString(char[] arr){
    this.value = Arrays.copyOf(arr, arr.length);
}

... 

MyString toLowerCase() { // can't change return type
    for (int i =0; i<value.length; i++) {
        if ((int)value[i] > 64 && (int)value[i] < 91) {
            value[i] = (char) (value[i]+32);
        }
    }
    return this; // this returns address, and I can't override toString
}

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

Во-первых, класс String является неизменяемым типом, то есть методы String не изменяют внутреннее состояние (т. Е. Массив char), вместо этого они возвращают новый экземпляр типа String. Чтобы отразить это поведение, вы можете реализовать что-то вроде этого:

public MyString toLowerCase() {
    char temp = new char[value.length];
    // [...] Your code performing the actual logic on temp
    return new MyString(temp);
}

Неизменность (и ее значение) класса String очень важна для понимания на практике. Например, следующий код проконтролирует ожидаемый результат:

String word = "Word";
System.out.println("I can produce upper case (" + word.toUpperCase() + ") " + 
                   "and lower case (" + word.toLowerCase() + ") " + 
                   "without any side-effects on the original (" + word + ").");

Однако невозможно (без «хакерских» решений) реализовать такой метод:

void shortenString(String inputAndOutput);

Во-вторых, присвоение ожидает, что класс / метод должен использоваться следующим образом:

System.out.println(str.toLowerCase());

Атрибут out фактически является PrintStream, который предлагает (помимо других методов) следующие два:

println(Object x) - печатает объект, а затем завершает строку.

println(String x) - печатает строку, а затем завершает строку.

Если метод вызывается с параметром Object, внутренняя реализация вызывает toString() для данного объекта, таким образом, единственный способ удовлетворить требование - переопределить этот метод. К сожалению, это не разрешено назначением.

Однако, если явно не указано, что решение должно использовать java.lang.System, вы можете просто реализовать свой собственный класс System, который принимает MyString, например ::

public class System {
    public static class MyPrintStream /* optional: extends PrintStream */ {
         public void println(MyString x) {
             java.lang.System.out.println(x.getCharArray());
         }
    }

    public static final out = new MyPrintStream();
}

Это позволит вам использовать его точно так же, как описано в задании:

import my.package.System;

public class Main {
    public static void main(String[] args) {
        // [...] Instantiate str
        System.out.println(str.toLowerCase());
    }
}
0 голосов
/ 27 октября 2018

Проблема с System.out.println(str.toLowerCase()) в том, что он в итоге вызывает PrintStream.println(Object o), но этот метод внутренне в какой-то момент вызывает o.toString(), который использует код, унаследованный от Object#toString() (так как вы не можете переопределить toString, так как он ожидает, чторезультат String (который запрещен в вашем проекте), который приводит к форме TypeInfo@hexHashCode.

Это означает, что вы не можете использовать System.out.println(MyString).

НО PrintStream (экземпляр которого хранится System.out) позволяет нам предоставлять данные для печати в различных формах.В этом случае вы можете использовать println(char[]).Все, что вам нужно сделать, это добавить к MyString метод, подобный toCharArray(), который бы возвращал (предпочтительно копию) массива символов, содержащихся в классе MyString.

Таким образом, вы можете использовать его как System.out.println(myStringInstance.toCharArray()), поэтому код из вашего main метода должен выглядеть следующим образом:

System.out.println(str.toLowerCase().toCharArray());
//                                   ^^^^^^^^^^^--this should return char[]
...