目录

一、前言

二、何谓对象?

三、何谓对象引用?

四、创建对象

Vehicle veh1 = new Vehicle();

五、参数传值

六、Java Sting

最后!有错误的地方欢迎指正    


一、前言

在java学习中,理解对象以及对象的引用是万里长征的第一步。在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事。而且,现在大量的java学习书籍都将对象以及对象的引用混为一谈,然而实际上它们有着本质的区别。为了帮助更多的java学习者更好的理解,我将自己的学习理解记录下来。今天我们就来一起了解一下对象和对象引用之间的区别和联系。如有理解不全或者错误的地方,欢迎大家批评指正。

 

二、何谓对象?

  在Java中有一句比较流行的话,叫做“万物皆对象”,这是Java语言设计之初的理念之一。要理解什么是对象,需要跟类一起结合起来理解。下面这段话引自《Java编程思想》中的一段原话:

  “按照通俗的说法,每个对象都是某个类(class)的一个实例(instance),这里,‘类’就是‘类型’的同义词。”

  从这一句话就可以理解到对象的本质,简而言之,它就是类的实例,比如所有的动物统称为“动物”,这里的“动物”就是一个类(物种的一种类型),而具体到每个动物,比如狗这个动物,它就是对象,就是“动物”的实例。

三、何谓对象引用?

  我们先看一段话:

  “每种编程语言都有自己的数据处理方式。有些时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C/C++里的指针)来操作对象。所有这些在 Java 里都得到了简化,一切都被视为对象。因此,我们可采用一种统一的语法。“ 尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“引用”(reference)。”  

  这段话来自于《Java编程思想》,很显然,从这段话可以看出对象和对象引用不是一回事,是两个完全不同的概念。举个例子,我们通常会用下面这一行代码来创建一个对象:

Animal animal = new Animal("狗");

     有人会说,这里的animal是一个对象,是Animal类的一个实例。

  也有人会说,这里的animal并不是真正的对象,而是指向所创建的对象的引用。

  到底哪种说法是对的?我们先不急着纠结哪种说法是对的,再看两行代码:

Animal animal;
animal = new Animal("狗");

  这两行代码实现的功能和上面的一行代码是完全一样的。大家都知道,在Java中new是用来在堆上创建对象用的,如果animal是一个对象的话,那么第二行为何还要通过new来创建对象呢?由此可见,animal并不是所创建的对象,是什么?上面的一段话说的很清楚,“操纵的标识符实际上是指向一个对象的引用”,也就是说animal是一个引用,是指向一个Animal类对象的引用。真正创建对象的语句是右边的new Animal("狗");

我们仔细研究一下第二句,找找刚创建的对象叫什么名字?有人说,它叫“Animal”。不对,“Animal”是类(对象的创建模板)的名字。

       一个Animal类可以据此创建出无数个对象,这些对象不可能全叫“Animal”。

       对象连名都没有,没法直接访问它。我们只能通过对象引用来间接访问对象。

       为了形象地说明对象、引用及它们之间的关系,可以做一个或许不很妥当的比喻。对象好比是一只很大的气球,大到我们抓不住它。引用变量是一根绳, 可以用来系汽球。

  再看一个例子:

Animal animal;
animal = new Animal("狗");
animal = new Animal("猫");

  这里让animal先指向了“狗”这个对象,然后又指向了“猫”这个对象。也就是说,Animal animal,这句话只是声明了一个Animal类的引用,它可以指向任何Animal类的实例。

  也就是说,一个引用可以指向多个对象,但是最终一个引用只能指向一个对象!!!而一个对象可不可以被多个引用所指呢?答案当然是可以的。

  比如:

Demo demo1,demo2,demo3;//创建多个对象引用
demo1=new Demo();
demo2=demo1;
demo3=demo2;//创建对象,并被多个对象引用指向

四、创建对象

       Vehicle veh1 = new Vehicle();

通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。

1)右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。

2)末尾new Vehicle()意味着,在对象创建后,为Vehicle类的成员变量分配内存空间,立即调用Vehicle类的构造方法,对刚生成的对象(也就是对那些成员变量)进行初始化。构造方法是肯定有的。如果你没写,Java会给你补上一个默认的构造函数。分配内存后,将计算出的引用值赋给引用变量 Veh1

3)左边的“Vehicle veh 1”创建了一个Vehicle类引用变量。所谓Vehicle类引用,就是以后可以用来指向Vehicle对象的对象引用(简称对象也是可以的,但是实际上是引用变量,指向Vehicle对象。。。)。

4)“=”操作符使对象引用指向刚创建的那个Vehicle对象。

五、参数传值

public static void main(String[] args) {
String x = new String("ab");
change(x);
System.out.println(x);
} public static void change(String s) {
s = "cd";
}

