- 浏览: 177418 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
surfingll:
思路不错,赞一个
站内信的实现:数据库的设计 -
shakajava:
哎,都是千篇一律的东西
站内信的实现:数据库的设计 -
java_xiaoyi:
不错...
java API -
tonysmith:
兄弟说的太对了。干活用了一年多,考官一问,只知其一。这是个“杯 ...
Java 中的访问权限控制 -
上官车月:
像牛一样的干了一年多,除了工作和加班 还真没有想过,基础的东西 ...
Java 中的访问权限控制
到J2SE 1.4为止,一直无法在Java程序里定义实参个数可变的方法——因为Java要求实参(Arguments)和形参(Parameters)的数量和类 型都必须逐一匹配,而形参的数目是在定义方法时就已经固定下来了。尽管可以通过重载机制,为同一个方法提供带有不同数量的形参的版本,但是这仍然不能达到 让实参数量任意变化的目的。
“用数组包裹实参”的做法可以分成三步:首先,为这个方法定义一个数组型的参数;然后在调用时,生成一个包含了所有要传递的实参的数组;最后,把这个数组作为一个实参传递过去。
大体说来,“Varargs”是“variable number of arguments”的意思。有时候也被简单的称为“variable arguments”,不过因为这一种叫法没有说明是什么东西可变,所以意义稍微有点模糊。
只要在一个形参的“类型”与“参数名”之间加上三个连续的“.”(即“...”,英文里的句中省略号),就可以让它和不确定个实参相匹配。而一个带有这样的形参的方法,就是一个实参个数可变的方法。
private static int sumUp(int... values) {
}
private static int sumUp(int... values) {
} 注意,只有最后一个形参才能被定义成“能和不确定个实参相匹配”的。因此,一个方法里只能有一个这样的形参。另外,如果这个方法还有其它的形参,要把它们放到前面的位置上。
private static int sumUp(int[] values) {
}
private static int sumUp(int[] values) {
} 由于存在着这样的转化,所以不能再为这个类定义一个和转化后的方法签名一致的方法。
private static int sumUp(int... values) {
}
private static int sumUp(int[] values) {
}
private static int sumUp(int... values) {
}
}
根据J2SE 1.5的语法,在“...”前面的空白字符是可有可无的。这样就有在“...”前面添加空白字符(形如“Object ... args”)和在“...”前面不加空白字符(形如“Object... args”)的两种写法。因为目前和J2SE 1.5相配合的Java Code Conventions还没有正式发布,所以无法知道究竟哪一种写法比较正统。不过,考虑到数组参数也有“Object [] args”和“Object[] args”两种书写方式,而正统的写法是不在“[]”前添加空白字符,似乎采取不加空白的“Object... args”的写法在整体上更协调一些。
只要把要传递的实参逐一写到相应的位置上,就可以调用一个实参个数可变的方法。不需要其它的步骤。
sumUp(1, 3, 5, 7);
在背地里,编译器会把这种调用过程转化为用“数组包裹实参”的形式:
sumUp(new int[]{1, 2, 3, 4});
另外,这里说的“不确定个”也包括零个,所以这样的调用也是合乎情理的:
sumUp();
这种调用方法被编译器秘密转化之后的效果,则等同于这样:
sumUp(new int[]{});
注意这时传递过去的是一个空数组,而不是null。这样就可以采取统一的形式来处理,而不必检测到底属于哪种情况。
处理个数可变的实参的办法,和处理数组实参的办法基本相同。所有的实参,都被保存到一个和形参同名的数组里。根据实际的需要,把这个数组里的元素读出之后,要蒸要煮,就可以随意了。
private static int sumUp(int... values) {
int sum = 0;
for (int i = 0; i < values.length; i++) {
sum += values[i];
}
return sum;
}
private static int sumUp(int... values) {
int sum = 0;
for (int i = 0; i < values.length; i++) {
sum += values[i];
}
return sum;
}
有时候,在接受了一组个数可变的实参之后,还要把它们传递给另一个实参个数可变的方法。因为编码时无法知道接受来的这一组实参的数目,所以“把它们 逐一写到该出现的位置上去”的做法并不可行。不过,这并不意味着这是个不可完成的任务,因为还有另外一种办法,可以用来调用实参个数可变的方法。
public class PrintfSample {
public static void main(String[] args) {
// 打印出“Pi:3.141593 E:2.718282”
printOut("Pi:%f E:%f\n", Math.PI, Math.E);
}
private static void printOut(String format, Object... args) {
// J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法
System.out.printf(format, args);
}
}
public class PrintfSample {
// 打印出“Pi:3.141593 E:2.718282”
printOut("Pi:%f E:%f\n", Math.PI, Math.E);
}
// J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法
System.out.printf(format, args);
}
}
C语言里的printf(按一定的格式输出字符串)和sprintf(按一定的格式组合字符串)是十分经典的使用Varargs机制的例子。在 J2SE 1.5中,也分别在java.io.PrintStream类和java.lang.String类中提供了类似的功能。
尽管在背地里,编译器会把能匹配不确定个实参的形参,转化为数组形参;而且也可以用数组包了实参,再传递给实参个数可变的方法;但是,这并不表示“能匹配不确定个实参的形参”和“数组形参”完全没有差异。
private static void testOverloading(int[] i) {
System.out.println("A");
}
public static void main(String[] args) {
testOverloading(1, 2, 3);// 编译出错
}
private static void testOverloading(int[] i) {
System.out.println("A");
}
testOverloading(1, 2, 3);// 编译出错
}
J2SE 1.5中新增了“泛型”的机制,可以在一定条件下把一个类型参数化。例如,可以在编写一个类的时候,把一个方法的形参的类型用一个标识符(如T)来代表, 至于这个标识符到底表示什么类型,则在生成这个类的实例的时候再行指定。这一机制可以用来提供更充分的代码重用和更严格的编译时类型检查。
private static <T> void testVarargs(T... args) {
// 编译出错
}
private static <T> void testVarargs(T... args) {
// 编译出错
}
造成这个现象的原因在于J2SE 1.5中的泛型机制的一个内在约束——不能拿用标识符来代表的类型来创建这一类型的实例。在出现支持没有了这个约束的Java版本之前,对于这个问题,基本没有太好的解决办法。
private static <T> void testVarargs(T[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
private static <T> void testVarargs(T[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
Java支持“重载”的机制,允许在同一个类拥有许多只有形参列表不同的方法。然后,由编译器根据调用时的实参来选择到底要执行哪一个方法。
public class OverloadingSampleA {
public static void main(String[] args) {
testOverloading(1);// 打印出A
testOverloading(1, 2);// 打印出B
testOverloading(1, 2, 3);// 打印出C
}
private static void testOverloading(int i) {
System.out.println("A");
}
private static void testOverloading(int i, int j) {
System.out.println("B");
}
private static void testOverloading(int i, int... more) {
System.out.println("C");
}
}
public class OverloadingSampleA {
testOverloading(1);// 打印出A
testOverloading(1, 2);// 打印出B
testOverloading(1, 2, 3);// 打印出C
}
System.out.println("A");
}
System.out.println("B");
}
System.out.println("C");
}
}
public class OverloadingSampleB {
public static void main(String[] args) {
testOverloading(1, 2, 3);// 编译出错
}
private static void testOverloading(Object... args) {
}
private static void testOverloading(Object o, Object... args) {
}
}
public class OverloadingSampleB {
testOverloading(1, 2, 3);// 编译出错
}
}
}
}
public class OverloadingSampleC {
public static void main(String[] args) { /* 编译出错 */
testOverloading(1, 2); /* 还是编译出错 */
testOverloading(new Integer(1), new Integer(2));
}
private static void testOverloading(int... args) {
}
private static void testOverloading(Integer... args) {
}
}
public class OverloadingSampleC {
testOverloading(1, 2); /* 还是编译出错 */
testOverloading(new Integer(1), new Integer(2));
}
}
}
}
和“用数组包裹”的做法相比,真正的实参个数可变的方法,在调用时传递参数的操作更为简单,含义也更为清楚。不过,这一机制也有它自身的局限,并不是一个完美无缺的解决方案。
可以通过Sun的Java Technology页面找到下载J2SE 1.5的SDK及其文档的链接,目前的最新版本是J2SDK 5.0 Beta 2。 《JSR 201: Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for loops and Static Import》中定义了很多在J2SE 1.5中出现了的新语言特性。虽然在标题里并没有明确提到,但是Varargs机制也在其中。 Calvin Austin在《J2SE 1.5 in a Nutshell》一文中,比较全面的对J2SE 1.5的新特性进行了简单的介绍。 John Zukowski在《驯服 Tiger:Tiger 预览版现已推出》一文中,介绍了如何开始使用J2SDK 1.5的基础知识。不过因为这篇文章是依照J2SDK 1.5 Alpha版的状况所写,所以里面提到的一些细节(如下载地址和默认安装路径)已经发生了变化。 John Zukowski在《驯服 Tiger:格式化输出》一文中,介绍了利用J2SE 1.5中新增的功能进行字符串格式化的办法。 Gilad Bracha在《Generics in the Java Programming Language》一文中,细致的介绍了J2SE 1.5中的泛型机制的使用方法和各种限制。 Martin Fowler在《Refactoring -- Improving the Design of Existing Code》(中译本名为《重构——改善既有代码的设计》, 由侯捷、熊节合译)一书的第七章《在对象之间移动特性(Moving Features Between Objects)》中,介绍了被称作“引入外加函数(Introduce Foreign Method)”和“引入本地扩展(Intoduce Local Extension)”的重构手法。 Gilad Bracha、James Gosling、Bill Joy和Guy Steele在《The Java Language Specification, 2nd Edition》一书里的《Classes》一章中的《Overloading》一节和《Expression》一章中的《Method Invocation Expressions》一节里深入的讨论了重载方面的问题。不过因为这本书是依照J2SDK 1.2版的状况所写,所以并没有完整地涵盖J2SE 1.5中的实际情况。
发表评论
-
HashMap HashTable区别
2012-03-05 15:52 1182我想先问一个问题:为什么hashmap允许key可以为null ... -
字符串比较之 “==”和 “equals”
2012-03-05 13:04 924字符串比较之 “==”和 “equals” 提示:引用 ... -
介绍一下抽象类和接口的异同
2012-03-02 16:27 1126我把基本的弄成了表格形式的。下载附件吧。本想吧table co ... -
Java 中的上转型对象 使用
2012-03-02 15:34 5572呵呵。最近交接工作比较闲,顺便温习一下基础的知识吧: 今天看 ... -
最好的学习地址:Java开源框架SSH 和 ANT的学习地址
2012-02-29 15:44 1090给大家推荐一个我经常去看的网站:这个网站适合初级程序员,学生, ... -
Java 中的访问权限控制
2012-02-29 15:39 2150要辞职了,突然觉得这 ... -
JDK和JRE的区别
2012-02-29 12:17 1187<!--end: blogStats -->< ... -
Java 接口学习笔记
2012-02-26 02:23 3java语言不支持一个类有多个直接的父类(多继承),但可以实现 ... -
浅谈HTTP中Get与Post的区别(转)
2012-02-15 12:24 1232浅谈HTTP中Get与Post的区别 Http ... -
JDK中的URLConnection参数详解(转)
2012-02-15 11:51 1379JDK中的URLConnection参数 ... -
Java利用HttpURLConnection发送post请求上传文件
2012-02-14 10:58 2224在页面里实现上传文件不是什么难事,写个form,加上encty ... -
Java 存储过程 Mysql
2011-12-20 12:16 1376一:Java如何实现对存储过程的调用: A:不带输出参数的 ... -
spring jdbcTemplate
2011-12-08 11:08 1023先看applicationContext.xml配置文件: ... -
MyEclipse 8.6 download 官方下载地址
2011-12-07 14:28 1469Downloads: MyEclipse 8.6 for Ec ... -
windows下架设svn服务器
2011-12-07 11:36 963* 传统的Subversion 服务器 ... -
tomcat7.0 manager app和host manager web管理(转)
2011-12-07 11:23 10871在捣腾Tomcat 7的时候遇到一个问题,很多人对tomc ... -
Tomcat7.0 Error:java.lang.NoClassDefFoundError
2011-12-07 10:34 1330前面一段时间看到Tomcat7.0发布了几个测试版,由于没有稳 ... -
tomcat5.5 Error:cannot find the declaration of element 'web-app'
2011-12-05 12:01 2136tomcat 启动:cannot find the decla ... -
设置 session 失效时间的方法(转)
2011-09-21 09:57 1251具体设置很简单,方法有三种: (1) 在主页面或者公共页 ... -
Java读取properties文件的思考
2011-07-19 10:24 1037Java读取properties文件的思考 Java读 ...
相关推荐
### Java 实现多边形游戏解析 #### 游戏规则及背景 本篇文章将详细介绍如何使用Java编程语言来实现一种有趣的单人游戏——多边形游戏。在游戏中,玩家需要处理一个多边形,该多边形有n个顶点,每个顶点都有一个...
在Java编程环境中,读取Excel数据是一项常见的任务,特别是在数据处理、数据分析或系统集成的场景中。本示例中,我们关注的是如何使用Java来读取Excel表格中的数据,并将其保存,这通常涉及到Apache POI库的应用。...
Java语言是一种面向对象的编程语言,其主要特点包括简单性、多变性、面向对象和不依赖操作系统等。这些特点使得Java具有良好的移植性和安全性,在网络编程方面得到了广泛应用。Java平台根据用途的不同,分为三个版本...
JAVA具有简单、多变、面向对象、不依赖操作系统的特点,因此它具有很好的移植性和安全性。在JAVA的学习过程中,搭建Java开发环境是基础,其中包括下载、安装和配置JDK。 JDK,即Java Development Kit,是Java的系统...
在Java代码中,创建Map对象并设置参数: ```java Map, Object> params = new HashMap(); params.put("username", "evankaka"); params.put("age", 25); List<User> users = sqlSession.selectList("selectUser...
Java是一种广泛使用的编程语言,它因简单、面向对象、多变性和不依赖于操作系统等特性而著名。Java语言的这些特性为网络编程提供了极大的便利,具有良好的移植性和安全性。Java平台可以根据不同的应用范围分为三个...
JAVA是一门面向对象的编程语言,具有跨平台性、灵活多变和实用性强等特点,是软件开发的主要语言之一。 二、JAVA实训经验 在三周的实训中,我们小组完成了小通讯录的程序,虽然还有些不完善的地方,但是通过实践,...
算法能够处理不同数量和不同概率分布的奖品,使得整个抽奖过程更加灵活多变。下面将详细介绍该算法的工作原理、关键步骤以及实现细节。 #### 关键知识点 1. **概率转换与缩放**:由于计算机生成的随机数通常为0到1...
【简易Java运维工具详解】 Java运维工具是一种利用Java编程语言构建的实用程序,它整合了各种运维功能,便于系统管理员对远程服务器进行...通过深入理解和使用这类工具,运维人员可以更好地应对复杂多变的运维挑战。
首先,Java作为后台开发的主要语言,具有跨平台、面向对象和丰富的库支持等优点,非常适合构建这种复杂且需求多变的车联网系统。在这个项目中,Java源码可能包含了车辆数据处理、用户管理、设备通信、数据分析等功能...
Java编程语言在处理数据导入和导出时,经常会用到一些通用模板,以提高代码的复用性和...这种模板化的设计模式在Java开发中具有广泛的应用价值,尤其是在处理大量数据和多变的需求时,能显著提升开发效率和代码质量。
Java是一种广泛应用于网络编程的程序设计语言,具有简单、多变、面向对象和不依赖操作系统的特性。Java以其良好的移植性和安全性,在网络编程领域有着广泛的应用。Java平台根据用途可以分为三个版本:JavaSE、JavaEE...
这里使用了`File`类的构造函数,传入两个参数:路径(`path`)和文件名(`name`)。这一步创建了一个`File`对象,但此时文件并未实际存在于文件系统中。 接下来调用`createNewFile()`方法来真正地在指定位置创建...
Java是一种广泛应用于网络编程领域的高级编程语言,其特点包括简单、多变、面向对象,且不依赖特定操作系统,具有良好的移植性和安全性。Java平台可依其用途分为三个版本:Java标准版(JavaSE),主要用于桌面级应用...
Java的特点使其在编程语言中独树一帜,并且Java程序的可移植性让它在多变的软件开发环境中占据了重要的位置。学习Java语言程序设计有助于学生建立起良好的软件开发基础,并为将来在更广泛的软件工程领域的工作奠定...
此外,Java 9 对现有的类库也进行了一系列改进,例如增强了 Stream API,使其更加灵活多变;改进了 JavaFX 平台,增强了用户界面组件的功能等。 #### 五、性能改进 性能始终是 Java 开发者关注的重点。Java 9 在这...
1. Java简介:Java是一种网络编程广泛应用的程序设计语言,它简单、多变、面向对象且不依赖操作系统,具备良好的移植性和安全性。Java平台根据用途分为三个主要版本:JavaSE(标准版)、JavaEE(企业版)、JavaME...