Java中的final怎么了,String的值传递还是引用传递?
2015-09-18 10:26
771 查看
final关键词会被用在四个地方;
1、类定义;
2、变量定义;
3、方法定义;
4、方法的入参;
第一种应用,那就是String类了;
第二种应用,定义常量用;
第三种应用,单纯的不希望方法被覆盖;
第四种应用,就涉及到值传递还是引用传递了~~~~~
先看代码:
package string;
public class FinalString {
/**
* final类讨论
*
* @param args
*/
static String strc = "Hust";
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* @String 是final类,因此不能修改原对象。当非要对他进行修改的时候,也并非是对原对象修改,而是重新创建一个对象
* @str2 指向的还是原对象hust
*/
String str1 = "Hust";
String str2 = str1;
str1 += str1;<span style="white-space:pre"> </span>//此处,你以为你在修改值为hust的String对象,其实你只是在修改str变量的指向!
System.out.println(str1);//HustHust
System.out.println(str2);//Hust
<span style="white-space:pre"> </span>
看完上面的程序,我想大家应该对被定义成final的String和不是Final的StringB有什么区别了~~
当对String类型的变量进行修改时,会一直创建新的对象,放弃原来对象。
有一个StringBuffer类型可以作为String的替代拼,其实和StringB是一样的,放弃了Final标记。
String导致更改时一直新建新建,为什么要设置成final呢?
答:其中一个理由就是,尽管String类型是引用传递,但是却可以像int,char那样在函数方法中起到值传递的效果!在方法中修改入参的String不会影响原来的String对象!因为String的使用是如此的广泛,作为方法的入参也是非常多,String又不想Integer那样有基本类型的实现,只要借用这种方式实现值传递了!如果不用final的,那就真的是引用传递,通过上面的测试,你能看出对于非final类型的入参,即便添加final标记,也不能阻止引用对象的修改,如果你要问为什么不能阻止,我会说此时的final限制的是变量,不是对象~~
事实上,追本溯源的说final类的意义是不能被继承,指示为了达到这个目的的!并非为了阻止修改类的内容!目前Java似乎还没有提供阻止类被修改的方案,除了一下方式!:
final String str;
上面定义的str和i看起来都挺像定义常量的,但事实上只有int的定义方式才算是定义常量,String并非是直接定义常量,而是间接实现的,理由上面找!你想问第三行是定义StringB类型的常量吗?不是,第三行定义的是死死盯着某个StringB类型的对象的变量,死死盯着从来不转移目光!
1、类定义;
2、变量定义;
3、方法定义;
4、方法的入参;
第一种应用,那就是String类了;
第二种应用,定义常量用;
第三种应用,单纯的不希望方法被覆盖;
第四种应用,就涉及到值传递还是引用传递了~~~~~
先看代码:
package string;
public class FinalString {
/**
* final类讨论
*
* @param args
*/
static String strc = "Hust";
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* @String 是final类,因此不能修改原对象。当非要对他进行修改的时候,也并非是对原对象修改,而是重新创建一个对象
* @str2 指向的还是原对象hust
*/
String str1 = "Hust";
String str2 = str1;
str1 += str1;<span style="white-space:pre"> </span>//此处,你以为你在修改值为hust的String对象,其实你只是在修改str变量的指向!
System.out.println(str1);//HustHust
System.out.println(str2);//Hust
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>final String str11 = "Hust";<span style="white-space:pre"> </span>//比如此处str11被定义为final时,str11已经不允许被修改了
<span style="white-space:pre"> </span>//str11 += str11;
/** * 自定义的StringB不是Final类,他是可修改的,而且是在原对象上修改的,所以strv1和strv2一直指向同一个对象 */ StringB strv1 = new StringB(); StringB strv2 = strv1; strv1.name += strv1.name; System.out.println(strv1.name);//Hust1Hust1 System.out.println(strv2.name);//Hust1Hust1 changestr(strc); } public static void changestr(String s) { /** * String传值本来是引用传递,下面的判断也可以印证! */ System.out.println(s == strc);//true s = "HustHust"; /** * 但是String是final的,对s进行修改,s会重新创建,s的指向不在是原来的strc,对s的修改也没有影响到原来strc, * 造成String传值的假象 */ System.out.println(s == strc);//false } public static void changestr1(final String s, final int v, int k, final StringB b) { /** * s,v的修改都是不允许,他们被定义为final,表示不允许修改。对s修改,则会重新创建String,对s重新指向。如果对v需改, * 则v会重现指向常量池地址 */ // s = "HustHust"; // v = 300; k = 200; /** * 尽管b也被设置成final,但是对b.name的修改并不会影响b的指向,所以这种修改是允许的,一旦想要修改b的指向则会报错 */ b.name = "HustHust"; // b = null; } } /** * 定义一般类 * * @author M007 * */ class StringB { String name = "Hust1"; }
看完上面的程序,我想大家应该对被定义成final的String和不是Final的StringB有什么区别了~~
当对String类型的变量进行修改时,会一直创建新的对象,放弃原来对象。
有一个StringBuffer类型可以作为String的替代拼,其实和StringB是一样的,放弃了Final标记。
String导致更改时一直新建新建,为什么要设置成final呢?
答:其中一个理由就是,尽管String类型是引用传递,但是却可以像int,char那样在函数方法中起到值传递的效果!在方法中修改入参的String不会影响原来的String对象!因为String的使用是如此的广泛,作为方法的入参也是非常多,String又不想Integer那样有基本类型的实现,只要借用这种方式实现值传递了!如果不用final的,那就真的是引用传递,通过上面的测试,你能看出对于非final类型的入参,即便添加final标记,也不能阻止引用对象的修改,如果你要问为什么不能阻止,我会说此时的final限制的是变量,不是对象~~
事实上,追本溯源的说final类的意义是不能被继承,指示为了达到这个目的的!并非为了阻止修改类的内容!目前Java似乎还没有提供阻止类被修改的方案,除了一下方式!:
final String str;
final int i;
final StringB strb;
上面定义的str和i看起来都挺像定义常量的,但事实上只有int的定义方式才算是定义常量,String并非是直接定义常量,而是间接实现的,理由上面找!你想问第三行是定义StringB类型的常量吗?不是,第三行定义的是死死盯着某个StringB类型的对象的变量,死死盯着从来不转移目光!
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统