Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Я думаю, что сделал бы этот [интервал] и этот [строка] средства доступа виртуальный и переопределил бы их в BList/BDictionary. Классы, где средства доступа не имеет смысла, должны бросить NotSupportedException () (возможно, при наличии реализации по умолчанию в BItem).
Это заставляет Ваш код работать таким же образом и дает Вам более читаемую ошибку в случае, если необходимо записать
(BInteger)torrent["info"][0]["files"]["length"];
по ошибке.
Моя рекомендация состояла бы в том, чтобы представить больше абстракций. Я нахожу его путающий, что BItem имеет DecodeFile (), который возвращает BDictionary. Это может быть разумной вещью сделать в домене потока, я не знаю.
Однако я нашел бы API как следующее более разумное:
BFile torrent = BFile.DecodeFile("my.torrent");
int filelength = torrent.Length;
Путем я вижу его, не, все BItems являются наборами, таким образом не, все BItems имеют индексаторы, таким образом, индексатор не должен быть в BItem. Я получил бы другой абстрактный класс из BItem, давайте назовем его BCollection и поместим индексаторы там, что-то как:
abstract class BCollection : BItem {
public BItem this[int index] {get;}
public BItem this[string index] {get;}
}
и сделайте BList, и BDictionary наследовались BCollection. Или Вы могли приложить дополнительные усилия и сделать BCollection универсальным классом.
Если длина файла - что-то, что Вы часто получаете, почему бы не реализовать свойство в классе BDictionary (?)... так, чтобы Вы кодировали, становится:
BDictionary torrent = BItem.DecodeFile("my.torrent");
int filelength = torrent.FileLength;
Тем путем детали реализации скрыты от пользователя.
Сделал Вы рассматриваете парсинг простого "пути", таким образом, Вы могли записать этому этот путь:
BDictionary torrent = BItem.DecodeFile("my.torrent");
int filelength = (int)torrent.Fetch("info.files.0.length");
Возможно, не лучший способ, но удобочитаемость увеличивается (немного)
Вы действительно не должны получать доступ ни к каким производным классам от базового класса, поскольку он в значительной степени повреждает идею ООП. Readibility, конечно, имеет большое значение, но я не обменял бы его на возможность многократного использования. Рассмотрите случай, когда необходимо будет добавить другой подкласс - необходимо будет также обновить базовый класс соответственно.
Если необходимо сделать это, по крайней мере перенестись, это (управляйте доступом к списку) в классе, который имеет сигнатуры методов со строгим контролем типов.
BString GetString(BInteger);
SetString(BInteger, BString);
Примите и возвратите BStrings даже при том, что Вы внутренне храните его в BList BItems. (позвольте мне разделить, прежде чем я сделаю свои 2 B или не 2 B),
Хм. Я на самом деле утверждал бы, что первая строка кодированных более читаема, чем второе - она берет немного дольше для выяснения то, что идет на нее, но его более очевидное, что Вы рассматриваете объекты как BList или BDictionary. Применение методов к абстрактному классу скрывает ту деталь, которая может мешать выяснять то, что на самом деле делает Ваш метод.
Это - просто я
BDictionary torrent = BItem.DecodeFile("my.torrent");int filelength = (BInteger)((BDictionary)((BList)((BDictionary) torrent["info"])["files"])[0])["length"];
Вам не нужен 'поток' броска BDictionary, объявляется как BDictionary
public BItem this[int index]{ get { return ((BList)this)[index]; }}public BItem this[string index]{ get { return ((BDictionary)this)[index]; }}
Они не достигают желаемого результата, поскольку тип возврата является все еще абстрактной версией, таким образом, все еще необходимо бросить.
Переписанный код должен был бы быть
BDictionary torrent = BItem.DecodeFile("my.torrent");int filelength = (BInteger)((BList)((BDictionary)torrent["info"]["files"])[0])["length"];
Который является настолько же плох как первая партия
При представлении дженериков можно постараться не бросать.
class DecodedTorrent : BDictionary<BDictionary<BList<BDictionary<BInteger>>>>
{
}
DecodedTorrent torrent = BItem.DecodeFile("mytorrent");
int x = torrent["info"]["files"][0]["length"];
Хм, но это, вероятно, не будет работать, поскольку типы могут зависеть от пути, Вы берете через структуру.