- 浏览: 1654171 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (405)
- C/C++ (16)
- Linux (60)
- Algorithm (41)
- ACM (8)
- Ruby (39)
- Ruby on Rails (6)
- FP (2)
- Java SE (39)
- Java EE (6)
- Spring (11)
- Hibernate (1)
- Struts (1)
- Ajax (5)
- php (2)
- Data/Web Mining (20)
- Search Engine (19)
- NLP (2)
- Machine Learning (23)
- R (0)
- Database (10)
- Data Structure (6)
- Design Pattern (16)
- Hadoop (2)
- Browser (0)
- Firefox plugin/XPCOM (8)
- Eclise development (5)
- Architecture (1)
- Server (1)
- Cache (6)
- Code Generation (3)
- Open Source Tool (5)
- Develope Tools (5)
- 读书笔记 (7)
- 备忘 (4)
- 情感 (4)
- Others (20)
- python (0)
最新评论
-
532870393:
请问下,这本书是基于Hadoop1还是Hadoop2?
Hadoop in Action简单笔记(一) -
dongbiying:
不懂呀。。
十大常用数据结构 -
bing_it:
...
使用Spring MVC HandlerExceptionResolver处理异常 -
一别梦心:
按照上面的执行,文件确实是更新了,但是还是找不到kernel, ...
virtualbox 4.08安装虚机Ubuntu11.04增强功能失败解决方法 -
dsjt:
楼主spring 什么版本,我的3.1 ,xml中配置 < ...
使用Spring MVC HandlerExceptionResolver处理异常
在java和C++中都采用了引用这个概念,但是二者的行为并不一样。java的引用其实更象c++中的指针,而非c++中的引用,的确c++的指针给我们带来强大威力的同时,也给我们带来了危险,大多的攻击也都是利用指针让系统崩溃。在许多书上都没有见到关于java中reference行为的更详细的探讨,本文便从与c++的的区别谈起:
一.先看java中的引用:
现产生两个对象 :
引用Person p=p1,p1=p2;
测试结果p.getName(): Zhangsan;
p1.getName():Lisi;
P2.getName :Lisi;
而在c++的引用中其结果应该都是Lisi即p2的name(因为p1的改变会影响p);
上述结果显示:在java中referece其行为就是c++中的指针,而不是c++中的引用.
但是java的referece是一种安全的指针,不仅受到编译器的保护,还受到执行系统的保护。但java没有“指针”运算。c++中的引用感觉叫做别名更合适,许多语言都用alias关键字来定义别名。
二、java中的参数传递问题--By value or By reference
java中的参数传递都是采用by value.其实这句话是个笼统的说法,如果不加思索或许不能理解其真正的含义。
首先说什么是by value,by value是指在参数结合的时候,形参是否是实参的一个副本,如果产生这个副本那么我们说是by value,否则我们说是by reference.
java中的基本类型和c、c++语言一样采用by value传参是毋庸置疑的。
那么java有在参数传递的时候有没有by reference?回答是否定的。java中的一切类型在传递参数的时候都是传值的。
首先,我们想想c++和java中的对象有什么区别?其实没有什么区别,只是java中的对象必须由reference来持有,而c++的对象可以单独存在。那好,那就让我们看看java是怎么传递对象的:
能完成交换工作么?不能。为什么?
我们看看:
当我们传递参数的时候,我们传递的是对象么?不,是对象的一个句柄(引用、“指针”)。java的对象只能
由引用来持有。如果你对c++熟悉,那么上面的过程我们翻译过来:
这两段代码产生的行为是一样的,都不能正常工作(即无法完成我们的交换工作)。
那我们先想想c++是怎么实现对象的交换的?你或许一口就说出使用引用和指针做参数。但是上面的参数是指针
作为参数呀!原因在于:在c++中我们传递的参数的确能是对象:
这样可以成功完成交换动作.
前两段的代码不能工作的原因在于:
但我们传递实参的时候,我们传递的是指针("指针"),传递的过程,指针("指针")进行了复制,如下图示:
a--->对象1<----a'(其中a',b'分别为a,b在传递参数的时候产生的副本)
b--->对象2<----b'
进入函数体后副本发生了交换,如下图示:
a-->对象1<---b'
b-->对象2<---a'
我们可以看出a和b安然无恙的指向了原来的对象.这就是产生上述结果的原因.
但java可以在函数体内修改对象的值:
对java传递参数总结:
1)一个方法不能够修改一个基本类型的实参的值
2)一个方法可以改变对象的状态.
3)一个方法不能让实参引用指向另一个对象.
public static void swap(Person person1, Person person2) {
Person temp = person1;
person1 = person2;
person2 = temp;
System.out.println("输出 : " + person1.getName() + " -- " + person2.getName());
}
在里面打印,结果肯定是交换了。但是swap的意思是指实参发生交换,而不是形参。
调用:
调用swap之后,a的name还是Alice,b的name还是Bob,所以没有交换。
这种情况依然还是能完成交换。BTW:你的第3点的意思是不是想说明,方法中不能交换对象的引用?
如果是Person类的话,可以运行是可以完成交换的。
所以你总结的第3点是不正确的。
你可以试验一下
如果是Person类的话,可以运行是可以完成交换的。
所以你总结的第3点是不正确的。
一.先看java中的引用:
class Person { private String name; public Person(String name) { this.name=name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
现产生两个对象 :
Person p1=new Person("Zhangsan"); Person p2=new Person("Lisi");
引用Person p=p1,p1=p2;
测试结果p.getName(): Zhangsan;
p1.getName():Lisi;
P2.getName :Lisi;
而在c++的引用中其结果应该都是Lisi即p2的name(因为p1的改变会影响p);
上述结果显示:在java中referece其行为就是c++中的指针,而不是c++中的引用.
但是java的referece是一种安全的指针,不仅受到编译器的保护,还受到执行系统的保护。但java没有“指针”运算。c++中的引用感觉叫做别名更合适,许多语言都用alias关键字来定义别名。
二、java中的参数传递问题--By value or By reference
java中的参数传递都是采用by value.其实这句话是个笼统的说法,如果不加思索或许不能理解其真正的含义。
首先说什么是by value,by value是指在参数结合的时候,形参是否是实参的一个副本,如果产生这个副本那么我们说是by value,否则我们说是by reference.
java中的基本类型和c、c++语言一样采用by value传参是毋庸置疑的。
那么java有在参数传递的时候有没有by reference?回答是否定的。java中的一切类型在传递参数的时候都是传值的。
首先,我们想想c++和java中的对象有什么区别?其实没有什么区别,只是java中的对象必须由reference来持有,而c++的对象可以单独存在。那好,那就让我们看看java是怎么传递对象的:
public static void swap(Person person1, Person person2) // doesn't work { Person temp = person1; person1 = person2; person2 = temp; } Person a = new Person("Alice"); Person b = new Person("Bob"); swap(a, b);
能完成交换工作么?不能。为什么?
我们看看:
当我们传递参数的时候,我们传递的是对象么?不,是对象的一个句柄(引用、“指针”)。java的对象只能
由引用来持有。如果你对c++熟悉,那么上面的过程我们翻译过来:
static void swap(Person *person1,Person *person2) { Person *temp = person1; person1 = person2; person2 = temp; } Person *a = new Person("Alice"); Person *b = new Person("Bob"); swap(a,b);
这两段代码产生的行为是一样的,都不能正常工作(即无法完成我们的交换工作)。
那我们先想想c++是怎么实现对象的交换的?你或许一口就说出使用引用和指针做参数。但是上面的参数是指针
作为参数呀!原因在于:在c++中我们传递的参数的确能是对象:
Person a("Alice"); Person b("Bob"); swap(a,b);
这样可以成功完成交换动作.
前两段的代码不能工作的原因在于:
但我们传递实参的时候,我们传递的是指针("指针"),传递的过程,指针("指针")进行了复制,如下图示:
a--->对象1<----a'(其中a',b'分别为a,b在传递参数的时候产生的副本)
b--->对象2<----b'
进入函数体后副本发生了交换,如下图示:
a-->对象1<---b'
b-->对象2<---a'
我们可以看出a和b安然无恙的指向了原来的对象.这就是产生上述结果的原因.
但java可以在函数体内修改对象的值:
static void changName(Person person){ person.setName("Bob"); } changName(a);
对java传递参数总结:
1)一个方法不能够修改一个基本类型的实参的值
2)一个方法可以改变对象的状态.
3)一个方法不能让实参引用指向另一个对象.
评论
7 楼
kevinStar
2010-09-19
明白你的意思了,与你交流很愉快。
6 楼
fuliang
2010-09-18
引用
public static void swap(Person person1, Person person2) {
Person temp = person1;
person1 = person2;
person2 = temp;
System.out.println("输出 : " + person1.getName() + " -- " + person2.getName());
}
在里面打印,结果肯定是交换了。但是swap的意思是指实参发生交换,而不是形参。
调用:
Person a("Alice"); Person b("Bob"); swap(a,b);
调用swap之后,a的name还是Alice,b的name还是Bob,所以没有交换。
5 楼
kevinStar
2010-09-18
你说的第1点,我理解你是在说Java基本类型是传值的(即创建了副本,所以当发生改变的时候不影响外部的基本类型值。
第2点,我理解你是在说java对象是传址的(所以像你说的能改变对象的状态)。
那么你的第三点解释的
另:你公布的不是全部代码,所以我是猜测着写的。所以完成了交换能正常运行。
这个是我写的测试代码,能运行通过。不知道你是怎么写的?
BTW:哥们交流下,交个朋友。我好久不来论坛了,有表达不对的地方,请见谅。
第2点,我理解你是在说java对象是传址的(所以像你说的能改变对象的状态)。
那么你的第三点解释的
fuliang 写道
第三点是说由于是值传递,所以实参在参数结合的时候,生成了副本,改变副本的指向,不影响原来的实参。
不是和第1点重复了么?另:你公布的不是全部代码,所以我是猜测着写的。所以完成了交换能正常运行。
public class Person { private String name; public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void swap(Person ...persons) { Person temp = persons[0]; persons[0] = persons[1]; persons[1] = temp; System.out.println("输出 : " + persons[0].getName() + " -- " + persons[1].getName()); } public static void swap(Person person1, Person person2) { Person temp = person1; person1 = person2; person2 = temp; System.out.println("输出 : " + person1.getName() + " -- " + person2.getName()); } public static void changed(int i) { i = 12; System.out.println(i); } public static void changed(Person person) { person.setName("wangwu"); System.out.println(person.getName()); } public static void main(String[] args) { Person p1 = new Person("zhangsan"); Person p2 = new Employee("lisi"); // int i = 0; // changed(i); // System.out.println(i); // changed(p1); // System.out.println(p1.getName()); // Person p = p1; // p1 = p2; // System.out.println(p.getName()); // swap(new Person[]{p1, p2}); swap(p1, p2); } } class Employee extends Person { public Employee(String name) { super(name); } @Override public String getName() { return super.getName(); } @Override public void setName(String name) { super.setName(name); } }
这个是我写的测试代码,能运行通过。不知道你是怎么写的?
BTW:哥们交流下,交个朋友。我好久不来论坛了,有表达不对的地方,请见谅。
4 楼
fuliang
2010-09-18
第三点是说由于是值传递,所以实参在参数结合的时候,生成了副本,改变副本的指向,不影响原来的实参。
3 楼
kevinStar
2010-09-18
class Employee extends Person { public Employee(String name) { super(name); } @Override public String getName() { return super.getName(); } @Override public void setName(String name) { super.setName(name); } }
这种情况依然还是能完成交换。BTW:你的第3点的意思是不是想说明,方法中不能交换对象的引用?
2 楼
fuliang
2010-09-18
kevinStar 写道
public static void swap(Person person1, Person person2) // doesn't work { Person temp = person1; person1 = person2; person2 = temp; } Person a = new Person("Alice"); Person b = [color=red]new Employee("Bob");//应该是Person吧?[/color] swap(a, b);
如果是Person类的话,可以运行是可以完成交换的。
所以你总结的第3点是不正确的。
你可以试验一下
1 楼
kevinStar
2010-09-18
public static void swap(Person person1, Person person2) // doesn't work { Person temp = person1; person1 = person2; person2 = temp; } Person a = new Person("Alice"); Person b = [color=red]new Employee("Bob");//应该是Person吧?[/color] swap(a, b);
如果是Person类的话,可以运行是可以完成交换的。
所以你总结的第3点是不正确的。
发表评论
-
Builder模式遇到继承
2013-10-13 13:48 0interface Self<T extends ... -
Builder模式遇到集成
2013-10-13 13:47 0package com.qunar.qss.business. ... -
JVM调优Step by Step
2012-02-02 17:38 0现代的JVM能够适应于各种应用和领域,每个应用和领域的使用 ... -
commons-lang StringUtils#split的坑
2011-12-31 10:11 3154今天用StringUtils#split,陷入了前两个坑。需求 ... -
使用scala.sys.process包和系统交互
2011-07-19 00:00 6490在Java中我们可以使用Runtime.getRuntime( ... -
HttpClient Json请求工具
2011-05-05 18:32 17849发送Json请求,结果返回Json. public sta ... -
利用Java反射实现通用的Excel报表
2011-04-12 16:00 2019最近有很多客户报表需要提供客户下载,需要生成一个Excel的格 ... -
深入异常处理
2011-03-31 20:46 1800异常处理是写一个健壮 ... -
Java序列化注意一些点
2011-03-12 21:04 18451.序列化ID的问题: 标示了版本号,版本号一致才能反序列化成 ... -
Java动态代理
2010-09-24 00:34 4459Java提供了动态代理,可以完成AOP和装饰模式的功能,主要的 ... -
Java Timestamp是和ExtJS的timestamp不兼容
2010-08-09 20:33 3352Timestamp纳秒级别的,ExtJS的timestamp使 ... -
XML DocumentBuilder#parse(String str)
2010-07-06 15:55 3886DocumentBuilderFactory dbf = ... -
[备忘]String#split/substring的子串会共享原来大的String
2010-03-29 17:18 1491如果每次需要大字符串中的很小的一个字串,可能会引起内存中大量的 ... -
runtime.exec()执行进程block死锁问题
2010-01-18 21:39 5286最近在java代码中使用runtime.exec执行rsync ... -
URL中文问题
2010-01-08 14:46 10525最近使用HttpClient,和Java的java.net.U ... -
A TaskExecutor Impl
2009-12-07 11:33 1625import java.util.ArrayList; im ... -
使用XStream把Java对象XML/JSON格式的序列化和反序列化
2009-05-05 11:37 6235试了一下Thoughtworks的XStream,以测试驱动和 ... -
从《编程的未来》这篇文章想到C++和Java语言的爽与不爽
2009-05-01 23:44 3970从编程的未来这篇文 ... -
《Effetive Java》读书笔记二
2009-02-23 14:23 1601第二章 所有对象共有的 ... -
《Effetive Java》读书笔记一
2009-02-19 11:36 2180《Effetive Java》和 《Effective C++ ...
相关推荐
【深入探讨 Java 类加载器】 Java 类加载器是Java虚拟机(JVM)的核心组成部分,它的主要任务是将Java类的字节码加载到JVM中以便执行。类加载器的概念始于JDK 1.0,最初是为了解决Java Applet在浏览器中的运行需求...
### 深入探讨Java类加载器 #### 类加载器基本概念 类加载器(Class Loader)是Java语言的关键组成部分之一,它负责将Java类的字节码加载到Java虚拟机(JVM)中,从而使得Java应用程序能够运行起来。自Java诞生以来...
在深入探讨Java中多态的内存分析之前,我们需要先理解一些基本概念。 首先,了解Java内存模型至关重要。Java程序运行时主要涉及四种内存区域:程序计数器、虚拟机栈、本地方法栈、堆和方法区(在Java 8及以后版本中...
本文将深入探讨Java中的对象、引用以及它们之间的关系,并结合值传递的概念进行解析。 首先,我们需要理解什么是Java对象。在Java中,对象是类的实例。当我们使用`new`关键字创建一个类的实例时,就创建了一个对象...
本课程“MLDN魔乐JAVA_09深入引用、this关键字、对象比较”将带你深入探讨这些核心概念。 首先,让我们来讨论“引用”。在Java中,变量可以分为基本类型和引用类型。引用类型变量实际上存储的是对象在内存中的地址...
因此,要实现C++的引用行为,通常需要借助于Java的反射或者更底层的机制,这在应用层面上通常是不推荐的。 此外,Java中的基本类型与引用类型处理方式不同。对于基本类型,如`int`,它们在栈上直接存储值,不支持...
本教程将深入探讨Java中的引用传递机制,并通过视频教程的形式帮助学习者更好地理解和应用这一概念。 首先,理解“引用”在Java中的含义至关重要。在Java中,当我们声明一个对象变量时,实际上我们得到的是指向对象...
本文主要探讨Java中的对象、指针(受限指针)和引用,以及对象的存储空间和回收机制。 首先,Java语言中的万物皆对象。对象是面向对象编程的核心,它代表了现实世界中具体的事物或概念,并包含了其特性和行为。对象...
文章由天津工业大学软件工程专业的翁龙辉撰写,旨在深入剖析`String`在Java中的独特行为及其潜在的陷阱。下面我们将详细探讨这些陷阱及其背后的原理。 ### String的不可变性 `String`在Java中被设计为不可变对象,...
下面我们将深入探讨一些 Java 8 的核心知识点。 1. **函数式编程**: - **Lambda 表达式**:Java 8 引入了 Lambda 表达式,使得编写简洁、可读性强的代码成为可能。Lambda 可以被当作一种匿名函数,用于传递行为...
以下是深入探讨Java中多态实现机制的详细说明: 1. **子类型多态**: - 子类型多态是Java中最常见的多态形式,它基于继承和方法的覆盖。当一个派生类对象通过基类引用调用方法时,实际执行的是派生类中重写的方法...
在探讨Java内存管理和对象比较机制的同时,我们也应注意Java虚拟机(JVM)垃圾回收机制的作用,这直接关联到对象的生命周期管理,对内存分配和释放有着重要影响。JVM在堆内存中不断追踪和管理对象的使用状态,以确保...
在书中,作者深入探讨了JVM的各个方面,包括其体系结构、垃圾收集机制、Java安全模型、类的动态加载与扩展机制、以及class文件的结构等。通过对这些深层次的了解,读者能够更好地理解Java技术的底层原理,并编写出...
本文将围绕这两个概念进行深入探讨,并针对初学者常见的疑惑点进行解答。 #### Java面向对象基础 Java是一种完全面向对象的语言,几乎所有的功能都是通过类和对象来实现的。在Java中,类(Class)是一种定义对象的...
在此,我们将深入探讨这两个关键知识点。 一、字符串操作 1. 字符串创建:在Java中,字符串是对象,可以通过`new String()`构造函数或字面量`""`来创建。字面量方式创建的字符串会被放入常量池,而使用构造函数则...
本教程将深入探讨Java中的引用类型,以及它们在实际编程中的应用。 一、类类型 类类型是基于类的对象引用,当你创建一个类的实例时,你会得到一个指向该实例的引用。例如: ```java public class Student { ...
这里,我们将深入探讨Java编程规范中的核心概念,并提供一些关键知识点。 1. **基本语法与类型系统**: - **变量**:Java中的变量有基本类型和引用类型。基本类型包括整型(byte, short, int, long)、浮点型...
深入探讨Java2 SDK源代码(3):揭秘package与make机制 在《深入Java2 SDK源代码(3)》这篇文章中,作者王森通过详细分析Java的package和make机制,帮助读者理解Java编译和运行时的重要概念。文章强调了遵守“每一...
这篇13页的PDF文档,很可能是深入探讨了Java中的引用类型及其在开发中的应用技术。在这里,我们将对Java引用类型的一些关键知识点进行详细的阐述。 1. 类(Class):Java是一种面向对象的语言,类是创建对象的蓝图...