Java - Должны ли частные переменные экземпляра быть доступны в конструкторах с помощью метода получения и установки? - PullRequest
10 голосов
/ 02 апреля 2010

Я знаю, что частные переменные экземпляра доступны через их общедоступные методы получения и установки.

Но когда я генерирую конструкторы с помощью IDE, он инициализирует переменные экземпляра напрямую, а не инициализирует их с помощью методов установки.

Q1. Поэтому я должен изменить сгенерированный IDE код для конструкторов, чтобы инициализировать эти переменные экземпляра через их методы установки.

Q2. Если да, то почему IDE не генерирует код конструкторов таким образом?

============================= РЕДАКТИРОВАНИЕ ================= ======================

  • Я использую Eclipse и Netbeans IDE

  • Это общий вопрос. Но, как спрашивает @Lords, ответ будет зависеть от того, является ли наш конструктор общедоступным или защищенным, или пакетом приватным или приватным?

Ответы [ 7 ]

12 голосов
/ 03 апреля 2010

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

Рассмотрим этот надуманный пример:

class A {
    private int x;

    public A() {
        setX(2);
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getX() {
        return x;
    }
}

class B extends A {
    private int number = 10;

    @Override        
    public void setX(int x) {
        // set x to the value of number: 10
        super.setX(number);
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        // b.getX() should be 10, right?
        System.out.println("B.getX() = " + b.getX());
    }
}

Вывод этой программы:

B.getX() = 0

Причина в том, что B элемент number не инициализируется во время вызова setX, поэтому используется значение по умолчанию 0.

Эта статья содержит более подробное объяснение, как и Effective Java .

2 голосов
/ 02 апреля 2010

Конструкторы для инициализации. Инициализируйте частные переменные экземпляра непосредственно в конструкторе. Методы определяют поведение объекта. Поведение происходит после создания экземпляра / инициализации. Управляйте состоянием переменных вашего экземпляра с помощью методов установки. Это классическое ООП мышление и, вероятно, почему ваша IDE генерирует код, который она делает.

1 голос
/ 02 апреля 2010

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

0 голосов
/ 05 августа 2010

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

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

A1) Хотя вам не нужно инициализировать переменные экземпляра (закрытая строка someString; по умолчанию - null и допустимо), одна из причин этого заключается в том, что значение по умолчанию, назначенное компилятором, может не соответствовать требуемому значению или, что еще хуже неверный (который должен поймать компилятор).

Q2) Предполагая часть выше, каково значение get; задавать; свойства?

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

При всем этом, у вас может быть совершенно веская причина для того, чтобы делать что-то иначе, чем то, что говорит книга или кто-то еще. Всегда есть согласие с «правилом (ами)», и вы должны написать соответствующий код.

0 голосов
/ 02 апреля 2010

Прежде всего initialization != setters (по крайней мере, не всегда)

Но IDE просто хорошо играют с когда-то уважаемым шаблоном дизайна JavaBean Предполагая, что изменения свойств должны происходить через сеттеры.

Итак, это вопрос дизайна. Если ваши классы представляют объекты с чистой ценностью, не повредите при инициализации через = Но если ваши классы могут стать JavaBean, чье изменение свойства больше, чем просто инициализация или назначение, используйте set* вызовов.

0 голосов
/ 02 апреля 2010

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

PS. Я скорее использую сеттеры и геттеры. Как привычка, поддерживающая целостность кода, я чувствую, что кому-то еще будет легче читать, если я сохраню привычки по всему коду.

0 голосов
/ 02 апреля 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...