打印结果:ab

在change方法中,参数也是对象,当字符串“ab”被创建,java分配存储字符串对象所需的内存空间。然后,将对象分配给变量x,该变量是被实际分配的引用对象。此引用是该对象被存储在内存的地址。变量x包含一个字符串对象的引用。 x不是引用本身!它是用于存储一个引用(内存地址)的变量。
当把x传给参数s时,s得到的是x的引用值的拷贝也就是副本,在方法体内改变了s指向的对象(也就是s指向了别的对象,牵着气球的绳子换气球了),给s重新赋值后,方法change()创建另一个对象“cd”,它有一个不同的引用。它是被改变的x副本指向“cd”的变量,而不是x引用本身。s与x已经毫无关联,它和x指向了不同的对象,指向ab的s已经被覆盖掉了,没有了!(图片下方的x为文中所说的s)所以不管对s做什么操作,都不会影响x指向的对象,故调用change方法前后x指向的对象内容并未发生改变。

如果再简单化理解 ,就理解为将"ab"这个字符串常量赋值给变量x,方法调用将变量x的值传给形参变量s,将cd赋值给s,变量的本质是什么,就是代替复杂的地址,所以这两个变量其实不是同一个变量,即使它俩同名,我是指形参与实参这里,它们是不同的内存地址,所以形参的改变对实参是无影响的,即使你把void change改为 String change 加return 也没用,因为你没用变量去接收这个值,简单化理解就是把cd返回给了原方法,用原来变量接收了这个值,底层一些就是将"cd"的引用又传给了x,就这样整一圈,又回来了。

 public static void main(String[] args) {
String x = new String("ab");
x=change(x);
System.out.println(x);
} public static String change(String s) {
s = "cd";
System.out.println(s);
return s;
}
}

自行理解吧,我也是自己想出来的,

对基本数据类型来说,你可以用原来的变量去接收这个值。

比如:

public class Person1 {
public static void main(String[] args) {
int p=10;
p=Value(p);
System.out.println(p); }
private static int Value(int p) {
p=p*3;
return p;
}
}

如果我有哪方面是错误理解,请各位大佬指教,谢谢!!

六、Java Sting

在这里要永远记住一点:“String对象一旦被创建就是固定不变的了,对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象”

创建字符串的方式很多,归纳起来有三类:

  • 使用new关键字创建字符串,比如String s1 = new String("abc");这种写编译器会提示你是多余的,除非显式original
  • 直接指定。比如String s2 = "abc";
  • 使用串联生成新的字符串。比如String s3 = "ab" + "c";    《String对象的创建》 String对象的创建也有很多门道,关键是要明白其原理。
  1. 每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的对象引用(即地址)。如果字符串不存在常量池中,就会在字符串常量池中实例化该字符串(也就是创建该字符串对象)并返回这个对象的地址。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串(重要)。
  2. new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则,将使得堆中的字符串永远是池中的子集,导致浪费池的空间)!

JAVA为了提高效率,对String类型进行了特别的处理---为string类型提供了串池  定义一个string类型的变量有两种方式:

String name= "tom ";(String name="t"+"o"+"m"的效果和此处是相同的)

String name =new String( "tom ")

如果你使用了第一种方式,那么当你在声明一个内容也是 "tom "的string时,它将使用串池里原来的那个内存,而不会重新分配内存,也就是说,string saname= "tom ",将会指向同一块内存。而如果用第二种方式,不管串池里有没有"tom",它都会在堆中重新分配一块内存,定义一个新的对象。

另外关于string类型是不可改变的问题: string类型是不可改变的,也就是说,当你想改变一个string对象的时候,比如name= "madding " 那么虚拟机不会改变原来的对象,而是生成一个新的string对象,然后让name去指向它,如果原来的那个 "tom "没有任何对象去引用它,虚拟机的垃圾回收机制将接收它。

按值传递为什么形参改变对实参无影响呢??  那可能是因为实参传值给了形参,并且两个变量指向了不同的内存空间,所以两者互不干扰!

对于change方法的调用结果,可能很多人会有这种感觉:这不明明是按引用传递吗?对于这种问题,我想说这每个人的理解不同,你说只按值传递也可以,说有引用传递也可以,传值,对引用类型来说,可以是传引用值,所以说纠结传值还是传引用是没有必要的,每个人有每个人的理解!!!!

var code = "cc9a58e4-3711-40ee-ba33-65dbc86cbca4"

  暂时就讲这么多了,感兴趣的朋友可以查阅相关文档和资料。  

最后!有错误的地方欢迎指正    

