2017-01-05 2 views
-2

Я использую Java 8 и Spring. Недавно у меня был странный (для меня) вопрос. В принципе, у меня есть два класса: 1. Это базовый класс:равно нулю между базовым и расширенным классами

public BaseClass { 
    private int variableA; 

    public BaseClass() { 
     /* this is an empty costructor */ 
    } 

    public BaseClass(int a) { 
     this.variableA = a; 
    } 

    /* getter and setter method */ 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) { 
      return true; 
     } 
     if (o == null || getClass() != o.getClass()) { 
      return false; 
     } 
     BaseClass that = (BaseClass) o; 
     /* (HERE) */ 
     return variableA == that.variableA; 
    } 
} 

2. @Configuration класс, который расширяет базовый класс:

@Configuration 
@ConfigurationProperties(prefix = "config") 
@RefreshScope //org.springframework.cloud.context.config 
public MyClass extends BaseClass { 
    private int variableB; 

    /* getter and setter method */ 
} 

Все, что я хочу, чтобы проверить, два класса равны, рассматривая только переменные в baseClass. Пример Метод

public boolean areTheyEqual(BaseClass a, MyClass b) { 
    return a.equals(b); 
} 

В методе areTheyEqual классы a и b правильно заполненной. Когда вы смотрите на BaseClass.equals в строку, где написано (HERE): в этом пункте у меня есть BaseClass, созданный с MyClass. Это не NullPointer, но variableA равно 0 (в MyClass установлено некоторое значение). Я не знаю почему!

но

если изменить метод areTheyEqual к:

public boolean areTheyEqual(BaseClass a, MyClass b) { 
    return a.equals(new BaseClass(b)); 
} 

все работает отлично. Мне действительно интересно, почему. Это какая-то проблема, которая, используя equals Я лижу @Configuration класс MyClass для Object, а затем в BaseClass?

РЕДАКТИРОВАТЬ 1: Пример:

@Component 
public class Example { 
    private MyClass myClass; 
    private BaseClass baseClass; 

    @Autowired 
    public Example(MyClass myClass) { 
     this.myClass = myClass; 
     this.baseClass = new BaseClass(myClass); 
    } 

    @Scheduled 
    private void checkMe() { 
     if(!areTheyEqual()) { 
      /* do something */ 
     } 
    } 

    private boolean areTheyEqual() { 
     /* baseClass.variableA == 2 AND myClass.variableA == 2 */ 
     return baseClass.equals(myClass); 
    } 
} 

В моем вопросе не важно, что реализация equals (кстати метод генерируется Intellij).

Мое определение «прекрасно работает» является: 1. Когда variableA в BaseClass такая же, как variableA в MyClass тогда equals возвращает истину 2. Если нет, то 1. ложно

+1

Вы можете показать нам код равных PLS –

+1

Мы не можем ответить на это, потому что слишком много кода отсутствует, и мы не знаем, что такое определение «отлично работает». Что вы подразумеваете под «в« MyClass »было установлено какое-то значение»? Где он был установлен, и как? Ваш вопрос совершенно неясен. – ajb

+0

Покажите свой метод равным в 'BaseClass' – additionster

ответ

0

С небольшим количеством информации, полученной, наиболее вероятная причина, кажется, вы пересматривал же приватные переменную variableA в подклассе, например:

public class BaseClass { 
    private int variableA; 

    public BaseClass (int a) { 
     this.variableA = a; 
    } 
} 

public class MyClass extends BaseClass { 
    private int variableA; 

    public MyClass (int a) { 
     this.variableA = a; 
    } 
} 

Если вы сделаете это, базовый класс переменный будет оставаться 0 в экземпляре подкласса, но вы я все еще вижу, что он правильно установил переменную под названием variableA, если вы смотрите на подкласс. Если вы добавите его в суперкласс, переменная базового класса станет видимой, показывая 0.

+0

в BaseClass является переменной A, а MyClass - переменной B. Здесь нет переопределения. –

2

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

Затем вы получаете то, о чем просите.В вашем equals реализации, есть утверждение:

if (o == null || getClass() != o.getClass()) { 
    return false; 
} 

, который подразумевает, что два объект может быть только равным, если они имеют точно такой же класс, поэтому экземпляр MyClass не может быть равен прямой инстанцией BaseClass, который не является экземпляром MyClass.

Если вы хотите, чтобы рассматривать все случаи BaseClass и его подклассы одинаково, независимо от их фактического типа, вы должны изменить это заявление

if (o == null || ! (o instanceof BaseClass)) { 
    return false; 
} 

Оператор instanceof принимает экземпляры подклассов указанного типа. Вам не нужно проверять тип this, тогда как это подразумевается, что this instanceof BaseClass всегда true.

Обратите внимание, что в отличие от вызова o.getClass(), instanceof также обрабатывает null правильно, так что можно также уменьшить заявление

if (! (o instanceof BaseClass)) { 
    return false; 
} 

Но это решение стиля кодирования, следует ли использовать более простую форму или явный null тест.

Кстати, когда ваше намерение состоит в том, что все BaseClass экземпляры имеют такое же определение равенства, независимо от фактического типа их (суб), вы должны сделать equals метод final, для ясности.

Смежные вопросы