Подтвердить что ты не робот

Final String class vs final methods of Non-final String class

Я знаю, что класс java.lang.String объявляется окончательным по соображениям безопасности и производительности.

То, что я не понимаю, является частью того, можно ли достичь одной цели с использованием всех конечных переменных и конечных методов вместо объявления конечного класса?

Короче говоря, в чем разница между двумя фрагментами кода.. например,

public class final String { .. } 

V/S

// non final class
public class String {

// all final variables
private final char[] value;

// all final methods
public final String subString() { .. }
public final int length() { return value.length;}

// etc
}

редактирует

Простыми словами, могу ли я достичь такого же уровня неизменности, перейдя к любому подходу? Они оба хороши, чтобы объекты были неизменными?

4b9b3361

Ответ 1

Заключительные классы не могут быть расширены.

Не конечные классы с окончательными методами могут быть расширены (новые подходы могут быть добавлены в подклассы), но существующие окончательные методы не могут быть переопределены.

Ответ 2

Окончательный модификатор в классе не означает, что свойства также являются окончательными и неизменяемыми. Это просто означает, что класс больше не может быть родительским классом. Невозможно продлить окончательный класс.

См. Использование конечного класса в Java

Ответ 3

Финал имеет разные эффекты, зависящие от того, где вы его используете.

Если класс его окончательный, он не может быть подклассом.

Если метод его окончательный, он не может быть переопределен каким-либо подклассом.

Если переменная ее окончательная, ее можно инициализировать только один раз, делая ее постоянной.

Ответ 4

Вы забыли о конструкторе. Конструктор не может быть окончательным. Чтобы избежать ситуаций Is-A.

Если вы не отмечаете класс как окончательный, хотя все ваши методы являются окончательными, мы все же можем расширять String и можем обманывать потоки, утверждая, что мой класс также является классом String.

Если только String не является окончательным, а методы являются окончательными, ниже законно, что вызывает беспорядок

public class MyUnTrustedClass extends String {

   void MyUnTrustedClass(String virus){
        super(virus);
     }

}

Ответ 5

public final String { ... }
public ExtendedString extends String { ... } // compiler error

public String { ... }
public ExtendedString extends String { ... } // fine

Немного больше объяснений:

Создание окончательного класса также неявно делает все методы окончательными, но также запрещает даже расширять класс. Выполнение окончательных методов все еще позволяет расширить класс и только запрещает отменять окончательные методы. В последнем случае вы можете объявить совершенно новые методы в расширяющемся классе.

Не конечный класс String со всеми конечными методами будет по-прежнему неизменен (если применимы все другие аспекты непреложности). Обратите внимание, что создание финала класса - это слишком мало усилий, чтобы сделать его неизменным. На самом деле, даже не конечный класс может быть неизменным, если он правильно разработан.

Ответ 6

То, что я не понимаю, - это то, достигаются с использованием всех конечных переменных и конечных методов вместо объявить окончательный класс?

Цель объявления класса как конечного значения не совпадает с целью, заключающейся в объявлении всех методов в классе как final.

Заключительные классы

Когда я объявляю класс A окончательным, я указываю, что такой класс заморожен, он не предназначен для расширения и что он не должен использоваться каким-либо другим способом, кроме выраженного в его структуре и объявлениях, Класс А в силу того, что он является окончательным, не открыт для уточнения.

ПРИМЕЧАНИЕ 1:. Если вам нужно что-то использовать с типом A, есть один и только один класс, один тип, а именно A, который вы можете использовать. Ограничение преднамеренное в соответствии с любым дизайном, который вы преследуете или согласно вашим требованиям.

Класс java.lang.System является ярким примером. Во время выполнения существует один тип системы. Можно было бы иметь несколько экземпляров этой системы (или, как в Java, своего рода одноэлементную оболочку для системы). Но тип, возможности этого типа системы - это один и только один.

Классы с конечными методами

С другой стороны, класс A со всеми методами final просто говорит то, что я вам предоставляю, вы не можете продлить. Однако вы можете добавить больше функциональности или указать расширение на меня.

