Не передавайте свою основную форму в качестве аргумента в Application.Run
:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm frmMain = new MainForm();
frmMain.Show();
Application.Run();
Таким образом, вы сможете закрыть ее при показе другой формы:
private void btnSubmit_Click(object sender, EventArgs e)
{
frmData QS = new frmData();
QS.Show();
this.Close();
}
To закрыть приложение, которое вы должны использовать
Application.Exit();
Я просто заметил, что вы ссылались на мою статью .
Java Spec говорит, что все в Java является передачей по значению. В Java нет такой вещи, как «pass-by-reference».
Ключом к пониманию этого является то, что что-то вроде
Dog myDog;
является not собака; это на самом деле указатель для собаки.
Что это значит, когда у вас есть
Dog myDog = new Dog("Rover");
foo(myDog);
, вы по существу передаете адрес созданного объекта Dog
к методу foo
.
(я говорю, по сути, потому, что указатели Java не являются прямыми адресами, но проще всего их так думать)
Предположим, что объект Dog
находится по адресу памяти 42. Это означает, что мы передаем метод 42.
, если метод был определен как
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
let's посмотрите, что происходит.
someDog
установлен на значение 42 someDog
, после чего он Dog
указывает на точки к объекту Dog
по адресу 42), что Dog
(тот по адресу 42) предлагается изменить свое имя на Max Dog
. Предположим, что он находится по адресу 74, мы присваиваем параметру someDog
значение 74 Dog
, которое указывает (объект Dog
по адресу 74), что Dog
(тот, который находится по адресу 74), предлагается изменить его имя на Rowlf . Теперь давайте подумаем о том, что происходит вне метода: / g28]
Изменено myDog
?
Имеется ключ.
Помня, что myDog
является указателем , а не фактический Dog
, ответ НЕТ. myDog
все еще имеет значение 42; он все еще указывает на оригинал Dog
(но обратите внимание, что из-за строки «AAA» его имя теперь «Макс» - все тот же Dog, значение myDog
не изменилось.)
Совершенно верно для следовать за адресом и изменять то, что находится в конце его; что не изменяет переменную.
Java работает точно так же, как C. Вы можете назначить указатель, передать указатель методу, следовать указателю в методе и изменить данные, на которые указали. Тем не менее, вы не можете изменить, где находится этот указатель.
В C ++, Ada, Pascal и других языках, поддерживающих pass-by-reference, вы можете фактически изменить переданную переменную.
Если у Java была семантика по-ссылке, метод foo
, который мы определили выше, изменился бы там, где myDog
указывал, когда он назначил someDog
в строке BBB.
Подумайте о контрольных параметрах как как псевдонимы для переданной переменной. Когда этот псевдоним назначается, то и переменная, которая была передана.
Я создал поток, посвященный этим типам вопросов для любых языков программирования здесь .
Также упоминается Java . Вот краткое резюме:
Различие, или, возможно, только то, как я помню, поскольку я был под тем же впечатлением, что и исходный плакат, таков: Java всегда проходит по значению. Все объекты (в Java, все, кроме примитивов) в Java - это ссылки. Эти ссылки передаются по значению.
Java передает параметры по VALUE и по значению ONLY.
Чтобы сократить длинный короткий текст:
Для тех, кто приходит из C #: нет параметра «out» .
Для тех, кто приходит из PASCAL: нет параметра «var».
blockquote>Это означает, что вы не можете изменить ссылку с самого объекта, но можете всегда изменяйте свойства объекта.
Обходным путем является использование параметра
StringBuilder
вместоString
. И вы всегда можете использовать массивы!
you can't change the reference from the object itself
– sakhunzai
30 March 2017 в 05:41
Java имеет значение только по значению. Очень простой пример для проверки этого.
public void test() {
MyClass obj = null;
init(obj);
//After calling init method, obj still points to null
//this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
objVar = new MyClass();
}
obj
(null
) передано на init
, а не на ссылку obj
.
– David Schwartz
10 June 2017 в 23:24
В принципе, переназначение параметров объекта не влияет на аргумент, например,
private void foo(Object bar) {
bar = null;
}
public static void main(String[] args) {
String baz = "Hah!";
foo(baz);
System.out.println(baz);
}
будет печатать "Hah!"
вместо null
. Причина этого в том, что bar
является копией значения baz
, что является лишь ссылкой на "Hah!"
. Если бы это была фактическая ссылка, то foo
изменила бы baz
на null
.
Java всегда передается по значению. К сожалению, они решили назвать местоположение объекта «ссылкой». Когда мы передаем значение объекта, мы передаем ему ссылку . Это запутывает новичков.
Это выглядит следующим образом:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true
aDog.getName().equals("Fifi"); // false
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
В приведенном выше примере aDog.getName()
все равно вернет "Max"
. Значение aDog
в main
не изменяется в функции foo
с Dog
"Fifi"
, поскольку ссылка на объект передается по значению. Если он был передан по ссылке, то aDog.getName()
в main
вернет "Fifi"
после вызова foo
.
Аналогично:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
В выше, Fifi
является именем собаки после вызова foo(aDog)
, потому что имя объекта было установлено внутри foo(...)
. Любые операции, выполняемые foo
на d
, таковы, что для всех практических целей они выполняются на самом aDog
(кроме случаев, когда d
изменен, чтобы указать на другой экземпляр Dog
, например d = new Dog("Boxer")
), .
Я думал, что внес свой ответ, чтобы добавить более подробную информацию из Спецификаций.
Во-первых, В чем разница между передачей по ссылке или передачей по значению?
Передача по ссылке означает, что параметр вызываемых функций будет таким же, как переданный аргумент вызывающих (а не значение, а идентификатор - сама переменная).
Передача по значению означает, что параметр вызываемых функций будет копией переданного аргумента вызывающих.
blockquote>Или из википедии, на тему прохода -by-reference
При оценке пошаговой ссылки (также называемой pass-by-reference), функция получает неявную ссылку на переменную, используемую как аргумент, а не копией его стоимости. Это обычно означает, что функция может изменять (т. Е. Назначать) переменную, используемую как аргумент, - то, что будет видно ее вызывающей стороне.
blockquote>При вызове по умолчанию вычисляется выражение аргумента, и результирующее значение привязывается к соответствующей переменной в функции [...]. Если функция или процедура могут назначать значения своим параметрам, назначается только ее локальная копия [...].
blockquote>Во-вторых, нам нужно знать, что использует Java в своих вызовах метода , Спецификация языка Java указывает
При вызове метода или конструктора (§15.12) значения фактических выражений аргументов инициализируют вновь созданные переменные параметра, каждый из которых объявленный тип перед выполнением тела метода или конструктора.
blockquote>Таким образом, он присваивает (или связывает) значение аргумента соответствующей переменной параметра.
Каково значение аргумента?
Рассмотрим ссылочные типы, спецификация Java Virtual Machine Specification
Существует три типа ссылочных типов: типы классов, типы массивов и типы интерфейсов. Их значения - это ссылки на динамически созданные экземпляры классов, массивы или экземпляры классов или массивы, которые реализуют интерфейсы соответственно.
blockquote>В спецификации языка Java также указано
Опорные значения (часто только ссылки) являются указателями на эти объекты и специальной нулевой ссылкой, которая ссылается на отсутствие объекта.
blockquote>Значение аргумента ( определенного ссылочного типа) является указателем на объект. Обратите внимание, что переменная, вызов метода с типом возвращаемого типа ссылочного типа и выражение создания экземпляра (
new ...
) все решаются для значения ссылочного типа.Итак
public void method (String param) {} ... String var = new String("ref"); method(var); method(var.toString()); method(new String("ref"));
все связывают значение ссылки с экземпляром
String
с вновь созданным параметром метода,param
. Это именно то, что описывает определение pass-by-value. Таким образом, Java является передачей по значению.Тот факт, что вы можете следовать ссылке для вызова метода или доступа к полю ссылочного объекта, совершенно не имеет отношения к разговору. Определение pass-by-reference было
Это обычно означает, что функция может изменять (т. Е. Присваивать) переменную, используемую как аргумент, - то, что будет видно ее вызывающей стороне.
blockquote>В Java изменение переменной означает ее повторное назначение. В Java, если вы переназначили переменную в методе, она останется незамеченной для вызывающего. Изменение объекта, на которое ссылается переменная, является совершенно другой концепцией.
Примитивные значения также определены в Спецификации виртуальной машины Java, здесь . Значение типа представляет собой соответствующее значение интеграла или с плавающей запятой, соответствующим образом закодированное (8, 16, 32, 64 и т. Д.).
Короче говоря, объекты Java обладают некоторыми очень своеобразными свойствами.
В общем, Java имеет примитивные типы (int
, bool
, char
, double
и т. д.), которые передаются непосредственно по значению. Тогда у Java есть объекты (все, что происходит от java.lang.Object
). Объекты на самом деле всегда обрабатываются посредством ссылки (ссылка является указателем, который вы не можете коснуться). Это означает, что по сути объекты передаются по ссылке, так как ссылки обычно не интересны. Тем не менее, это означает, что вы не можете изменить, на какой объект указывается, поскольку сама ссылка передается по значению.
Звучит ли это странно и запутанно? Рассмотрим, как C реализует передачу по ссылке и передает значение. В C по умолчанию принято передать значение. void foo(int x)
передает значение int по значению. void foo(int *x)
- это функция, которая не хочет int a
, а указатель на int: foo(&a)
. Можно было бы использовать это с оператором &
для передачи адреса переменной.
Возьмите это на C ++, и у нас есть ссылки. Ссылки в основном (в этом контексте) синтаксического сахара, которые скрывают указательную часть уравнения: void foo(int &x)
вызывается foo(a)
, где сам компилятор знает, что это ссылка и адрес без ссылки a
должен быть принят. В Java все переменные, относящиеся к объектам, фактически относятся к ссылочному типу, фактически вызывая вызов по ссылке для большинства целей и целей без мелкозернистого управления (и сложности), предоставляемого, например, C ++.
Я всегда думаю об этом как «проход по копии». Это копия значения, будь она примитивной или справочной. Если это примитив, это копия битов, которые являются значением, и если это объект, то это копия ссылки.
public class PassByCopy{
public static void changeName(Dog d){
d.name = "Fido";
}
public static void main(String[] args){
Dog d = new Dog("Maxx");
System.out.println("name= "+ d.name);
changeName(d);
System.out.println("name= "+ d.name);
}
}
class Dog{
public String name;
public Dog(String s){
this.name = s;
}
}
вывод java PassByCopy:
< blockquote>name = Maxx name = Fido
blockquote>Примитивные классы-оболочки и строки неизменяемы, поэтому любой пример с использованием этих типов не будет работать так же, как другие типы / объекты.
Нет, он не проходит по ссылке.
Java передается по значению в соответствии с Спецификацией языка Java:
При вызове метода или конструктора (§15.12 ), значения фактических выражений аргументов инициализируют вновь созданные переменные параметра, каждый из объявленного типа, перед выполнением тела метода или конструктора. Идентификатор, который появляется в DeclaratorId, может использоваться как простое имя в теле метода или конструктора для ссылки на формальный параметр .
blockquote>
В java все ссылается, поэтому, когда у вас есть что-то вроде: Point pnt1 = new Point(0,0);
Java делает следующее:
[/g7]
Java не передает аргументы метода по ссылке; он передает их по значению. Я буду использовать пример из этого сайта :
public static void tricky(Point arg1, Point arg2) {
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args) {
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X1: " + pnt1.x + " Y1:" + pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
}
Поток программы:
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
Создание двух разных объектов Point с двумя различными ссылками , [/g8]
System.out.println("X1: " + pnt1.x + " Y1: " +pnt1.y);
System.out.println("X2: " + pnt2.x + " Y2: " +pnt2.y);
System.out.println(" ");
Как и ожидалось, выход будет:
X1: 0 Y1: 0
X2: 0 Y2: 0
В этой строке «pass-by-value» переходит в игру ...
tricky(pnt1,pnt2); public void tricky(Point arg1, Point arg2);
Ссылки pnt1
и pnt2
передаются по значению сложному методу, что означает, что теперь ваши ссылки pnt1
и pnt2
имеют свои copies
с именем arg1
и arg2
. Так же pnt1
и arg1
указывают на тот же объект. (То же самое для pnt2
и arg2
) [/g9]
В методе tricky
:
arg1.x = 100;
arg1.y = 100;
[/g10]
Далее в методе tricky
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
Здесь вы сначала создаете новую ссылку temp
Point, которая будет point в том же месте, что и arg1
справка. Затем вы перемещаете ссылку arg1
в точку в то же место, что и arg2
. Наконец, arg2
будет point в том же месте, что и temp
.
[/g11]
Отсюда область действия tricky
метод ушел, и вы больше не имеете доступа к ссылкам: arg1
, arg2
, temp
. Но важно отметить, что все, что вы делаете с этими ссылками, когда они «в жизни», будет постоянно влиять на объект, на который они указывают .
Итак, после выполнения метода tricky
, когда вы вернетесь к main
, у вас есть такая ситуация: [/g12]
Итак, теперь полное выполнение программы будет be:
X1: 0 Y1: 0
X2: 0 Y2: 0
X1: 100 Y1: 100
X2: 0 Y2: 0
arg1.x = 1; arg1.y = 1; arg2.x = 2; arg2.y = 2;
, так как arg1 теперь держит pnt2 refrence и arg2, удерживая теперь ссылку pnt1, поэтому его печать X1: 2 Y1: 2 X2: 1 Y2: 1
– Shahid Ghafoor
20 December 2016 в 02:29
Насколько я знаю, Java знает только вызов по значению. Это означает, что для примитивных типов данных вы будете работать с копией и для объектов, которые будут работать с копией ссылки на объекты. Однако я думаю, что есть некоторые подводные камни; например, это не сработает:
public static void swap(StringBuffer s1, StringBuffer s2) {
StringBuffer temp = s1;
s1 = s2;
s2 = temp;
}
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("Hello");
StringBuffer s2 = new StringBuffer("World");
swap(s1, s2);
System.out.println(s1);
System.out.println(s2);
}
Это заполнит Hello World, а не World Hello, потому что в функции swap вы используете копии, которые не влияют на ссылки в основном. Но если ваши объекты не являются неизменяемыми, вы можете изменить их, например:
public static void appendWorld(StringBuffer s1) {
s1.append(" World");
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("Hello");
appendWorld(s);
System.out.println(s);
}
. В командной строке будет заполняться Hello World. Если вы измените StringBuffer на String, он произведет только Hello, потому что String неизменен. Например:
public static void appendWorld(String s){
s = s+" World";
}
public static void main(String[] args) {
String s = new String("Hello");
appendWorld(s);
System.out.println(s);
}
Однако вы можете сделать оболочку для String, подобную этой, которая позволила бы ей использовать ее со строками:
class StringWrapper {
public String value;
public StringWrapper(String value) {
this.value = value;
}
}
public static void appendWorld(StringWrapper s){
s.value = s.value +" World";
}
public static void main(String[] args) {
StringWrapper s = new StringWrapper("Hello");
appendWorld(s);
System.out.println(s.value);
}
edit: я считаю, что это также причина использования StringBuffer, когда дело доходит до «добавления» двух строк, потому что вы можете модифицировать исходный объект, который не может быть с неизменяемыми объектами, такими как String.
swap(a, b)
, что (1) свопы a
и b
из POV вызывающего, (2) являются агностическими типами, насколько допускается статическая типизация (то есть использование его другим типом ничего не требует больше, чем изменение объявленных типов a
и b
), и (3) не требует, чтобы вызывающий ящик явно передавал указатель или имя, тогда язык поддерживает передачу по ссылке.
– cHao
17 December 2013 в 23:24
Java всегда передает аргументы по значению NOT по ссылке.
Позвольте мне объяснить это с помощью примера :
public class Main{
public static void main(String[] args){
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a){
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c){
c.setAttribute("c");
}
}
объясните это поэтапно:
f
типа Foo
и присвоение ее новому объекту типа Foo
с атрибутом "f"
. Foo f = new Foo("f");
[/g1] Foo
с именем a
и изначально назначена null
. public static void changeReference(Foo a)
[/g2] changeReference
, ссылка a
будет назначена объекту, который передается в качестве аргумента. changeReference(f);
[/g3] b
типа Foo
и присвоение ее новому объекту типа Foo
с атрибутом "b"
. Foo b = new Foo("b");
[/g4] a = b
переназначает ссылку a
NOT f
объекту, чей его атрибут "b"
. [/g5] modifyReference(Foo c)
, для объекта с атрибутом "f"
создается и назначается ссылка c
. [/g6] c.setAttribute("c");
изменит атрибут объекта, на который указывает ссылка c
, и это тот же объект, на который указывает ссылка f
. [/g7] Надеюсь, теперь вы понимаете, как объекты передачи в качестве аргументов работают в Java:)
a
указывает на тот же объект, что и f
(и никогда не получает свою собственную копию объекта f
указывает на), любые изменения в объекте, выполненные с использованием a
, должны измените f
(так как они оба работают с одним и тем же объектом), поэтому в какой-то момент a
должен получить свой собственный copy i> объекта f
.
– Mr D
15 July 2013 в 20:08
Java всегда проходит по значению, без каких-либо исключений, когда-либо.
Итак, как же все могут быть смущены этим и считают, что Java проходит по ссылке или думает, что они пример Java, действующий как пропуск по ссылке? Ключевым моментом является то, что Java никогда не обеспечивает прямой доступ к значениям самих объектов , в любых обстоятельствах. Единственный доступ к объектам через ссылку к этому объекту. Поскольку объекты Java всегда всегда доступны через ссылку, а не напрямую, обычно говорят о полях и переменных и аргументах метода как объекты , когда педантично они являются только ссылками на объекты . Путаница проистекает из этого (строго говоря, неправильного) изменения в номенклатуре.
Итак, при вызове метода
int
, long
, и т. д.), пропуск по значению - фактическое значение примитива (например, 3). Итак, если у вас есть doSomething(foo)
и public void doSomething(Foo foo) { .. }
, два Foos скопировали ссылки , которые указывают на тот же объектов.
Естественно, что передача по значению ссылки на объект очень похожа на (и на практике неотличима от), передавая объект по ссылке.
Чтобы показать контраст, сравните следующие фрагменты C ++ и Java :
В C ++: Примечание: Утечки с ошибками в коде! Но это демонстрирует точку.
void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
val = 7; // Modifies the copy
ref = 7; // Modifies the original variable
obj.SetName("obj"); // Modifies the copy of Dog passed
objRef.SetName("objRef"); // Modifies the original Dog passed
objPtr->SetName("objPtr"); // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to
// by the original pointer passed.
objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}
int main()
{
int a = 0;
int b = 0;
Dog d0 = Dog("d0");
Dog d1 = Dog("d1");
Dog *d2 = new Dog("d2");
Dog *d3 = new Dog("d3");
cppMethod(a, b, d0, d1, d2, d3);
// a is still set to 0
// b is now set to 7
// d0 still have name "d0"
// d1 now has name "objRef"
// d2 now has name "objPtr"
// d3 now has name "newObjPtrRef"
}
В Java,
public static void javaMethod(int val, Dog objPtr)
{
val = 7; // Modifies the copy
objPtr.SetName("objPtr") // Modifies the original Dog pointed to
// by the copy of the pointer passed.
objPtr = new Dog("newObjPtr"); // Modifies the copy of the pointer,
// leaving the original object alone.
}
public static void main()
{
int a = 0;
Dog d0 = new Dog("d0");
javaMethod(a, d0);
// a is still set to 0
// d0 now has name "objPtr"
}
Java имеет только два типа передачи: по значению для встроенных типов и по значению указатель на типы объектов.
Dog **objPtrPtr
к примеру C ++, таким образом мы можем изменить то, что указатель & quot; указывает на & quot ;.
– Amro
2 July 2014 в 04:59
В Java передаются только ссылки и передаются по значению:
Все аргументы Java передаются по значению (ссылка копируется при использовании метода):
В случай примитивных типов, поведение Java просто: значение копируется в другом экземпляре примитивного типа.
В случае объектов это одно и то же: переменные объекта являются указателями (ведрами), содержащими только адрес объекта который был создан с использованием «нового» ключевого слова и скопирован как примитивные типы.
Поведение может отличаться от примитивных типов: поскольку скопированная объектная переменная содержит один и тот же адрес (для одного и того же объекта) контент / члены могут по-прежнему модифицироваться в рамках метода и позже получать доступ снаружи, создавая иллюзию того, что сам объект (содержащий) был передан по ссылке.
Объекты «String» являются идеальным контр-примером для городской легенды, говорящей, что «Объекты передаются по ссылке»:
По сути, в рамках метода вы никогда не будете , чтобы обновить значение строки, переданной как аргумент:
Объект String, содержит символы массивом, объявленным окончательным, который не может быть изменен. Только адрес объекта может быть заменен другим, используя «новый». Использование «нового» для обновления переменной не позволит объекту получить доступ извне, поскольку переменная была первоначально передана по значению и скопирована.
Мне кажется, что спорить о «pass-by-reference vs pass-by-value» не очень полезно.
Если вы говорите: «Java - это pass-by-whatever (reference / value ) ", в любом случае вы не получите полного ответа. Вот еще одна дополнительная информация, которая, мы надеемся, поможет понять, что происходит в памяти.
Курс Crash по стеку / куче прежде, чем мы перейдем к реализации Java: значения идут и выходят из стека с хорошей упорядоченной манерой, например стопку тарелок в столовой. Память в куче (также известная как динамическая память) беспорядочна и дезорганизована. JVM просто находит пространство везде, где может, и освобождает его, поскольку переменные, которые его используют, больше не нужны.
Хорошо. Во-первых, локальные примитивы идут в стек. Таким образом, этот код:
int x = 3;
float y = 101.1f;
boolean amIAwesome = true;
приводит к этому:
[/g0]
Когда вы объявляете и создаете экземпляр объекта. Фактический объект переходит в кучу. Что происходит в стеке? Адрес объекта в куче. Программисты на С ++ назвали бы это указателем, но некоторые разработчики Java против слова «указатель». Без разницы. Просто узнайте, что адрес объекта идет в стек.
Так же:
int problems = 99;
String name = "Jay-Z";
[/g1]
Массив объект, поэтому он также попадает в кучу. А как насчет объектов в массиве? Они получают свое собственное пространство кучи, и адрес каждого объекта попадает внутрь массива.
JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
[/g2]
Итак, что передается, когда вы вызвать метод? Если вы передаете объект, то, что вы фактически передаете, является адресом объекта. Некоторые могут сказать «значение» адреса, а некоторые говорят, что это просто ссылка на объект. Это генезис священной войны между «ссылочными» и «ценностными» сторонниками. То, что вы называете это, не так важно, как вы понимаете, что то, что передается, - это адрес объекта.
private static void shout(String name){
System.out.println("There goes " + name + "!");
}
public static void main(String[] args){
String hisName = "John J. Jingleheimerschmitz";
String myName = hisName;
shout(myName);
}
Создается одна строка, а пространство для нее выделяется в куче и адрес строки сохраняется в стеке и задается идентификатор hisName
, так как адрес второй строки такой же, как и первый, новая String не создается и не выделяется новое пространство кучи, но новый идентификатор созданный в стеке. Затем мы вызываем shout()
: создается новый стек стека и создается новый идентификатор name
и назначается адрес уже существующей строки.
[/g3]
Итак, значение, ссылка? Вы говорите «картофель».
Не могу поверить, что никто еще не упомянул Барбару Лисков. Когда она разработала CLU в 1974 году, она столкнулась с этой же проблемой терминологии, и она придумала термин , разделив (также известный как вызов путем совместного использования объектов и вызов по объекту ) для этого конкретного случая «вызов по значению, где значение является ссылкой».
Вы никогда не можете передавать по ссылке в Java, и одним из очевидных способов является то, что вы хотите вернуть более одного значения из вызова метода. Рассмотрим следующий бит кода в C ++:
void getValues(int& arg1, int& arg2) {
arg1 = 1;
arg2 = 2;
}
void caller() {
int x;
int y;
getValues(x, y);
cout << "Result: " << x << " " << y << endl;
}
Иногда вы хотите использовать тот же шаблон в Java, но вы не можете; по крайней мере, не напрямую. Вместо этого вы можете сделать что-то вроде этого:
void getValues(int[] arg1, int[] arg2) {
arg1[0] = 1;
arg2[0] = 2;
}
void caller() {
int[] x = new int[1];
int[] y = new int[1];
getValues(x, y);
System.out.println("Result: " + x[0] + " " + y[0]);
}
Как было объяснено в предыдущих ответах, в Java вы передаете указатель на массив как значение в getValues
. Этого достаточно, потому что метод затем модифицирует элемент массива, и по соглашению вы ожидаете, что элемент 0 будет содержать возвращаемое значение. Очевидно, вы можете сделать это другими способами, такими как структурирование вашего кода, чтобы это не было необходимо, или создание класса, который может содержать возвращаемое значение или разрешить его установку. Но простой шаблон, доступный вам в C ++ выше, недоступен на Java.
Java передает ссылки на объекты по значению.
Несколько поправок к некоторым сообщениям.
C НЕ поддерживает передачу по ссылке. Он ВСЕГДА проходит по значению. C ++ поддерживает передачу по ссылке, но не является по умолчанию и весьма опасен.
Не имеет значения, какое значение имеет значение Java: примитивный или адрес (примерно) объекта, он ВСЕГДА прошел мимо value.
Если объект Java «ведет себя» так, как он передается по ссылке, это свойство изменчивости и не имеет абсолютно никакого отношения к передающим механизмам.
Я не почему это так запутанно, возможно, потому, что так много «программистов» Java официально не обучены и, следовательно, не понимают, что происходит в памяти?
Java передает ссылки по значению.
Таким образом, вы не можете изменить ссылку, которая будет передана.
Позвольте мне объяснить свое понимание с помощью четырех примеров. Java является pass-by-value, а не pass-by-reference
/ **
Pass By Value
В Java все параметры передаются по значение, т. е. назначение аргумента метода не отображается вызывающему.
* /
Пример 1:
public class PassByValueString {
public static void main(String[] args) {
new PassByValueString().caller();
}
public void caller() {
String value = "Nikhil";
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Результат
output : output
value : Nikhil
valueflag : false
Пример 2:
/ ** * * Pass By Value * * /
public class PassByValueNewString {
public static void main(String[] args) {
new PassByValueNewString().caller();
}
public void caller() {
String value = new String("Nikhil");
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Результат
output : output
value : Nikhil
valueflag : false
Пример 3:
/ ** У этого «Pass By Value» есть ощущение «Pass By Reference»
Некоторые говорят, что примитивные типы и «String» являются «pass by value», а объекты «проходят» по ссылке '.
Но из этого примера мы можем понять, что это infact передается только по значению, имея в виду, что здесь мы передаем ссылку как значение. т.е.: ссылка передается по значению. Вот почему они могут меняться, и все же это верно после локального масштаба. Но мы не можем изменить фактическую ссылку за пределами исходной области. что это означает, показано в следующем примере PassByValueObjectCase2.
* /
public class PassByValueObjectCase1 {
private class Student {
int id;
String name;
public Student() {
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
new PassByValueObjectCase1().caller();
}
public void caller() {
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student);
}
public String method(Student student) {
student.setName("Anand");
return "output";
}
}
Результат
output : output
student : Student [id=10, name=Anand]
Пример 4:
/ **
В дополнение к тому, что упоминалось в примере 3 (PassByValueObjectCase1.java), мы не можем изменить фактическую ссылку вне исходной области. "
Примечание: я не вставляю код для private class Student
. Определение класса для Student
такое же, как в примере 3.
* /
public class PassByValueObjectCase2 {
public static void main(String[] args) {
new PassByValueObjectCase2().caller();
}
public void caller() {
// student has the actual reference to a Student object created
// can we change this actual reference outside the local scope? Let's see
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student); // Will it print Nikhil or Anand?
}
public String method(Student student) {
student = new Student(20, "Anand");
return "output";
}
}
Результат
output : output
student : Student [id=10, name=Nikhil]