Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Не обоснованно, на "управляемых" языках. Это downcasting, и там не нормально вниз способ обработать его, по точно причине, которую Вы описали (подклассы обеспечивают больше, чем базовые классы - куда это "больше" прибывает из?). Если Вы действительно хотите подобное поведение для конкретной иерархии, Вы могли бы использовать конструкторов для производных типов, которые возьмут базовый тип в качестве прототипа.
можно было создать что-то с отражением, которое обработало простые случаи (более определенные типы, которые не имеют никакого дополнительного состояния). В целом, просто модернизация для предотвращения проблемы.
Редактирование: Ой, не может записать операторы преобразования между основой/производными типами. Причуда попытки Microsoft "защитить Вас" от себя. А-ч хорошо, по крайней мере, они не где рядом настолько же плохо как Sun.
Это не может работать. Пойдите посмотреть на страницу справки, связанную ошибкой компиляции.
лучшее решение состоит в том, чтобы использовать методы фабрики здесь.
Это не возможно потому что, как Вы собираетесь получить "дополнительное", которое имеет производный класс. Как компилятор знал бы о значении derivedClass1 и не derivedClass2 при инстанцировании его?
я думаю, что Вы действительно ищете, шаблон "фабрика" или подобный, таким образом, можно инстанцировать объектов, действительно не зная явный тип, который это, инстанцируют. В Вашем примере, имея метод "Вставки" был бы интерфейс, которые инстанцируют реализации возвратов фабрики.
Это называют downcasting, и предложение Seldaek для использования "безопасной" версии является звуковым.
Вот довольно достойное описание с примерами кода .
Да - это - запах кода, и в значительной степени закрепляет то, что Ваша цепочка наследования повреждается.
Мой предположение (от ограниченного образца) - то, что Вы сделали бы, чтобы DerivedClass воздействовал на экземпляр SomeBaseClass - так, чтобы "DerivedClass имел , SomeBaseClass", а не "DerivedClass SomeBaseClass". Это известно как "состав пользы по наследованию".
Downcasting имеет смысл, если у Вас есть Объект производного класса, но на это ссылается ссылка типа базового класса, и по некоторым причинам Вы хотите, чтобы он назад был сослан ссылкой типа производного класса. Другими словами, Вы можете удрученный для инвертирования эффекта предыдущего upcasting. Но у Вас не может быть объекта базового класса, на который ссылается ссылка типа производного класса.
Нет, это не возможно. На управляемом языке как C# это просто не будет работать. Время выполнения не позволит его, даже если компилятор пропустит его.
Вы сказали себя, что это кажется глупым:
SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class;
Так спрашивают себя, class
на самом деле экземпляр SomeDerivedClass
? Нет, таким образом, преобразование не имеет никакого смысла. Если необходимо преобразовать SomeBaseClass
в SomeDerivedClass
, то необходимо обеспечить некоторое преобразование, или конструктор или метод преобразования.
Кажется будто для Вашей иерархии классов нужна некоторая работа, все же. В целом это не было должно быть возможным преобразовать экземпляр базового класса в экземпляр производного класса. Должны обычно быть данные и/или функциональность, которые не относятся к базовому классу. Если функциональность производного класса относится весь экземпляры базового класса, то это нужно или свернуть в базовый класс или вытянуть в новый класс, который не является частью иерархии базового класса.
Попробуйте состав вместо наследования!
Это кажется мне как, Вы были бы более обеспеченной передачей экземпляра SomeBaseClass к SomeDerivedClass (который больше не будет получать базовый класс и должен быть переименован как таковой)
public class BooleanHolder{
public bool BooleanEvaluator {get;set;}
}
public class DatabaseInserter{
BooleanHolder holder;
public DatabaseInserter(BooleanHolder holder){
this.holder = holder;
}
public void Insert(SqlConnection connection) {
...random connection stuff
cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
...
}
}
public static void Main(object[] args) {
BooleanHolder h = new BooleanHolder();
DatabaseInserter derClass = new DatabaseInserter(h);
derClass.Insert(new sqlConnection);
}
Выезд http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html (страница 3):
Повторное использование кода через состав Состав обеспечивает альтернативный путь к Apple к реализации Фруктов повторного использования кожицы (). Вместо того, чтобы расширить Фрукты, Apple может содержать ссылку на Фруктовый экземпляр и определить его собственную кожицу () метод, который просто вызывает кожицу () на Фруктах.
Как другие отметили, кастинг, Вы предлагаете, не действительно возможно. Это, возможно, был бы случай, где Шаблон "декоратор" (Возглавляют Первое извлечение) может быть представлен?
Задумывались ли вы об интерфейсе, который в настоящее время будет реализован в вашем базовом и производном классах? Я не знаю, почему вы применяете этот способ, но он может сработать.
я не знаю, почему никто не сказал это, и я могу иметь, отсутствуют, что-то кроме вас может использовать в качестве ключевого слова и если необходимо сделать если использование оператора если.
SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
;
- редактирование я задал этот вопрос давно
,