ПРИМЕЧАНИЕ 2:. Если вам нужно использовать класс A, который не является окончательным, но имеет большинство, если не все методы, как final, вы можете использовать либо экземпляр A, либо его подкласс. Вы можете использовать подкласс A в другом контексте, но основная функциональность, предоставляемая типом A, не изменяется.

Я не могу представить себе хороший пример, когда все методы являются окончательными. Обычно я вижу комбинацию методов final в сочетании с методами abstract. В таких случаях конечные методы реализуют алгоритмы, детали которых расширены абстрактными методами.

Рассмотрим невообразимый и довольно подробный (по назначению) пример класса контроля доступа, который замораживает основную логику авторизации (исключение исключения .ie. исключение для кого угодно, если только этот пользователь не авторизован.) Дальнейшие подробности остаются "пустыми", заполнены специализациями классов.

class AccessMonitor {
    abstract AuthorizationMechanism getUnderlyingMechanism();

    final void checkAccess(User user)
    {
         AuthorizationMechanism mechanism = getUnderlyingMechanism()
         if( mechanism.noAccess(user) )
         {
             throw someSecurityException("blah");
         }
         // otherwise, happy camper
    } 
}

class LdapBasedMonitor extends AccessMonitor {
    final AuthorizationMechanism getUnderlyingMechanism()
    {
       return someLdapThingieMajingie;
    } 
}

class DbBasedAuthenticator extends Authenticator {
    final AuthorizationMechanism getUnderlyingMechanism()
    {
       //query some database and make a decision, something something.
    } 
}

В реальной жизни мы обычно видим другие альтернативы по чистому утончению по наследству - на ум приходит составление и делегирование. На самом деле, в общем случае, предпочтете состав/делегирование по наследованию.

Однако это совсем другой предмет (один стоит книгу или две), а пример наследования лучше подходит в этом контексте, чтобы проиллюстрировать мысль о том, что не конечные классы имеют конечные методы.

Этот последний пример иллюстрирует идею наличия непредельного класса со всеми конечными методами (даже если этот пример оставляет место абстрактным методам.) По сравнению с предыдущим в этом же ответе я надеюсь, что вы увидите разница в намерении за этими двумя.

Ответ 7

Простыми словами, могу ли я достичь такого же уровня неизменности, пройдя с любым подходом? Они оба хороши, чтобы объекты были неизменными?

Нет. Если класс String не является окончательным, то кто-то может расширить String и создать подкласс, который изменен. Все разработчики Java теряют способность предполагать, что строки являются потокобезопасными.

Ответ 8

Это зависит от того, как мы определяем неизменяемость. Мы могли бы назвать объект неизменным, если

  • все поля объекта являются окончательными, а те ссылочного типа, которые, как известно, указывают на неизменяемые классы
  • наблюдаемое состояние объекта не должно меняться, когда наблюдаемое определяется
    • доступен через общедоступные методы или
    • доступный через общедоступные методы определенного класса

Если мы используем определение 1, сам класс должен быть окончательным, так как в противном случае подкласс мог бы объявить новое не конечное поле.

Если мы используем определение 2.1, сам класс также должен быть окончательным, поскольку в противном случае он мог бы объявить не конечное поле с геттером и установщиком.

Если мы используем определение 2.2, достаточно, чтобы каждое поле было окончательным или частным, каждый метод окончательный или закрытый, а все существующие методы класса сохраняют неизменность. (Мы можем расслабиться, чтобы включить поля и методы, защищенные пакетом, если мы знаем, что пакет должен быть запечатан, и проверили, что все остальные коды в пакете сохраняют неизменность и инкапсуляцию).

Для безопасности платформы Java, определение 2.2 и описанный выше подход к реализации будут достаточными. Однако было бы сложнее общаться, реализовывать и проверять, чем объявлять сам класс. Поскольку нарушение этого инварианта поставит под угрозу безопасность платформы, использование более простого и надежного подхода кажется разумным.

Ответ 9

Финал аналогичен const в С++, поэтому вы не можете изменить его состояние. Неизменяемым является внутренняя функциональность класса String. Для этого вы можете использовать StringBuilder. Неизменяемые объекты создают новый экземпляр в ОЗУ, когда вы назначаете ему новое значение. Я никогда не изменяю его состояние, и, таким образом, создается новый экземпляр, который считается переданным по ссылке