谈谈java中的Reference与指针的关系!

博客给出一段Java程序代码,展示了Java函数内部的传值方式。指出Java函数传值永远是Reference的copy,而非Reference本身。因为Java中Reference存于栈,对象存于堆,函数内对Reference的copy操作,退出函数后对象不变,除非针对对象操作。
请大家先看一段程序代码:
package com.cjl.test;

public class TestReference {
    Person p =new Person();
    public void f(Person p2){
        Person p1 =new Person();
        p1.setName("Caojinli");
        p=p1;//这里的p是真实的p,就是一个真实的引用,not copy
        p2=p1;//这里的p2只是外面参数的一个copy,比如说这里的per的copy,
        //对其进行引用的操作(这里指的是赋值),但是对对象进行的操作是有效的
        //比如说p2.setName("Zhang San");
    }       
    public void f2(Person p2){
        p=p2;
    }
    public void printSth(){
        System.out.println(p.getName());
    }
    public static void main(String[] args){
        TestReference reference=new TestReference();
        Person per=new Person();
        per.setName("Songhongmu");
       
        reference.f(per);
        System.out.println(per.getName());
        reference.printSth();
    }

}
class Person {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
   
   
}
大家可以从这里看到java的函数内部的传值方式---永远都是Reference的copy,而非Reference(一种安全的指针)本身。
这是因为在java内部,所有的Reference都是存放在Stack中的,而Reference所对应的真正的对象是存放在堆中的,所以说在函数内部接受到的Reference的copy的引用间的操作在退出函数以后,引用对应的对象是不发生任何变化的(就像这里的p2=p1;操作),除非是针对对象(不是引用)的操作,比如说p2.setName("XXX")!!!
一点心得于大家共勉!
wyf_cjl@msn.com
<think> 我们被要求解释Java中类、对象和引用的概念,并且参考了提供的引用内容。根据引用内容,我们可以总结如下: 1. 引用[1]和[3]都强调了引用变量存储的是对象在内存中的地址,也就是说,引用指向对象。 2. 引用[2]展示了如何通过对象的引用变量来访问对象的成员变量。 因此,我们可以这样组织回答: ### 一、基本概念 1. **类(Class)**:类是创建对象的模板,它定义了对象的属性和方法。例如,`Person`类定义了`name`、`age`和`sex`属性。 2. **对象(Object)**:对象是类的实例。通过`new`关键字创建,例如`Person person = new Person();`,这里`person`就是一个对象(严格来说,`person`是引用,而`new Person()`创建的对象才是对象本身)。 3. **引用(Reference)**:引用变量存储的是对象在内存中的地址,通过这个引用我们可以操作对象。例如,`person.name = "沉默王二";`是通过引用`person`来设置对象的`name`属性。 ### 二、三者关系 - 类是一个抽象的概念,对象是类的具体实例。 - 引用是指向对象的“指针”,通过引用可以访问和操作对象。 ### 三、代码示例 ```java class Person { String name; int age; } public class Main { public static void main(String[] args) { // 创建Person类的对象,并用引用person指向它 Person person = new Person(); // 通过引用设置对象的属性 person.name = "张三"; person.age = 20; // 打印对象的属性 System.out.println(person.name); // 输出:张三 System.out.println(person.age); // 输出:20 } } ``` ### 四、内存模型(图示) ``` 栈内存(Stack) 堆内存(Heap) +-------------+ +------------------------+ | 引用变量 | ------> | 对象实例(Person) | | person | | - name: "张三" | | | | - age: 20 | +-------------+ +------------------------+ ``` 解释:引用变量`person`存储在栈内存中,它保存了堆内存中实际对象的内存地址,对象的数据则存储在堆内存中。 ### 五、关键点 1. **对象创建**:使用`new`关键字会在堆内存中分配空间创建对象,并返回该对象的引用。 2. **引用赋值**:将对象引用赋值给另一个变量时,两个引用将指向同一个对象(而不是创建新对象)。例如: ```java Person person2 = person; // person2和person指向同一个对象 person2.name = "李四"; // 修改person2的name,person的name也变为"李四" ``` 3. **空引用**:引用可以被赋值为`null`,表示不指向任何对象。试图通过空引用访问成员将导致`NullPointerException`。 ### 六、常见误区 - 引用不是对象本身,而是对象的“遥控器”。 - 一个对象可以有多个引用(多个变量指向同一个对象)。 - 对象在没有引用指向时会被垃圾回收器回收。 ### 七、相关问题 1. Java中引用和C++指针有什么区别? 2. 如何理解Java的垃圾回收机制? 3. Java中的值传递和引用传递如何区分? [^1]: 引用内容1:自定义类对象的引用的创建和String类对象的引用创建类似。 [^2]: 引用内容2:通过对象的引用变量访问对象属性。 [^3]: 引用内容3:引用变量存储的是对象在内存中的地址。 </think> ### Java中类、对象、引用的理解 #### 一、核心概念解析 1. **类(Class)** 类是对象的蓝图和模板,定义了对象的结构和行为特征。它包含: - **属性**(成员变量):描述对象的状态 - **方法**(成员函数):定义对象的行为 - **构造器**:用于创建对象实例 ```java // 类定义示例 class Person { // 属性(成员变量) private String name; private int age; // 构造器 public Person(String name, int age) { this.name = name; this.age = age; } // 方法(成员函数) public void introduce() { System.out.println("我叫" + name + ",今年" + age + "岁"); } } ``` 2. **对象(Object)** 对象是类的具体实例,通过`new`关键字创建。每个对象: - 拥有独立的存储空间 - 包含类定义的所有属性副本 - 可以调用类定义的方法 ```java // 对象创建示例 Person p1 = new Person("张三", 25); // 创建Person类的对象实例 p1.introduce(); // 调用对象方法 ``` 3. **引用(Reference)** 引用是访问对象的"遥控器",本质是存储对象内存地址的变量: - 不是对象本身,而是指向对象的指针 - 多个引用可指向同一对象 - 未指向对象时为`null`(空引用) ```java Person p2 = p1; // p2和p1指向同一个对象 System.out.println(p2.name); // 输出"张三" ``` #### 二、内存模型解析 ```mermaid graph LR A[栈内存 Stack] -->|存储引用| B[引用变量 Person p] C[堆内存 Heap] -->|存储对象| D[对象实例] B -->|指向内存地址| D D --> E[属性 name='张三'] D --> F[属性 age=25] D --> G[方法 introduce()] ``` - **栈内存**:存储引用变量(如`Person p`) - **堆内存**:存储实际对象实例及其数据 - **引用本质**:引用变量存储对象在堆内存中的首地址(如`0x1000`) #### 三、关键特性对比 | 概念 | 本质 | 存储位置 | 生命周期 | 操作方式 | |-----------|-----------------------|------------|------------------|----------------| | **类** | 对象模板 | 方法区 | 程序运行期间 | 通过类名访问 | | **对象** | 类的实例 | 堆内存 | 直到被垃圾回收 | 通过引用操作 | | **引用** | 对象的内存地址指针 | 栈内存 | 作用域结束时 | 直接赋值/传递 | #### 四、典型场景分析 1. **对象创建引用赋值** ```java Person p3 = new Person("李四", 30); // 1. new在堆中创建对象 // 2. = 将对象地址赋值给引用p3 ``` 2. **多引用共享对象** ```java Person p4 = p3; p4.age = 31; // 修改影响p3指向的对象 System.out.println(p3.age); // 输出31 ``` 3. **空引用处理** ```java Person p5 = null; p5.introduce(); // 抛出NullPointerException ``` 4. **匿名对象** ```java new Person("王五", 28).introduce(); // 对象创建后无引用指向,使用后即被回收 ``` #### 五、常见误区澄清 1. **引用≠对象** 引用是访问对象的"钥匙",对象是内存中的实体。赋值操作复制的是引用(钥匙),而非对象本身。 2. **Java没有指针?** Java引用本质是指针,但相比C++指针: - 不能进行地址运算(`p+1`非法) - 自动内存管理(无需`delete`) - 类型安全检查(无法转为任意类型指针) 3. **参数传递机制** Java始终是**值传递**: ```java void changeName(Person p, String name) { p.name = name; // ✓ 修改对象状态(通过引用值) p = new Person(); // ✗ 不影响原引用 } ``` #### 六、高级应用场景 1. **对象克隆**:深拷贝浅拷贝 2. **引用队列**:`java.lang.ref`包(软/弱/虚引用) 3. **函数式接口**:方法引用(`ClassName::methodName`)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值