- 浏览: 9881 次
- 性别:
文章分类
最新评论
关于java中值的传递与改变
Java中变量有其作用范围,属性(全局变量)在类中都是其作用范围,方法中定义的变量作用范围是方法,方法中的循环中定义的作用范围就只有在此循环中,若其他的方法或类要对这个变量作出改变或使用,则需要用到传值。
Java中传值一般要用到三个方法:建立一个get的方法,通过类名直接访问属性,构造方法传值。
一:建立一个get的方法
Get方法中可以从其他类中或本类中得到返回的值。当然,在本类中要得到一个值没有必要特别建立一个get方法,一般时候只要将这个值设置为属性即可,但注意,静态的方法中只能直接得到静态的变量。看下面的例子。
第1个类:此类是程序的入口
public class GetMethodTran { //建立一个一般属性值 private int j=15; //建立一个静态属性值 private static int k=20; public static void main(String[] args) { Tran t=new Tran(); //从其他类中得到一个整形值 int i=t.getInOtherClass(); System.out.println("从其他类中得到了值:i="+i);
GetMethodTran gmt=new GetMethodTran(); //从本类中得到一个整形值 i=gmt.getInSameClass(); System.out.println("从本类中得到了值:i="+i);
//从本类中得到静态属性值 int a=k; System.out.println("从本类中得到的值:a="+a);
//试图得到一个非静态的属性,会报错,因为程序入口main方法是静态的 //int b=j;
} /** * 建立的一个get方法 * @return 一个整形值 */ public int getInSameClass(){ return 10; } } |
第2个类,只有一个get方法,用于测试
public class Tran { /** * 建立的一个get方法 * @return 一个整形值 */ public int getInOtherClass(){ return 5; } } |
二:通过类名直接访问属性
此方法看似最为简便,那么在其他类中可以访问其他类中什么修饰符修饰下的属性呢?
下面的例子:
第1个类,用于得到别的类中的属性
public class GetAttribute {
public static void main(String[] args) { MyAttributes a=new MyAttributes(); //得到一个默认的属性 int i=a.def; //得到一个受保护的属性 i=a.pro; //得到一个公有的属性 i=a.pub; //得到一个静态默认的属性 i=a.sta; //试图得到一个私有的属性,报错 //i=a.pri;
} } |
第2个类,设置属性,用于测试
public class MyAttributes { //公有属性 public int pub=0; //受保护属性 protected int pro=5; //默认属性,一般认为是default或friendly int def=10; //私有属性 private int pri=15; //静态默认属性 static int sta=20;
} |
在这两个类,我把它们放置在同一个工程的同一个包中,所以才除了私有的属性不能被第一个类访问,当这两个类在不同的包中时会出现不同的结果,原因是java的保护机制,属性的修饰符的原因,修饰符控制了属性的访问范围。此时,了解修饰符很重要。以下是修饰符的简单介绍:
Public :公有,同包或不同的包中的类都可访问,
Protected: 本包中所有类以及包外的子类可访问,
Default/friendly:本包内的所有类可以访问,其他包中类包括子类无法访问,
Private: 只有在类的内部能访问,
当然了,不同的工程中,不管是什么修饰符下的属性也是不可访问的。
三:构造方法传值
此方法最为常用,它有固定的格式。看下面的例子。
第一个类,用于传值,开始程序
public class MyConstruction {
public static void main(String[] args) { int i=5; //实例对象,同时完成了传值 MyConstruction2 mc=new MyConstruction2(i);
}
} |
第二个类,得到第一个类的值,并打印出来
public class MyConstruction2 { private int i; /** * 有参的用于传值的构造方法 * @param i 传来的值 */
public MyConstruction2(int i){ this.i=i; System.out.println("得到传来的值:i="+i); }
} |
当然,构造方法中可以一次传递多个值,这个格式如下:
修饰符 类名(第一个值的类型 第一个值的变量名,第二个值的类型 第二个值的变量名,·····,第N个值的类型 第N个值的变量名){}
在有此类构造方法的类中,一般也设置了1~N个属性,在构造方法中的大括号中有N个“this.变量名=变量名;”,如何理解这个表达式呢。“This.变量名”是指本类中的属性,“=变量名”中的变量名是指构造方法格式中的1~N个变量名的某个,是调用了此个构造方法实例对象时传来的值。格式中“this.变量名=变量名;”这两个变量名不一定相同。
注意,当建立了有参构造方法,原有的无参构造方法将会隐藏,要用无参构造方法的话要在类中重新建立一个无参构造方法。
我们知道,传值的目的是对传来的值作出一些改变,传值方法的传的值也不仅是八种基本的数据类型,还包括了对象。有的时候,我们想传过去的值的改变不影响原来的值,有时却要传过去的值的改变要改变原来的值,来使原来的值产生一些必要的改变,出现新的样式。这就要理解和区别它们。这里主要讨论一下我对八种基本数据类型,数组,对象,String的一些传值改变的理解。
一:关于八种基本数据类型
基本数据类型一般都是值的传递,以int作为例子。
第一个类,程序入口,利用构造方法传值
public class BaseType {
public static void main(String[] args) { //传过去的值是0; int i=0; BaseType2 bt=new BaseType2(i); System.out.println("经过了BaseType2构造方法后的i值:"+i); change(i); System.out.println("执行了change(int i)方法后原来的i值:"+i); } /** * 改变i值的方法 * @param i 传入的数据 */ public static void change(int i){ i=10; System.out.println("执行了change(int i)方法的后来的i值:"+i); }
} |
第二个类,对值进行改变,
public class BaseType2 { private int i; public BaseType2(int i){ this.i=i; System.out.println("BaseType传来的i值:"+i+"\n执行了this.i=i;后的BaseType2的i值:"+this.i); //改变BaseType2的i值 this.i=5; System.out.println("执行了this.i=5;的BaseType2的i值:"+this.i); }
}
|
运行后得到的结果:
由此个例子可看出基本数据类型是通过值进行传递的,当传值后,将此个值赋给别的值A,A的改变不会引起原来的值的改变。
二:对象
关于对象的传值,毫无疑问,是地址的传递,这个关系如下:
我们可以打印这个对象,得到它的内存地址,如此,我们就可以判断出在操作对象传值后出现的改变是否改变了原值。只要地址不变,对这个对象作出的任何操作,都会影响原来的对象。看下面的例子。
第一个类:程序的入口,
public class ObjectTest {
public static void main(String[] args) { ObjectTest2 ot1=new ObjectTest2(20); System.out.println("未调用任何方法进的age="+ot1.age+" 对象内存地址:"+ot1); ot1.setNewAge2(ot1); System.out.println("调用了setNewAge2方法后的age="+ot1.age+" 对象的内存地址:"+ot1); ot1.setNewAge(ot1); System.out.println("调用了setNewAge方法后的age="+ot1.age+" 对象的内存地址:"+ot1); }
} |
第二个类:有两种方法,对传来的对象进行操作,
public class ObjectTest2 { //设置一个年龄属性 public int age; public ObjectTest2(int i){ this.age=i; } /** * 设置一个新的年龄 * @param i 新的年龄 */ private ObjectTest2 ot; public void setNewAge(ObjectTest2 ot){ this.ot=ot; this.ot.age=25; System.out.println("调用了setNewAge方法时的age="+this.ot.age+" 对象的内存地址:"+this.ot); } /** * 设置一个新的年龄 * @param i 新的年龄 */ public void setNewAge2(ObjectTest2 ot){ ot=new ObjectTest2(25); System.out.println("调用了setNewAge2方法时的age="+ot.age+" 对象的内存地址:"+ot); } } |
运行后的结果是:
可以看出,调用setNewAge2方法时,原对象并未发生改变,且输出的对象内存地址不同,意味了setNewAge2方法操作的是不同的两个对象。而setNewAge方法中,使原来的对象发生了改变,setNewAge方法中输出的对象内存地址是原对象的内存地址。其实很容易理解,因为在setNewAge2方法中语句: ot=new ObjectTest2(25);使对象内存地址改变了,所以操作了不同的对象。这里我们称对象的内存地址为对象引用。对于setNewAge方法的对象引用理解是:它们指向了同一个内存地址
对setNewAge2方法的对象引用理解是:它们指向了不同的内存地址
三:数组
关于数组的问题,一般都会问数组是对象还是基本数据类型,因为数组中的元素都是存储八基本数据类型的。一般认为数组是对象,第一,数组的创建使用了new关键字,第二,打印数组的变量名时显示的是内存地址。第三,只是声明而没有创建时,若要使用,必需将其设置为null,而不是其他或它本身就有默认值,可能这是分配内存空间的需要吧。
传递数组时,传递的是对象引用,那么,如果我们要传递后的数组改变不影响原数组怎么办?是否要进行循环,将数组的每个元素分别进行赋值呢。其实不用。看下面的例子。
public class About_ArrayCopy {
/** * @param args */ public static void main(String[] args) { //最后的一个逗号一向不要 int src[]=new int[]{1,2,3,4,5,}; int[] dest=new int[src.length]; //系统的方法,数组的复制 System.arraycopy(src, 0, dest, 0, src.length);
print(src); print(dest); System.out.println(src); System.out.println(dest);
} public static void print(int[] al){ for(int x:al){ System.out.print(x+" "); } System.out.println("\n------------------------"); }
}
|
得到的结果是:
可以看到,数组进行了复制,对象的引用不同。
但有时我们要复制的不是一维数组,而是多维数组怎么做?这个你们可以探究一下。
四:关于String
关于String,我们一定用过很多,这个一般会认为这也是一个基本的数据类型,很简单,因为我们打印变量名时,出现的是String的内容,而不是它的内存地址,而且,它的使用也是和基本数据类型一样,传值时的改变也一样。如下面的例子。
public class AboutString {
public static void main(String[] args) { String str1="abc"; System.out.println("调用changeStr前的str:"+str1); changeStr(str1); System.out.println("调用changeStr后的str:"+str1); } /** * 改变String的方法 * @param str String的传入 */ public static void changeStr(String str){ str=str+"def"; System.out.println("调用changeStr方法时的str:"+str); }
}
|
得到的结果是:
传值的改变规律也如基本数据类型。
但是,其实String是一个类,尽管它与基本数据类型如此相似。如下面的例子。
public class StringTest {
public static void main(String[] args) { //新建一个String对象 String s=new String("String is Class"); System.out.println(s); } } |
但是八种基本数据类明显不能通过new关键字来创建,否则会报错,这个或许能证明String的确是一个类吧。
但是,为什么String表现得如此像基本数据类型呢。因为String是一个非可变类,String对象一旦创建,就不能进行修改,String对象修改后,返回的都是它的新的对象。对此,明显对想用这个String的对象在不同的方法或类中进行修改造成困扰。在这介绍两个String子类用于解决这个问题。StringBuilder和StringBuffer。
如下面的例子。
public class StringTest {
public static void main(String[] args) { //创建StringBuilder对象 StringBuilder stbui=new StringBuilder("StringBuilder"); System.out.println("StringBuilder对象调用方法前:"+stbui); changeStringBuilder(stbui); System.out.println("StringBuilder对象调用方法后:"+stbui);
//创建StringBuffer对象 StringBuffer stbuf=new StringBuffer("StringBuffer"); System.out.println("StringBuffer对象调用方法前:"+stbuf); changeStringBuffer(stbuf); System.out.println("StringBuffer对象调用方法后:"+stbuf); } /** * 改变字符串的方法 1 * @param str 传入的字符串 */ public static void changeStringBuilder(StringBuilder str){ //改变字符串 str=str.append(" will change!"); System.out.println("StringBuilder对象调用方法时:"+str); } /** * 改变字符串的方法 2 * @param str 传入的字符串 */ public static void changeStringBuffer(StringBuffer str){ //改变字符串 str=str.append(" will change too!!"); System.out.println("StringBuffer对象调用方法中:"+str);
} } |
<!--EndFragment-->
相关推荐
Java中值传递和引用传递的区别详解 Java中值传递和引用传递是两个重要的参数传递机制,它们在程序设计中发挥着至关重要的作用。了解这两种机制的区别对于程序员来说是非常必要的。本文将通过示例代码详细介绍Java...
在Java编程环境下实现中值滤波,可以为图像处理软件或算法提供基础。以下是对中值滤波器及其Java实现的详细解释。 中值滤波的基本原理是:对于图像中每个像素点,我们选择一个窗口(通常为奇数大小的邻域),然后对...
### 均值中值滤波Java实现 #### 概述 本文档介绍了一个使用Java编写的简单应用程序,用于实现彩色图像的均值滤波和中值滤波处理。该程序通过图形用户界面(GUI)提供了操作选项,使得用户能够方便地加载、处理并...
java实现图像中值滤波
微分中值定理是微积分学中的核心概念,它揭示了函数的局部性质与它的导数之间的关系。本文主要探讨了微分中值定理在大学生数学竞赛中的应用,特别是如何通过构造辅助函数来解决相关问题。文章分为引言、定理的陈述、...
均值滤波和中值滤波的内容非常基础,均值滤波相当于低通滤波,有将图像模糊化的趋势,对椒盐噪声基本无能为力。中值滤波的优点是可以很好的过滤掉椒盐噪声,缺点是易造成图像的不连续性。
Java 实现下拉列表 JComboBox 中值和显示不同 在 Java 中,实现下拉列表 JComboBox 中值和显示不同是一种常见的需求。下拉列表 JComboBox 是 Java 中的一种 GUI 组件,用于提供用户选择多个选项。通常情况下,我们...
图像处理中值滤波与均值滤波Matlab算法实现 图像处理是计算机视觉和图像分析的根本步骤,其中图像滤波是图像处理中最基本的操作之一。中值滤波和均值滤波是图像滤波中两种最常用的方法,本文将通过Matlab算法实现...
缺省情况下C++以值传递方式传递对象到函数。除非你另外指定,否则函数参数都是以实际参数的复件(副本)为初值,而调用端所获得的亦是函数返回值得一个副本。这些复件由copy构造函数产生,会造成昂贵的费时操作。举...
DSP(Digital Signal Processing)中的中值滤波是一种非线性的信号处理技术,它在去除噪声、边缘保护等方面具有显著优势。这种滤波方法基于排序统计理论,通过将图像或信号的每个像素点替换为其邻域内像素值的中值来...
因此,如果在一个方法中改变了这个引用变量指向的对象,原始变量也会受到影响,因为它们都指向同一个堆内存对象。例如,如果你有一个对象`MyClass obj1 = new MyClass();`,然后创建一个新引用`MyClass obj2 = obj1;...
《第三章 微分中值定理与导数的应用习题课》主要涵盖了微积分中的核心概念和应用,包括洛必达法则、罗尔定理、拉格朗日中值定理、泰勒公式以及一系列与导数相关的知识点。这些定理和公式是解决实际问题和理解函数...
本文将深入探讨如何使用中值滤波器和小波分析相结合的方法来去除信号中的随机噪声和脉冲噪声,这是【标题】“中值与小波结合去噪程序”的核心内容。这种技术在【描述】中提及,通过这种方法可以有效地提升信号质量。...
与传统的线性滤波(如均值滤波)不同,它不采用邻域像素的平均值来代替中心像素的值,而是选取邻域内像素的中值。这一特性使得中值滤波在保留边缘细节的同时,能有效地消除孤立的噪声点,因此在图像清晰度提升方面...
在《中值滤波与均值滤波的去噪性能比较》这篇文章中,作者吴建华深入分析了这两种滤波器的性能,提供了有价值的理论见解和实践经验,对于从事图像处理和信号分析的专业人士来说是一份宝贵的参考资料。
2. **数据读取与排序**:根据窗口大小,从输入图像数据流中读取对应像素值并存入存储单元。然后,利用Verilog的并行处理能力,对这些像素值进行排序。排序方法可以是计数排序、快速排序等,但考虑到硬件实现的效率,...
该研究通过实验对比了快速中值滤波算法与传统快速排序算法及现有改进算法在处理速度上的差异。实验结果显示,针对七种常用窗口形状的快速中值滤波算法相比传统方法和其他改进算法,在速度上均有不同程度的提高。具体...
中值滤波常用于图像去噪,但也可能改变图像的一些细节,尤其是边缘。因此,在实际应用中,需要根据具体情况调整滤波器的大小,以平衡去噪效果和图像细节的保留。 总的来说,中值滤波是MATLAB图像处理的一个基础操作...
这个压缩包“关于微分中值定理的应用2800.zip”显然包含了对这一主题的深入探讨,特别是可能包含了一份2800字的文档,详细阐述了微分中值定理的实际应用。 微分中值定理主要包括三个主要定理:罗尔定理( Rolle's ...
### 中值定理的应用和推广 #### 摘要 本文首先介绍了微分中值定理的基础知识,随后探讨了微分中值定理的实际应用,并对比分析了几种不同的中值定理之间的异同点。最后,文章进一步讨论了如何将微分中值定理推广到...