Другое событие NullPointerException
возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals
для гарантированного непустого объекта.
Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null
.
Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Вы не должны вкладывать с несколькими использованиями:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
// all three get disposed when you're done
}
Можно соединить операторы использования перед вводными фигурными скобками как так:
using (StreamWriter w1 = File.CreateText("W1"))
using (StreamWriter w2 = File.CreateText("W2"))
{
// code here
}
Вы могли использовать этот синтаксис для сжатия вещей вниз немного:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
}
Это - один из тех редких случаев, где не использование {} для всех блоков имеет смысл, по моему скромному мнению.
Вместо операторов использования вложения можно просто выписать вызовы.Dispose вручную - но Вы почти наверняка пропустите тот в какой-то момент.
Или выполнить FxCop или что-то еще, которое может удостовериться, что все экземпляры типа IDisposable-реализации имеют.Dispose () вызов или соглашение с вложением.
У меня есть используемые решения как Michael Meadows прежде, но его StreamWrapper
код не принимает во внимание, обратились ли эти Dispose()
методы к членским переменным, выдают исключение по той или иной причине, последующее Dispose()
, es не назовут, и ресурсы могли свиснуть. Более безопасный путь к тому для работы:
var exceptions = new List<Exception>();
try
{
this.sr.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
this.bs.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
try
{
this.fs.Dispose();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
можно опустить фигурные скобки, как:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
// use sr, and have everything cleaned up when done.
}
или использование регулярная попытка наконец приблизьтесь:
FileStream fs = new FileStream("c:\file.txt", FileMode.Open);
BufferedStream bs = new BufferedStream(fs);
StreamReader sr = new StreamReader(bs);
try
{
// use sr, and have everything cleaned up when done.
}finally{
sr.Close(); // should be enough since you hand control to the reader
}
Это делает для намного большей сети плюс в строках кода, но материальном усилении в удобочитаемости:
using (StreamWrapper wrapper = new StreamWrapper("c:\file.txt", FileMode.Open))
{
// do stuff using wrapper.Reader
}
, Где StreamWrapper определяется здесь:
private class StreamWrapper : IDisposable
{
private readonly FileStream fs;
private readonly BufferedStream bs;
private readonly StreamReader sr;
public StreamWrapper(string fileName, FileMode mode)
{
fs = new FileStream(fileName, mode);
bs = new BufferedStream(fs);
sr = new StreamReader(bs);
}
public StreamReader Reader
{
get { return sr; }
}
public void Dispose()
{
sr.Dispose();
bs.Dispose();
fs.Dispose();
}
}
С некоторым усилием, StreamWrapper мог быть пересмотрен, чтобы быть более универсальным и допускающим повторное использование.
Нужно отметить, что обычно при создании на основе потоков от другого потока новый поток будет закрывать тот, передаваемый в. Так, для дальнейшего сокращения примера:
using (Stream Reader sr = new StreamReader( new BufferedStream( new FileStream("c:\file.txt", FileMode.Open))))
{
// all three get disposed when you're done
}
Оператор использования является синтаксическим сахаром, который преобразовывает в:
try
{
obj declaration
...
}
finally
{
obj.Dispose();
}
можно явно звонить, Располагают на объектах, но это не будет столь же безопасно, с тех пор, если один из них выдает исключение, ресурсы не будут освобождены правильно.