java取随机整数中整数的值超过了它的下界用什么定义

java中t=(true|false); 什么意思?_百度知道
java中t=(true|false); 什么意思?
java中t=(true|false); 什么意思?
提问者采纳
是(按位或),原理为。及上面 () 中有一个为真即 t= true:对两个整数的二进制形式逐位进行逻辑或运算:1|0=1,0|0=0,1|1=1,0|1=1等
提问者评价
谢谢哈~你回答得早,采纳你了嘿嘿
其他类似问题
按默认排序
其他5条回答
||的话是判断true成功后您好,提问者:
是短路或,建议使用||,浪费效率,false就不去判断了,说白了就是判断了true还要去判断false。
都是逻辑运算,没必要判断两次
对括号内的参数逐个判断,不过就(true|false)来说,怎么判断都是true的。
(true|false)就是把true和false进行按位或运算,结果为true,也就是t= 去了解下位运算符逻辑运算符的基础知识吧
t是个boolean型的变量,定义它的值是true或者
true的意思
java的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁为什么 Java 只有值传递,但 C# 既有值传递,又有引用传递,这种语言设计有哪些好处?
按投票排序
一般来说,最常见的参数引用传递是如下的惯用法:Xif(Xxx.TryParse("text", out result)) {
//解析成功}这是为了避免使用异常提高效率,尤其是在数据量很大的时候。多说几句,C# 的设计思想与 Java 不同,C# 更多的考虑了性能方面的实际情况而不是只考虑“语言的简单纯洁性”。
先强调这个问题前半句是真命题。说问题逻辑有问题,说一切都是值传递,都是没理解什么叫引用传递和值传递。虽然这个问题根本就没有在问“Java是不是值传递”,但是看完其它答案发现,如果不先解释清楚到底什么是值传递,什么是引用传递,后面的好处也无从谈起。只关心好处的请拉到最后。第一种误解是:Java是引用传递。(这么理解的人,大体会解释说Java的形参是对象的引用所以才叫引用传递。这个解释的错误在于:引用传递这个词不是这个意思,这个词是形容调用方式,而不是参数本质的类型的。所以,即使有人因为明白引用本身也是个值,然后觉得Java其实是值传递了,这种理解也是错的。你这种理解,叫“传递的是值”,而非“值传递”。后面展开。)第二种误解是:值类型是值传递,引用类型用的是引用传递。第三种误解是:认为所有的都是值传递,因为引用本质上也是个值,本质就是个指针嘛。第四种误解是:常出现在C++程序员中,声明的参数是引用类型的,就是引用传递;声明的参数是一般类型或指针的就是值传递。(也有人把指针归为引用传递,其实它比较特殊,无论你归哪边都是错的。)值传递与引用传递,在计算机领域是专有名词,如果你没有专门了解过,一般很难自行悟出其含义。而且在理解下面的解释时,请不要把任何概念往你所熟悉的语言功能上套。很容易产生误解。比如Reference,请当个全新的概念,它和C#引用类型中的引用,和C++的&,一点儿关系都没有。值传递和引用传递,属于函数调用时参数的求值策略(),这是对调用函数时,求值和传值的方式的描述,而非传递的内容的类型(内容指:是值类型还是引用类型,是值还是指针)。值类型/引用类型,是用于区分两种内存分配方式,值类型在调用栈上分配,引用类型在堆上分配。(不要问我引用类型里定义个值类型成员或反之会发生什么,这不在这个本文的讨论范畴内,而且你看完之后,你应该可以自己想明白)。一个描述内存分配方式,一个描述参数求值策略,两者之间无任何依赖或约束关系。在函数调用过程中,调用方提供实参,这些实参可以是常量:Call(1);也可以是变量:Call(x);也可以是他们的组合:Call(2 * x + 1);也可以是对其它函数的调用:Call(GetNumber());但是所有这些实参的形式,都统称为表达式(Expression)。求值(Evaluation)即是指对这些表达式的简化并求解其值的过程。求值策略(值传递和引用传递)的关注的点在于,这些表达式在调用函数的过程中,求值的时机、值的形式的选取等问题。求值的时机,可以是在函数调用前,也可以是在函数调用后,由被调用者自己求值。这里所谓调用后求值,可以理解为Lazy Load或On Demand的一种求值方式。而且,除了值传递和引用传递,还有一些其它的求值策略。这些求值策略的划分依据是:求值的时机(调用前还是调用中)和值本身的传递方式。详见下表:看到这里的名传递,可能就有人联想到C++里的别名(alias),其实也是两码事儿。语言层直接支持名传递的语言很不主流,但是在C#中,名传递的行为可以用Func&T&来模拟,说到这儿应该能大概猜出名传递的大致行为了。不过这不是重点,重点是值传递和引用传递。上面给出的传值方式的表述有些单薄,下表列出了一些二者在行为表象上的区别。这里的改变不是指mutate, 而是change,指把一个变量指向另一个对象,而不是指仅仅改变属性或是成员什么的(如Java,所以说Java是Pass by value,原因是它调用时Copy,实参不能指向另一个对象,而不是因为被传递的东西本质上是个Value,这么讲计算机上什么不是Value?)。这些行为,与参数类型是值类型还是引用类型无关。对于值传递,无论是值类型还是引用类型,都会在调用栈上创建一个副本,不同是,对于值类型而言,这个副本就是整个原始值的复制。而对于引用类型而言,由于引用类型的实例在堆中,在栈上只有它的一个引用(一般情况下是指针),其副本也只是这个引用的复制,而不是整个原始对象的复制。这便引出了值类型和引用类型(这不是在说值传递)的最大区别:值类型用做参数会被复制,但是很多人误以为这个区别是值类型的特性。其实这是值传递带来的效果,和值类型本身没有关系。只是最终结果是这样。求值策略定义的是函数调用时的行为,并不对具体实现方式做要求,但是指针由于其汇编级支持的特性,成为实现引用传递方式的首选。但是纯理论上,你完全可以不用指针,比如用一个全局的参数名到对象地址的HashTable来实现引用传递,只是这样效率太低,所以根本没有哪个编程语言会这样做。(自己写来玩玩的不算)综上所述,对于Java的函数调用方式最准确的描述是:参数藉由值传递方式,传递的值是个引用。(句中两个“值”不是一个意思,第一个值是evaluation result,第二个值是value content)由于这个描述太绕,而且在字面上与Java总是传引用的事实冲突。于是对于Java,Python、Ruby、JavaScript等语言使用的这种求值策略,起了一个更贴切名字,叫。这个名字诞生于40年前。前面讨论了各种求值策略的内涵。下面以C++为例:void ByValue(int a)
a = a + 1;
void ByRef(int& a)
a = a + 1;
void ByPointer(int* a)
*a = *a + 1;
int main(int argv, char** args)
int v = 1;
ByValue(v);
// Pass by Reference
ByPointer(&v);
// Pass by Value
int* vp = &v;
ByPointer(vp);
Main函数里的前两种方式没有什么好说,第一个是值传递,第二个函数是引用传递,但是后面两种,同一个函数,一次调用是Call by reference, 一次是Call by value。因为:ByPointer(vp);
没有改变vp,其实是无法改变。ByPointer(&v);
改变了v。(你可能会说,这传递的其实是v的地址,而ByPointer无法改变v的地址,所以这是Call by value。这听上去可以自圆其说,但是v的地址,是个纯数据,在调用的方代码中并不存在,对于调用者而言,只有v,而v的确被ByPointer函数改了,这个结果,正是Call by reference的行为。从行为考虑,才是求值策略的本意。如果把所有东西都抽象成值,从数据考虑问题,那根本就没有必要引入求值策略的概念去混淆视听。)请体会一下,应该就明白上面一直在说的调用的行为的意思。C语言不支持引用,只支持指针,但是如上文所见,使用指针的函数,不能通过签名明确其求值策略。C++引入了引用,它的求值策略可以确定是Pass by reference。于是C++的一个奇葩的地方来了,它语言本身(模拟的不算,什么都能模拟)支持Call by value和Call by reference两种求值策略,但是却提供了三种语法去做这俩事儿。C#的设计就相对合理,函数声明里,有ref/out,就是引用传递,没有ref/out,就是值传递,与参数类型无关。不过如果观察一下void ByRef(int& a)和void ByPointer(int* a)所生成的汇编代码,会发现在一定条件下其实是一样的。都是这个样子:; 12
mov ebp, esp
sub esp, 192
lea edi, DWORD PTR [ebp-192]
mov ecx, 48
mov eax, -
; ccccccccH
*a = *a + 1;
mov eax, DWORD PTR _a$[ebp]
mov ecx, DWORD PTR [eax]
add ecx, 1
mov edx, DWORD PTR _a$[ebp]
mov DWORD PTR [edx], ecx
调用方的代码也是一样的。代码就不贴了。这两种传递方式说完了,下面回到正题说好处。问题中“这种”指代不明,且认为是Java。支持多种求值策略可以给语言带来更高的灵活性,但是同时也需要一个“灵活”的人来良好地驾驭。Java通过牺牲这种价值不大还可能带来问题的灵活性,带来了语言自身语法一致性、逻辑鲁棒性及更容易学习等多个好处。不仅仅Java和C#,每个语言,在设计时都需要在这些特性间做出自己独特的取舍来体现自己的设计理念,并适应不同人,不同使用环境的要求。虽然说没有什么功能是一个语言可以做,而另一个语言做不了的。但是每个语言,都有它最适合的范畴与不适合的范畴。
我就这么说吧。为什么在Java里面【使用一个类包装一个变量传递进函数】来模拟C#的ref跟C#的ref不一样,这倒不是什么语义上的,而是因为C#的ref和out最终被JIT出来,是一个真正的指针。这也就是为什么C#不让你在lambda表达式里面调用外层函数的ref和out参数,因为在这种实现下,这么做会破坏GC的效果。C#的ref和out还有一个语义上的约束,就是传递给ref的值必须是初始化过的,而传递给out的值在函数结束之后会被认为是初始化过的,函数里也必须在任何退出点之前给out参数赋值。至于Java为什么不提供这样的机制,我觉得最直接的原因就是Java他爹喜欢纯粹的东西。当然现在纯粹的东西被证明使用起来比起有语法糖的感觉要恶心的多,所以现在也渐渐加入很多语法糖了,譬如说lambda表达式什么的,尽管它的所有功能都可以被匿名类覆盖。而C#提供这样的机制,出发点也是有两个。第一个就是用户怎么方便怎么来,所以语言里面有大量的语法糖,而且你不知道这些语法糖并不会影响到你的编程,最多只是让你的代码写出来恶心一点而已。还有.net里面函数的大量重载也是。第二个就是不能太过相信程序员对自己的能力的信任,所以还要提供一些机制让写library的人可以约束一下用library的人,让他们不要不小心乱写。
Java和C#的指导思想不一样Java的目标是,简化,尽一切可能的简化,如果因为简化减弱了表现力那也没招,大不了用户用的时候绕个弯呗,反正那是少数情况(其实也不少了,能有10%了)。最后的感觉就是,语言好像装模作样的。Q:我希望修改参数的值应该怎么办?A:请弄一个对象,把参数包起来。C#的目标是,语言怎么自然怎么来,因为只有自然的语言用户学起来才简单,哪怕因此引入了更多的概念也没关系,因为我们的概念比较自然嘛。既然是自然的概念,当然用户应该很容易学啊。最后的感觉是,语言比较顺眼,但是据说学习的成本更大。(我是不太明白到底哪里大,不过我还经常不懂别人为啥不懂呢,谁知道呢。)Q:我希望修改参数的值应该怎么办?A:如果又读又写,请用ref;如果只写不读,请用out。-----------------分割线-----------------反对老赵的观点,所谓值传递还是引用传递,指的是语言提供的概念,而不是实现。从实现来讲,所有的传递肯定都是值传递(反正我学的语言都是)至于从语言对外暴露的接口,Java的函数没有提供在函数内修改变量影响到函数外的手段,C#可以用ref和out做到,这就是两者的区别,这是确实存在的。
如果把JAVA里传递对象的情形当做值传递,那么需要把它对应地理解为C里面传指针。呵呵呵呵,那这样一看JAVA的对象传递不就跟是C里传指针一样一样儿么?如果把这种情况定义为传值,那C/C++里传结构的时候那种传值又怎么定义?好嘛,是不是要起个新名字叫“复制传值”?要么是一个名词两种解释,要么是两件事情起同一个名字,呵呵呵呵,这不自己折腾自己么?要我说,“JAVA里都是传值”这句话,如果是认真说的,是出于“简化理解”的目的而说的,那完全就是反而把人弄糊涂了。所以我觉得传值还传引用先看内存上怎么走就行了share内存就是传引用,copy内存就是传值(先抛开一些特殊情况)这样的话:C/C++:默认传值,引用传引用,指针单独理解JAVA:基础数据类型传值,对象传引用C#:值类型传值,引用类型传引用,ref/out特殊理解JAVA和C#的string要特殊理解,表象是传值,实际要看虚拟机实现OK不
老赵的说法是有问题的。 世上只有值传递?我所接触的语言中,值传递传递的是实际参数的一个副本,而引用传递传递的就是实际参数的地址的一个副本,然后在函数中再去偷偷增加一条获取该地址内容的指令。为什么Java和C#中的对象类型传递比较容易误解,只要大家明白下面这条就好理解了。Java和C#中new出来的对象变量是存放在栈上的指针。而指针是什么?指针就是类似于int的基本数据类型。如 Object o = new Object(); 变量o就是基本数据类型,是值类型,并且存放在栈上。
Java 中的所有函数调用都是值传递。值传递是指,函数在调用时,传递的参数不是实参本身,而是它的副本。引用传递是指,函数在调用时,传递的参数就是实参本身(的地址)。显然,在使用引用传递的情况下,在函数体内可以对参数本身进行修改,修改结果会对函数调用者产生影响。而使用值传递,由于函数内对参数的修改实际上不是对参数本身,而是对参数的副本进行的修改,因此,修改结果不会对调用者产生影响。在 Java 中,对象(类的实例)都是通过引用来访问的。例如:
Object foo = new Object();
其中,foo 是一个引用,指向了新创建的这个 Object 对象。的确,你可以在某个方法(函数)中,对其参数引用的对象进行修改,例如:
void doSth(Object bar) {
bar.attr = newValue;
假设某个调用者调用了 doSth 方法,并且将 foo 传入。在方法返回之后,foo 所引用的对象的 attr 属性变成了 newValue。但这并不是值传递。因为 doSth 方法体内修改的是 foo 所引用的对象,而不是 foo 本身。在 Java 中,你绝不可能在方法体内,把作为参数传入的引用本身指向其他对象。因为 Java 所有的函数调用都是值传递。这样的修改只会修改参数的副本,而不是参数本身。--------------Java 的设计目的之一就是为了填 C/C++ 的各种「坑」,让编程语言更加易用和易于理解,例如垃圾自动回收机制,单继承策略,等等。引用传递使得方法内部可以对方法外的数据进行修改,这无疑增加了一定的(但我觉得这很少)危险性。当然,这会使语言的灵活性降低,就算你对你的数据掌控得很好,你也不能随心所欲地修改它。事实上,你完全可以通过传递引用参数来修改方法外创建的对象。因此,受到制约的实际上就只有那些原生类型而已。或许这是 Java 注重安全性与实用性而宁愿放弃一些灵活性的设计哲学的一种体现。
好吧,大家都在忙着解释这个语法的功用和名词的含义,却没有怎么去回答提问者真正的问题么:这种语言设计有哪些好处?糖?当然是糖,但事实上任何一个程序设计语言都是一坨糖,否则大家都图灵完备的,你用汇编不也能写出来?仅仅一个糖并不足以说明这种设计的优势。除了大家说的简化语法之外,这种语法设计还有两个重要的优势:1、性能。C#/CLR其实给予了程序员完整的操作栈对象的能力,ref参数本质上就是栈对象引用,栈对象(值类型对象)相较于引用类型对象是有极大的性能优势的,虽然这种性能的优势大多数时候并不能完整的体现出来,但是当这个方法被调用成千上万次时,这种优势就会变得非常可观。2、互操作性。在语言和运行时层面支持这种语法,对于互操作性是有很大的帮助的,这样一来,带有引用传递参数的C++的函数便可以轻松地映射为C#的函数,实现两个语言之间的无缝调用。
你的逻辑不自洽。假如你认为Java里传递的都是值,说明你把引用的值也当作是值,这么理解可以认为没有错,但得坚持下去。假如使用这种理解方式,你就不应该把C#里的ref或out传递看作是引用传递,因为它不过也就是传递了存放引用的地址的值罢了。世上只有值传递。
因为很多时候,没有必要为了多个返回值定义一个专用class,如果定义几个泛型类的话语义就太模糊了。-----------------分割线-----------------反对 的说法,完全是混淆概念的狡辩。在值传递与引用传递概念中是把实体(比如变量)当做一个整体看待的,而不管这个整体是一个结构体还是一个引用指针。值传递是指把这个实体当做参数,引用传递是指把这个实体的地址当做参数。世界上只有数值传递,此值非彼值,在当前问题的上下文中是没有任何意义的。
因为在某些时候按引用传递还是很有用的。比如:bool int.TryParse(string str, out int result)在使用这个函数时,可以直接通过返回值判断是否转换成功,通过引用传递的参数获取返回值。
这篇文章的解释挺不错的,楼主可以看看。再加上C#的比较下static void Main()
StringBuilder buffer= new StringBuilder("colin");
SChange(out buffer); //把out去掉再试试,下面的SChange的out也要同时去掉
System.Console.WriteLine( buffer);
public static void SChange (out StringBuilder str) {
str= new StringBuilder("huang");
C#的这个设计的作用相当有限,而且把语言复杂化了(每个初学者都要问Java和C#的这个区别有什么意义)而且别的不说,增加了设计API的决策成本,到底什么情况下用专用class返回,什么情况下用引用?例外情况又是什么?用引用会不会被指为ugly的代码风格?没有引用就不用想那么多啦!多省心
回答这个问题,个人觉得首先要分清几个概念: “值类型”与“引用类型”;“值传递”与“引用传递”。以下是这几个概念的解释:1 值类型: 存储在线程栈里的数据类型,如int型;2 引用类型:存储在托管堆里的数据类型,如Date型,或自定义class对象;3 值传递: 每次传递变量时,都是对栈里的原始值进行拷贝,如栈地址0001处存放一个整数值4,值传递时,先copy整数值4,将之存放在栈地址0002处的内存空间,再将栈地址0002进行传递;4 引用传递: 每次传递变量时,直接传递栈地址,如栈地址0001处存放一个整数值4,引用传递时,直接传递栈地址0001,而不做复制。
对于引用类型的变量而言,它们的“内容”存放在托管堆里,而在线程栈里存放的,是“内容”的“地址”。如对象在托管堆中的地址是x0001,那么栈地址0001所指向的内存空间中存放的就是这个对象的内存地址x0001(此处栈地址和托管堆地址并无任何对应关系,由操作系统进行分配)。
由此大概可以推想,“数据类型”与“传递方式”并不是相关的,也就是说“值类型”并不一定对应“值传递”,“引用类型”并不一定对应“引用传递”。其实可能的组合有4种: 1 “值类型”进行“值传递”;2 “值类型”进行“引用传递”;3 “引用类型”进行“值传递”;4 “引用类型”进行“引用传递”。我们分别针对这四种情况进行说明:
1 这种情况是经常见到的。首先定义函数function ChangeValue(int value){ value = 10;} 。int a = 1;ChangeValue(a); Print(a).
2 这种情况C#支持,而Java不支持。函数定义和调用都要稍作调整。具体如下:function ChangeValue(ref int value){ value = 10;} 。int a = 1;ChangeValue(ref a); Print(a).
大家应该能猜到,1和2打印出来的结果分别是“1”和“10”。因为值传递,传递的是原始值的副本,副本值的改变并不会影响原始值;而引用传递,传递的是原始值的地址,所以改变的就是原始值本身(引用传递在C#中以ref或out关键字标识)
对于引用类型而言,也是一样。例如:
3 Person p = new Person(“Tony”);定义函数: function ChangeValue(Person p){Person new_p = new Person("John"); p = new_p;},调用 ChangeValue(p); Print(p.Name);
Person p = new Person(“Tony”);定义函数: function ChangeValue(ref Person p){Person new_p = new Person("John"); p = new_p;},调用 ChangeValue(ref p); Print(p.Name);
对于情况3,打印的结果还是“Tony”,因为传递的是一个副本,那么即使指向的对象变化了,也是副本的变化,与原值无关;对于情况4,使用了ref关键字,传递的是原始值的地址,所以指向的修改完全是针对原始值的,所以4的打印结果为“John”。
有朋友可能会有疑惑: 因为Java只支持值传递,那么对于情况3里的引用类型Person来说,也只能进行值传递,那么修改的永远只能是副本,这样的话如何修改原对象的属性值呢?这岂不是出大乱子了?
其实即使是值传递,也是可以正常修改原对象的属性值的。例如Person类对象p在托管堆里的地址是x0001,而该地址存放在栈地址0001对应的内存空间中,即0001-&x0001,值传递时进行副本拷贝,拷贝值x0001到新的栈地址空间中,即0002-&x0001,可见原始值和副本值都是x0001,即对象p在托管堆里的地址。所以我们定义函数ChangeName(Person p){p.Name = "John";}调用 Person p = new Person(“Tony”); ChangeName(p); Print(p.Name);打印的结果是"John"。因为函数中p.Name = "John",实际是x0001.Name = "John",即修改的是我们想要修改的对象p。
因为Java只支持值传递,所以当传递一个引用类型给函数时,函数内部只能修改该对象的属性值,却不可以更改对象的指向本身,即如果引用指向对象p,函数内部是不能将引用指向换成new_p的;即使换了,换的也只是副本的指向而已。
至于Java为何这样设计,我猜是基于安全性的考虑吧。当然c#中用ref和out标识引用传递,也不失为一种好的设计思路。
这个命题本身就是错的。Java的赋值操作,都是复制变量的值。Java的对象型变量,本身就是一种引用类型(和C++的引用不同),所以在需要复制引用值的地方,例如函数实参传值,都是在传引用,不过是安全的引用。C#的引用模仿C++明确写出来,更像是语法糖,强制你在有歧义的地方做明确策略选择。是一种更佳的编程风格提倡。不过过于强制了。
一个个说的那么复杂,其实这种概念自己好好思考,自己想明白了就是很简单的问题,自己没想明白别人啰嗦再多只会让你更混乱。
说语言是值传递还是还是引用传递,其实都取决你怎么看参数变量的类型。比如如果你把 Object a = new Object()
里面的a 看做一个对象,你就会得出参数传递是引用传递的观点; 但是如果你把a当作一个引用看,那么引用就只是一个特殊的数字而已,那么自然就是值传递了。C#有两种数据类型 value type 以及 Java也有两种数据类型,primitive type 以及 reference type. C# 和java 的reference type 基本一致,用于对象和类。value type 和 primitive type基本差不多,但是 C#和java相比比较容易让人混乱的就是value type 多了一些组合的值类型,比如struct,struct不再是一个数字,而是多个数字; struct的使用方面了参数传递,但是反而让语法含糊不清。Object a = new Object()
StructX x = new StructX(); // 为什么要用new, 这个语法实在是个大错误,value type就不应该new
这里 x还是个值类型,虽然使用了new (实在是个非常糟糕的语法设计),但是值还是在栈上,传递的时候需要把整个struct拷贝一遍。(除非你在函数的定义里面显示指定为reference)结论:你把reference 看作特殊的value, 那么就是世上只有值传递。
我的理解是:从来就只有 pass by value当函数声明传的是 reference/pointer 时, 其实传的是对应的 4 或者 8 字节内存地址所代表的值而已.pointer 和 reference 的区别我理解就在于 pointer 可以做指针运算, 更灵活自由威力大, 同样破坏力也可以很大.
个人理解,java中传递一个已经实例化后的对象时,应该传递的是栈中存储的指向堆中这个对象实际内存区域首地址的值,即这个对象在栈中的引用,所以我一直觉得java中对象类型的传递是引用传递。这里以一个List对象为例,比如函数A中有一个List对象并实例化,把这个List传入B中,然后add一个内容进去,那么A中这个List的内容也会发生改变。实现这样的传递效果的前提条件就是这个List对象必须在A函数中new出来,因为只有new出来的时候,jvm才会在堆中分配这个List的内存,并在栈中记录下这个List在堆中内存的首地址,即这个对象的引用,如果函数A中没有实例化这个List,而在函数B中实例化,那么B中对这个List对象的操作并不会影响到A中的List对象。java中除了原子类型如int,float等,其他的类型都是对象类型,即都为引用传递。有一个特例,就是String类型,这是一个对象类型,但若使用String x = “111”这种方法赋值,那么x在堆中没有内存,它指向栈中值为“111”的那个地址,如果这个时候再定义一个String y = “111”,那么x == y会返回true,即它们的引用地址是相同的,若使用String x = new String("111"),String y = new String(“111”),则x == y返回false。好吧,其实我想说java也是有引用传递的。不知道题主明白没。欢迎拍砖--------------------------------------------------------------------------------------------------------------------------关于String的例子,谢谢的提醒。只有new关键字会在堆中创建新的内存,而=这个赋值操作是将两个对象指向同一个栈中的引用地址。所以String的例子并不特殊。如所说的引用传递的概念,那么java确实上都是值传递,如果传递的是这个对象在堆内存中的地址,才可以叫做引用传递。
其实,我们要先讨论“当我们在讨论XX的时候,实际上在说什么?”那么,我们说的“值传递”、“引用传递”分别是什么呢?有“狭义”“广义”的值传递”“引用传递”么?很遗憾,其实是有的。最开始,函数(或者方法,下面统称函数)调用的时候,我们都是把参数统一复制一份到某个地方(栈),函数就去这个地方就能找到所有的参数了,这就是值传递。后来,人们想做这么一件事情:一个函数要返回多个值,或者说,函数想把对参数的修改保留下来,而不是函数结束调用了之后这个修改就烟消云散了;人们还想干一种事情:函数的参数太大了太多了,如果调用函数的时候要把它们全复制一份的话,函数调用的开销太大。这两种事情,都可以通过同一种方法来解决:就是把参数们放到一个地方,调用函数的时候,不复制这些参数,而是把参数的地址告诉函数。这就是引用传递。这就是最广义的“值传递”和“引用传递”:从用途以及概念来定义,抛开所有的语言实现。不同的语言为了达到上面的“值传递”和“引用传递”的目的,各有各的实现:C语言说,我用指针就可以搞定一切(但是其实是有漏洞的,下面再谈)。C++为了堵住C的漏洞,但是又为了和C语言兼容,于是加了另外一个语法去专门实现“引用”,造成的结果是,两种传参类型,但是有三种调用方法。Java说,你们太扯了,我要优雅!于是Java实际上最后就变成了所有的基本类型是值传递,所有的对象是引用传递(但是C语言的漏洞Java还是有,这也是为什么说Java本质上全部是值传递也不能说是错的)。最后,C#就出了这么一个大补丁……我们来谈一下C语言的那个漏洞是什么。先说一下,引用传递要做的一件事情是什么?函数想把对参数的修改保留下。对参数的修改都有什么方式?1 如果是基本类型,赋值\自增自减2 如果是类\结构体,对其成员赋值\自增自减3 如果是类\结构体,调用能改变其成员的函数C语言是这么做的class MyCvoid foo(int *pInt, MyClass *pMyClass);对1 2 3的操作,在foo里面,分别是1 *pInt = 3;2 *pMyClass = *(new MyClass());//注意,这会有内存泄漏,但是不影响我们说的问题3 pMyClass-&doSomething();但是万一有哪个不开眼foo的实现者,在foo里面写出了如下代码1 pInt = pAnotherI2 pMyClass = new MyClass();╮(╯_╰)╭这种写法有时候有他的用处,但是对一个初学者来说,很容易混淆,尤其是第二种,特别是在Java里面,对初学者来说,坑爹啊!所以大牛中牛小牛们谆谆教导初学者们“Java全部是值传递”C++为了避免这个问题,改了改语法,将"&"这个符号扩展了一下,有了下面这个使用方法:void foo(int &pInt, MyClass &pMyClass);这样子,上面说的漏洞就堵住了,但是,为了兼容C语言,传指针的使用方法还保留了下来……而Java呢,搞到最后,发现C语言的这个坑还是没有填,到最后就只好说“Java全部是值传递”,但是对“3 如果是类\结构体,调用能改变其成员的函数”的操作,又不能很好的自圆其说了……所以说,Java还是没有完全躲开指针,让初学者不踩指针的坑还是没有完全达到,这里也是其中的一个例子。另外,Java的这个特性,没有办法让基本类型传引用……为了填Java的这个“没有办法让基本类型传引用”的坑,C#就又把C++对C的填漏洞的方法用了一遍,让你明确说出来,这样子虽然增加了新关键字,写起来也麻烦了,但是其实概念上是清晰了的。最后再说一下上面说的引用传递的两种目的的后一种,为了让使用者区分函数的目的到底是改变参数还是只是为了效率,于是在引用传递上又可以加const来修饰,含义就是——“我只是抱抱肯定不进去”~\(≧▽≦)/~

我要回帖

更多关于 java 取整数 的文章

 

随机推荐