Другое событие 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));
}
Передайте ref
, если Вы хотите изменить, каков объект:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
После вызова DoSomething, t
не обращается к оригиналу new TestRef
, но относится к совершенно другому объекту.
Это может быть полезно также, если Вы хотите изменить значение неизменного объекта, например, string
. Вы не можете изменить значение string
, как только оно было создано. Но при помощи ref
, Вы могли создать функцию, которая меняет струну для другого, который имеет различное значение.
Редактирование: Поскольку другие люди упомянули. Это не хорошая идея использовать ref
, если это не необходимо. Используя ref
дает свободу метода изменить аргумент в пользу чего-то еще, вызывающие стороны метода должны будут быть кодированы, чтобы гарантировать, чтобы они обработали эту возможность.
кроме того, когда тип параметра является объектом, затем переменные объекта всегда действуют как ссылки на объект. Это означает, что, когда ref
ключевое слово используется, у Вас есть ссылка на ссылку. Это позволяет Вам делать вещи, как описано в примере, данном выше. Но, когда тип параметра является примитивным значением (например, int
), тогда если этому параметру присвоят в рамках метода, то значение аргумента, который был передан в, будет изменено после возвратов метода:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
Необходимо различать "передачу ссылки значением", и "передачу параметра/аргумента ссылкой".
я написал довольно длинная статья о предмете , чтобы избежать необходимости писать тщательно каждый раз, когда это подходит на группах новостей:)
В.NET при передаче любого параметра методу создается копия. В значении типы означают, что любая модификация, которую Вы делаете к значению, в объеме метода и потеряна при выходе из метода.
При передаче Ссылочного типа, копия также сделана, но это - копия ссылки, т.е. теперь у Вас есть ДВЕ ссылки в памяти к тому же объекту. Так, при использовании ссылки для изменения объекта, она изменяется. Но если Вы изменяете саму ссылку - мы должны помнить, что это - копия - тогда, любые изменения также потеряны после выхода из метода.
, Поскольку люди сказали прежде, присвоение является модификацией ссылки, таким образом потерян:
public void Method1(object obj) {
obj = new Object();
}
public void Method2(object obj) {
obj = _privateObject;
}
методы выше не делают изменяет исходный объект.
Немного модификации Вашего примера
using System;
class Program
{
static void Main(string[] args)
{
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(t);
Console.WriteLine(t.Something);
}
static public void DoSomething(TestRef t)
{
t = new TestRef();
t.Something = "Bar";
}
}
public class TestRef
{
private string s;
public string Something
{
get {return s;}
set { s = value; }
}
}
Так как TestRef является классом (которые являются ссылочными объектами), можно изменить содержание внутри t, не передавая его как касательно Однако при передаче t как касательно TestRef может изменить то, к чему относится оригинал t. т.е. заставьте его указать на различный объект.
С ref
можно записать:
static public void DoSomething(ref TestRef t)
{
t = new TestRef();
}
И t будет изменен после того, как метод завершился.
Это похоже на передачу указателя на указатель в C. В.NET это позволит Вам изменять то, что оригинал T отсылает к, лично , хотя я думаю, делаете ли Вы это в.NET, Вы, вероятно, получили вопросы проектирования!
При помощи ref
ключевое слово со ссылочными типами Вы эффективно передаете ссылку на ссылку. Во многих отношениях это совпадает с использованием out
ключевое слово, но с незначительными различиями, что нет никакой гарантии, что метод на самом деле присвоит что-либо ref
'параметр редактора.
При передаче значения, однако, вещи отличаются. Можно вынудить значение быть переданным ссылкой. Это позволяет, Вы, чтобы передать целое число методу, например, и иметь метод изменяете целое число от Вашего имени.
Касательно обозначает, может ли функция достать сам объект, или только его значение.
Передача ссылкой не связывается с языком; это - стратегия привязки параметров рядом с передачей значением, передачей по имени, передачей потребностью и т.д.
заметка на полях А: имя класса TestRef
является ужасно плохим выбором в этом контексте;).