按值传递,引用传递 浅析java String ,对象与对象引用的区别的更多相关文章

  1. java中对象和对象引用的区别

    1.何谓对象? 在Java中有一句比较流行的话,叫做“万物皆对象”,这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一 ...

  2. Java中对象和对象引用的区别,引用、指向是什么意思

    Java的变量分为两大类:基本数据类型和引用数据类型. 其中基本类型变量有四类8种:byte short int long float double char boolean,除了8种基本数据类型变量 ...

  3. Java中对象、对象引用、堆、栈、值传递以及引用传递的详解

    Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...

  4. JAVA String对象和字符串常量的关系解析

    JAVA String对象和字符串常量的关系解析 1 字符串内部列表 JAVA中所有的对象都存放在堆里面,包括String对象.字符串常量保存在JAVA的.class文件的常量池中,在编译期就确定好了 ...

  5. 有关java的引用传递,直接操作对象本身。直接删除BE的value中某值

    HashSet<String> refRegions = BE.get(regionName);    HashSet<String> values = new HashSet ...

  6. 关于Java String对象创建的几点疑问

    我们通过JDK源码会知道String实质是字符数组,而且是不可被继承(final)和具有不可变性(immutable).可以如果想要了解String的创建我们需要先了解下JVM的内存结构. 1.JVM ...

  7. Java——String对象

    前言 实际上任何语言都没有提供字符串这个概念,而是使用字符数组来描述字符串.Java里面严格来说也是没有字符串的,在所有的开发里面字符串的应用有很多,于是Java为了应对便创建了String类这个字符 ...

  8. Java String对象的问题 String s="a"+"b"+"c"+"d"

    1, String s="a"+"b"+"c"+"d"创建了几个对象(假设之前串池是空的) 2,StringBuilde ...

  9. 我的Java开发学习之旅------>Java String对象作为参数传递的问题解惑

    又是一道面试题,来测试你的Java基础是否牢固. 题目:以下代码的运行结果是? public class TestValue { public static void test(String str) ...

  10. Java String对象的经典问题

     先来看一个样例,代码例如以下:  public class Test {       public static void main(String[] args) {           Strin ...

随机推荐

  1. windwos10-11打开任意文件弹出警告

    如下打开exe或者视频.图片都弹出警告 解决方案输入快捷键win+s换出搜索框 输入Internet 选项 进入安全选项点击自定义级别 找到,加载应用程序和不安全文件 勾选启用(不安全) 然后确定-在 ...

  2. vs2019系统内置方法无提示

    有个同事问我为什么他的vs编写C#代码,对于引用System.dll中的方法,鼠标移上去没有方法的使用说明或接口注释,具体可以看下面的截图,而我绝大多数情况下是使用Rider开发,并没有遇到这个问题, ...

  3. ubuntu16.04编译安装nginx1.24.0

    环境: Distributor ID: Ubuntu Description: Ubuntu 16.04.7 LTS Release: 16.04 Codename: xenial 安装包: pcre ...

  4. centos环境下MySQL8.0.25离线升级至8.0.32

    环境 centos7 mysql8.0.25 下载新版本mysql 下载地址:https://dev.mysql.com/downloads/mysql/ 升级 备份数据 先保存原始数据,进入mysq ...

  5. 又学了一招:微软科普Windows 11电脑自动清理释放硬盘

    你是不是每次都等到电脑内存被占满,磁盘"红"成一片,才想起来去清理那些没用的程序or文件? 今天微软官方科普了一个小技巧:既然都用上了Windows 11 ,为什么不让电脑帮你自动 ...

  6. ESP8266的AT指令模块程序

    最新代码可点击下载:ESP8266 模块代码 和以下代码实现方式不一致,更加自由可控 本段代码只是测试了esp8266作为服务器端使用,没有测试作为客户端使用. 没有超长延时等待或死循环等待AT指令反 ...

  7. 小知识:如何配置OSW添加私网监控

    最近遇到一个Case,Oracle Support要求添加私网(心跳网络)监控. OSW默认是没有私网监控的,如需增加只需配置private.net文件,对应采集信息会存放到archive/oswpr ...

  8. Linux用户被锁定后如何解锁

    客户的一台机器,按照提供的常用密码尝试使用oracle用户登陆,超过指定次数账号被锁定,提示如下: Account locked due to 6 failed logins 这需要使用root用户解 ...

  9. ehlib 排序后 滚动条 不对问题

    针对CDS的情况,作者的代码里 好像也不知道什么原因 必须写Cds.First但是,不写的话,就是不行,去掉作者的注释就可以了.

  10. 从零开始的react入门教程(三),了解react事件与使用注意项

    壹 ❀ 引 在从零开始的react入门教程(二),从react组件说到props/state的联系与区别一文中,我们介绍了react组件的基本用法以及props与state的区别.其中react组件分 ...