1. Передача по значению и по ссылке
Прежде чем говорить о передаче по значению и передаче по ссылке, узнайте, что такое типы данных Java.
Типы данных Java
В Java есть два типа типов данных: примитивные типы и объектные типы. Соответственно, переменные также имеют два типа: примитивные типы и ссылочные типы.
Основные типы включаютbyte
,short
,int
,long
,char
,float
,double
,boolean
Эти восемь основных типов данных,
Переменная базового типа сохраняет исходное значение, то есть значение, которое она представляет, является самим значением. Сегмент данных, хранящийся в памяти стека, поскольку он хранится по значению, может быть напрямую доступен и изменен. Исходное значение обычно соответствует область стека в памяти.
Ссылочные типы включают类类型
,接口类型
и数组
Эталонное значение сохраняется, и эталонное значение указывает на адрес области памяти. Представляет ссылку на объект, а не сам объект. Сам объект хранится по адресу, представленному этим эталонным значением. Объект, на который делается ссылка, соответствует куче памяти в памяти.
Разница между базовым типом и ссылочным типом переменной
При объявлении базового типа данных система выделяет для него место, независимо от того, назначен он или нет, виртуальная машина при его объявлении выделит 4-байтовую область памяти. Ссылочный тип данных отличается, он только выделяет ссылочное пространство для переменной при ее объявлении, а не выделяет пространство для данных.
Когда объявлен тип String, пространство для данных не выделяется, только размер ссылки 4 байта в области стека, а в области кучи памяти не выделяется.
基本类型
Переменная值传递
;引用类型
Переменные
передать по значению
При вызове метода фактический параметр передает свое значение соответствующему формальному параметру, а исходное значение, полученное функцией, является копией.В это время в памяти находятся два равнозначных базовых типа, а именно фактический параметр и формальный параметр, и все операции в следующих методах. Стоит изменить формальный параметр и не влияет на значение фактического параметра.
пройти по ссылке
Также широко известен как сквозной адрес. При вызове метода ссылка (адрес, а не значение параметра) фактического параметра передается соответствующему формальному параметру в методе, а адрес памяти исходного значения, полученного функцией
При выполнении метода содержимое формального параметра и фактического параметра совпадают, и требуется только один и тот же адрес памяти.Операция ссылки при выполнении метода повлияет на фактический объект.
Во-вторых, что такое глубокая и неглубокая копия.
Как поверхностное копирование, так и глубокое копирование являются операциями над существующим объектом. Система компиляции автоматически вызывает конструктор, конструктор копирования. Если пользователь не определяет конструктор копирования, будет вызван конструктор копирования по умолчанию.
В java при использовании = для выполнения операций присваивания для базовых типов данных фактически копируется его значение, но для объектов присваивание фактически указывает ссылку на объект, а ссылка исходного объекта передается в прошлое, они на самом деле по-прежнему указывают на объект.
заключить:
1. Поверхностная копия: базовый тип данных передается по значению, а ссылочный тип данных копируется по ссылке.Это поверхностная копия.
метод клонирования в java
как создаются объекты
В языке java есть несколько способов создания объектов?
1. Используйте новую операцию для создания объекта
2. Используйте метод клонирования для копирования объекта
Создание объекта с помощью новой операции предназначено для выделения памяти. Когда программа получает только новый оператор, она сначала смотрит на тип, стоящий за новым оператором, потому что, зная тип, можно узнать, сколько памяти нужно выделить. После выделения памяти вызовите конструктор для заполнения полей объекта, что называется инициализацией объекта. После того, как объект завершен, ссылка может быть выпущена наружу, и объектом можно манипулировать, используя эту ссылку снаружи.
На первом этапе клон похож на новый тем, что выделяет память.При вызове метода клона выделенная память совпадает с исходным объектом (то есть объектом, вызывающим метод клонирования), а затем использует соответствующий поля в исходном объекте для заполнения нового поля объекта, после завершения заполнения метод клонирования возвращается, может быть создан новый идентичный объект, и ссылка на этот новый объект публикуется снаружи.
мелкая копия
Сначала рассмотрим пример мелкой копии.
Сначала создайте класс человека, который является интерфейсом Cloneable, и переопределите метод clone().
package com.java.test;
public class Person implements Cloneable {
public String name;
public int age;
public Man man=new Man();
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args){
Person person=new Person();
person.name="法法";
person.age=24;
Person cloneperson=(Person)person.clone();
System.out.println("person==cloneperson :"+(person==cloneperson));
System.out.println("person hash :"+person.hashCode());
System.out.println("person hash :"+cloneperson.hashCode());
System.out.println("person.man==cloneperson.man :"+(person.man ==cloneperson.man));
System.out.println("person.man hash :"+(person.man.hashCode()));
System.out.println("cloneperson.man hash :"+(cloneperson.man.hashCode()));
}
}
class Man implements Cloneable{
public String name;
public int age;
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
输出
person==cloneperson :false
person hash :2039796785
person hash :57283044
person.man==cloneperson.man :true
person.man hash :1971244528
cloneperson.man hash :1971244528
Видно, что используя метод клонирования, по разнице между == и hashCode видно, что метод клонирования действительно носит новый объект.
В приведенном выше коде видно, что значения адреса человека двух объектов Person одинаковы, что указывает на то, что объекты человека двух объектов указывают на один и тот же объект, то есть на поверхностную копию.
Если значения адреса человека двух объектов различны, это означает, что они указывают на разные объекты, то есть при копировании объекта Person одновременно копируется объект man, то есть глубокая копировать.
глубокая копия
Теперь, когда вы узнали о методе clone(), вы можете сделать только неглубокую копию текущего объекта, а ссылочный тип все еще передает ссылку.
Итак, как сделать глубокую копию?
Есть два часто используемых решения:
- Сериализация (сериализация) этого объекта, а затем десериализация его обратно, вы можете получить этот новый объект, ничего кроме правил сериализации нужно написать самим.
- Продолжайте использовать метод clone().Поскольку метод clone() принадлежит нам, чтобы переписать его, мы можем снова клонировать() переменные ссылочного типа в нем.
Продолжайте переписывать приведенную выше демонстрацию, пусть ChildClass также реализует интерфейс Cloneable.
package com.java.test;
public class Person implements Cloneable {
public String name;
public int age;
public Man man=new Man();
public Object clone(){
try {
Person p=(Person) super.clone();
p.man=(Man)this.man.clone();
return p;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args){
Person person=new Person();
person.name="fafa";
person.age=24;
Person cloneperson=(Person)person.clone();
System.out.println("person==cloneperson :"+(person==cloneperson));
System.out.println("person hash :"+person.hashCode());
System.out.println("person hash :"+cloneperson.hashCode());
System.out.println("person.man==cloneperson.man :"+(person.man ==cloneperson.man));
System.out.println("person.man hash :"+(person.man.hashCode()));
System.out.println("cloneperson.man hash :"+(cloneperson.man.hashCode()));
}
}
class Man implements Cloneable{
public String name;
public int age;
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
вывод
person==cloneperson :false
person hash :1942571857
person hash :611315258
person.man==cloneperson.man :false
person.man hash :813773958
cloneperson.man hash :1923048010
Можно видеть, что человек также копируется один раз, что на самом деле является поверхностной копией Person, но для Person это глубокая копия.
Суммировать
Фактическая мелкая копия и глубокая копия являются только относительными.Если в объекте есть только базовый тип данных, то метод clone() используется для получения глубокой копии объекта, и если в нем есть ссылочный тип данных, затем используйте clone(). Этот метод представляет собой неглубокую операцию копирования.
Клон может не очень часто использоваться при разработке обычных проектов, но различие между глубоким и поверхностным копированием даст нам более глубокое понимание структуры памяти Java и режима работы. Глубокое копирование и тщательное глубокое копирование при создании неизменяемых объектов могут оказывать незначительное влияние на программу и определять, действительно ли неизменяемые объекты, которые мы создаем, являются неизменяемыми.