java中java string类型比较作为形参的问题

在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
1、问题描述java方法传String类型的参数时,为啥方法对值的修改没有在方法之外生效?假设是其他类型的对象,那么方法对对象的数据的修改是会在方法之外生效的啊,可是String类型也是对象类型啊,为啥就没有在方法之外生效呢?
2、代码示例
//示例1:对象类型
public class PassReferByValue
String a = "123";
public static void test(PassReferByValue test)
test.a = "abc";
public static void main(String[] args)
PassReferByValue test = new PassReferByValue();
System.out.println("对象的数据的初始值是:" + test.a); //123
test(test);
System.out.println("通过调用test方法修改对象的数据的值之后:" + test.a); //abc
总结:因为是对象类型,所以方法每次修改对象的数据的值之后,都在方法之外生效了,也就是说,在方法之外和在方法之内访问到的对象的数据的值是一致的。
//示例2:String类型
public class Test
public static void test(String str)
str = "word";
public static void main(String[] args)
String string = "hello";
System.out.println("对象的数据的初始值是:" + string);
test(string);
System.out.println("通过调用test方法修改对象的值之后还是以前的值:" + string);
总结:如果方法的参数是String类型,虽然方法修改了它的值,但是并没有在方法之外生效,也就是说,在方法之外和在方法之内的访问到的值不一样!!!这是为什么???
3、网上的解释String等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。
这样的解释太肤浅了,完全是基于文字的描述,有没有基于代码层面的解释,或者其他的更深层次的解释呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
按照你的理解思路来讲
示例一确实是对对象的数据的修改,但是示例二却是对参数本身的修改了
不管是值传递还是引用传递,其实本质上都是值传递,方法调用的时候 计算出参数的值,拷贝一份给对应的参数
只是对于对象类型,传递的是对象的引用(或者理解为指针,地址)值,虽然参数拿到的是拷贝的引用,但是和原引用指向的是同一个对象,因此根据这个引用可以操作到原对象的数据
你的示例二中,调用方法时,计算参数string的值(可以理解为hello这个字符串对象在内存中的地址),拷贝给参数str,参数str虽然拿到了原来hello字符串对象的引用(即str的值等于string的值,也即hello的地址),但是立马给这个参数重新赋值,这个时候str参数已经跟hello字符串没有任何关系了,str不再指向hello,改指向world了,但是这个过程中hello自身以及hello在内存中的地址没有任何变化,方法外部的string变量也一直指向hello这个字符串对象,没有任何变化
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
三句话总结一下:1.对象就是传引用2.原始类型就是传值3.String,Integer, Double等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。可以认为是传值。Integer 和 String 一样。保存value的类变量是Final属性,无法被修改,只能被重新赋值/生成新的对象。 当Integer 做为方法参数传递进方法内时,对其的赋值都会导致 原Integer 的引用被 指向了方法内的栈地址,失去了对原类变量地址的指向。对赋值后的Integer对象做得任何操作,都不会影响原来对象。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
test1.a = "567",这里你改的是 test1 所引用的对象的属性
str = "word" 你这里改的是引用变量 str 所指向的对象。
简单的说,两个,小明和小红,你给小明把手换成了机械手,小明的手就真的换了,但是你把小红改名叫小明……小红这个人本身还是没变的。
再深层一点,小明和小红去参加一个活动,活动不需要知道你的真名,所以给他们分配了代号A和B。这个时候,活动中A受伤了,把手换成了机械的,结果活动完了,小明的手确实已经换成机械的了。但是B只是把名牌了C进行了交换,出来之后,小红还是小红,并没有变成C对应的那个人。
这里,活动就是方法,进去分配的代号就是形参,对形参直接赋值不会影响实参,但对形参引用的对象的属性进行赋值,实际已经影响到了对象的属性。
给你补充一段带注释的代码,看能不能帮助你理解。如果要了解方法调用的真实过程还涉及栈之类的知识,就不搞那么复杂了。这段代码没有输出,你可以在理解之后自己尝试加一些输出来验证自己的理解是否正确。
public class PassReferByValue
String a = "123";
public static void test(PassReferByValue test)
test.a = "abc";
public static void test2(PassReferByValue test) {
test = new PassReferByValue();
test.a = "cde";
public static void test3(String s) {
s = "world";
public static void main(String[] args)
PassReferByValue obj = new PassReferByValue();
// -----------------------------------------------
// test(obj);
// 如果把这个调用过程展开,代码就像这样(为了便于识别,我改了下变量名
// 说明一下:下面用 { } 代码段主要是为了限定里面的变量作用域
// 进入 test(obj);
PassReferByValue test =
test.a = "abc";
// 没有返回类型,所以这里方法直接结束,出来
// ------------------------------------------------
// 现在来展开 test2(obj);
PassReferByValue test =
test = new PassReferByValue();
// test 是一个新对象,不是 obj 了
test.a = "cde";
// 改变的是新对象,对 obj 没有影响
// 所以方法调用结束之后 obj 还是没变,还是 obj.a.equals("abc");
// -------------------------------------------------
// 现在来看 string 的情况
String hello = "hello";
// 这里开始展开 test3(hello);
String s =
s = "world";
// 这里修改了 s 引用的对象,但没有修改 hello 引用的对象
// 所以 hello.equals("hello"), s.equals("world");
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
值传递,引用传递
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
Java中除了String,其他的Object都是按引用传递。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
//示例2:String类型
public class Test
public static void test(String str)
//str这个变量作用域在test这个函数里,原本指向"hello",现在指向"word"
str = "word";
public static void main(String[] args)
String string = "hello";
System.out.println("对象的数据的初始值是:" + string);
test(string);
System.out.println("通过调用test方法修改对象的值之后还是以前的值:" + string);
我的一篇的开头有讲到相关知识点,看你有点晕乎乎的,向你推荐一下。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
String是immutable类型,也就是说其值是不可变的。例如String a = "abc",在内存中a这个引用指向"abc"这块内存,当使用a = "bcd"时,并没有将"abc"所在内存块的值改为"bcd",而是另外生成一个字符串"bcd",然后将a指向"bcd",所以方法外的引用仍然指向"abc"这块内存。
而可变的类型,会直接修改"abc"所在内存的值,这样做方法外的引用仍然指向原来的内存地址,于是可以在方法外访问到修改后的值。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
String对象中包含的字符串是不能被修改的,当String类型的变量被重新赋值后,其引用也会发生变化,是一个新的对象了。
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。java子类类型的对象作为实参传向父类类型的形参,出现的问题分析。
java中一个关于子类类型的对象作为实参传向父类类型的形参。
首先有几点需要强调一下。&&&
1.java传递对象时进行的是首地址传递。传递的是对象分配在堆中的首地址。
2.对象的创建过程的第一步“声明”中声明了
在此处定义了父类的equals方法。
boolean equals(Object obj){
&& if(this == obj){
&& if(obj == null){
&& if(getClass() !=
obj.getClass()){
Citizen other =
(Citizen)&&
return this.id.equals(other.id);
&* Citizen的子类Army
public class Army extends Citizen {&
&String armyId;
&* 子类构造方法
&public Army(String id,String armyId){
&&super(id);
&&this.armyId =
armyId;&&&&
&* 子类重写父类的equals
&public boolean equals(Citizen
&&System.out.println(obj.getClass());
//输出结果为"class Army"即obj是子类&&&&&&&
&&/*此处使用obj.armyID会出现错误,因为obj属于父类类型*/
矛盾出现!上面一句话的结果说obj是子类类型,下面一句话只承认obj的父类用法*/
&&Army other =
&&return super.equals(obj) &
this.armyId.equals(other.armyId);&&
&* 测试程序
public class Demo {
&public static void
main(String[] args){
&&Army c = new
Army("150102","130324") ;
&&Army d = new
Army("150102","130324") ;
&&System.out.println(&
c.equals(d) );&&
矛盾之一:在子类的equals方法里面,即使形参列表的声明中obj是父类类型,但调用obj的*.getClass()方法,返回的结果始终是子类类型。
矛盾之二:虽然再obj的*.getClass()方法里说obj是子类类型,但是在equals方法执行过程中,obj只能当作父类类型使用!!
这两点矛盾可以用本文开头强调的两点来解释。由以上程序代码可以看出。对象的首地址传递过去了,对象在堆中的属性引用受到其形参声明的限制。但是在栈中的方法的使用却不受到这种限制。这又引出一个新问题:对象的属性存放在堆中,方法存放在栈中,引用变量在栈中记录了对象在堆中的首地址,是否也记录了在栈中方法的首地址。还是栈中方法的首地址由对象在堆中的内存纪录?
我们知道对象的创建过程分为3步:(1)声明--声明了对象所属类型的引用变量,此时并没有分配任何内存空间。(<FONT COLOR="#)给栈中的引用变量。
&&&&先把问题留在这里,有待以后解决.......
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。java(11)
转载:http://blog.csdn.net/pony_maggie/article/details/
看一段代码:
如果你认为arrayPassTest 函数中,s是作为&#20540;传递,而ss是作为引用传递,所以有这样的输出结果,也不算错误,但是决对没有真正理解里面的原因。在这里,String 类型的传递是引用传递,也即是地址传递。这个是毋庸置疑的。因为在里,String是对象类型,作为参数肯定是引用传递。之所以有&#20540;传递的效果,是因为Stirng内部实现时,是用char[]
来存储字符串的,所以String相当于char[]的包装类,那java中,包装类的一个特质就是&#20540;操作时体现对应的基本类型的特质。
这个确实有点难理解,尤其是从C/C&#43;&#43;转出过的程序员。需要再慢慢揣摩。
ss参数完全符合引用传递的特点,很好理解,不多说。附上String的构造函数实现,
这个示例也给我们一个启示,当写一个函数传递数组时,不要直接对内部成员赋&#20540;,否则结果就不可控了, 比如下面这个函数,如果myArray被某个成员函数改变了,那么传递的这个数组也会改变。
而应该这样实现比较好,MyBatis 参数类型为String时常见问题及解决方法
转载 & & 作者:Rain_Git
这篇文章主要介绍了MyBatis 参数类型为String时常见问题及解决方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
1. 参数为String时的插值问题
假设有下面一Dao接口方法
public Account findByAccountType (String type)throws DaoE
对应的Mapper.xml
&select id="findByAccountType " parameterType="string" resultType="account"&
form account
&if test ="type != null"&
type=#{type}
一般我们都是按这样的方式来写的,对于其他类型是没错的,但是如果为String的话会抛下面的异常:
There is no getter for property named 'type ' in 'class java.lang.String'
因为MyBatis要求如果参数为String的话,不管接口方法的形参是什么,在Mapper.xml中引用时需要改变为_parameter才能识别 :
&select id="findByAccountType " parameterType="string" resultType="account"&
form account
&if test ="_parameter!= null"&
type=#{_parameter}
2. 对字符串参数进行是否相等 比较时的问题
&if test="_parameter == '1' "&
type=#{_parameter}
&if test='_parameter == "1" '&
type=#{_parameter}
&if test="_parameter == '1'.toString() "&
type=#{_parameter}
注:上述问题不仅限于&if&标签,其他动态sql标签在对String进行处理时也会出现同样的问题。
以上所述是小编给大家介绍的MyBatis 参数类型为String时常见问题及解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具鍗氬?鍒嗙被锛

我要回帖

更多关于 java中string类型 的文章

 

随机推荐