关于slifejava的信息

博主:adminadmin 2022-12-26 22:30:15 63

今天给各位分享slifejava的知识,其中也会对进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

在JAVA中如何实现长时间任务

摘要:在软件开发中,我们经常面临着处理长时间任务的多线程编程问题。在我们的ezOne平台的开发中就多处涉及到,如JPC数据服务JPC数据处理服务、报警联动、门禁系统等。本人在编写DEMO程序的过程中几易其稿,煞费心机,但依然感觉有许多地方需要改进,为了减少多线程编程带来的风险,我尝试翻译整理了一个类似问题的解决方案框架以达到一劳永逸。 为了便于阅读,保留原文。 一、问题背景Quite often, you need a class to perform tasks like data processing, listening to events, or checking another class' activities during the application’s lifetime. To achieve this, you probably use threads with a set of locks and notifications. Java Thread API is well documented, but you need a great deal of code and experience to make your thread work properly and efficiently. You can avoid writing such classes from scratch every time you need them and build a more robust application by applying the framework we'll discuss in this article. 在应用程序中我们经常需要一个类去完成像数据处理、监听事件或检查另一个类的活动等任务。为了达到这个目标,我们可能使用带有一套锁和消息通知的线程。JAVA 线程API已经很好的文档化,但为了使线程能够正确而高效地运行,程序员仍然需要丰富的编程经验并编写大量的代码。通过应用本篇文章中讨论的框架,程序员能够避免忍受煎熬写大量的代码,快速创建健壮的应用程序。 二、长时间运行任务的程序框架Framework for long-running tasks The primary thing about a long-lived task is that it should somehow be kept running during the application lifetime. The right way to accomplish this is to provide a thread of execution for a particular task. You create a task as a thread or as an implementation of the java.lang.Runnable interface. If you implement Runnable, you can gain better object-oriented design and avoid the single-inheritance problems. You can also more efficiently manipulate with Runnable instances, for example, using a thread pool that usually needs a Runnable instance, not a thread, to run. 关于长时间运行的任务的主要事情是如何在应用程序的生命期使它一直保持运行。实现的恰当方法是提供一个线程来执行这个特定的任务。我们可以通过继承Thread类或实现java.lang.Runnable接口来达到该目标。如果采用实现Runnable接口的方式,就可以能够获得更好的面向对象的设计,同时可以避免JAVA中的单继承问题。另外,我们也能更有效的处理Runnable实例(例如使用线程池通常需要一个Runnable实例而不是线程来运行)。 The essence of the framework is the abstract class Worker ( Listing A), which implements the Runnable interface and provides the helper methods for efficient task handling. Some of the methods are fully implemented, like the run() method, but some are abstract and have to be filled by you. If you want to create a long-running class, you need only to extend the Worker class and implement several abstract methods. Let’s look at these methods in more detail. 框架的基础是一个叫Worker的抽象类,它实现了Runnable接口,并提供了有效处理任务的好方法。这些方法有些已经被实现,如run()方法,但有些是抽象方法,开发人员必须自己来实现。如果要创建一个长时间运行的类,你只需要继承Worker类并实现几个抽象方法。让我们看看这些方法的细节。 The run() method of the Worker class is designed to continuously execute the work() method until it is stopped. The work() method can be responsible for data processing, reaction to some event, file reading or writing, SQL execution, etc. It can throw an exception, so it is a good practice to propagate it and let the run() method handle it. Worker 类的run()方法被设计成只要不停止运行就持续的执行work()方法。work()方法可以负责数据处理、事件响应、文件读写、,执行SQL命令等操作。这样work()方法能够抛出异常,并将异常传给run(),然后由run()方法来处理这些异常。 The run() method has two levels of try-catch clause: outside and inside the while-loop. The first try-catch clause is meant to catch all nonprogrammed exceptions and guarantee that the run() method never exits. The second clause will catch any kind of exceptions belonging to business logic and behave accordingly. If some waiting operation takes place in the work() method (e.g., waiting on an InputStream or a Socket), it is advisable to propagate an InterruptedException. The thing to keep in mind is that the work() method does not need to have any while-loop to keep it going as long as an application runs. The Worker does this for you. run()方法有内外两层try-catch语句:一层处于while-loop循环外,一层在while-loop循环内。前一个try-catch用于捕获非编程异常以确保run()方法不退出。后一个try-catch语句捕获关于业务逻辑和相应行为的各种异常。如果在work()方法中发生了一些等待操作(例如等待一个输入流或一个Socket),抛出一个InterruptedException的方法是可取的。要记住的是只要应用程序在运行,work()方法不需要任何while-loop循环去维持它运行,这一切由Worker代办了。 When the run() method starts, it calls the prepareWorker() which is designed to prepare all resources needed for a long-running task (Listing A). In this method call, you can, for example, establish a database connection or open a file that will be used further. It is especially good to place here some blocking operations like opening a socket, because they will be done in a separate thread and thus will not block the main thread of execution. run()开始时,调用prepareWorker()方法来准备长时间运行任务需要的所有资源(参考程序清单A)。例如 ,在这个方法中可以打开一个将要用到的数据库连接或文件。尤其对于那些像建立一个socket这样的阻塞操作放在这儿是很好的。因为若让它们在一个独立的线程中运行,则不会阻塞主线程的执行。 The opposite of the previous method is the releaseWorker() which is called when the run() method is about to exit (Listing A). Here, you can put the code to dispose of system resources used by this task or to perform other cleanup. This method is similar to java.lang.Object.finalize(), but it is explicitly called before a thread terminates. 与前面方法相反的是releaseWorker(),它在run()方法准备退出时被调用(参考程序清单A)。在该方法中你可以编写那些释放系统资源或执行其它清除动作的代码。该方法类似于java.lang.Object.finalize(),但它在线程中止时被显式的调用。 三、框架中的错误处理机制Handling errors in the framework Another important method is the handleError(), which takes a java.lang.Throwable as a parameter. This method is called each time an error situation occurs within the run() method. It is up to you how to implement error handling. One way is to log errors and control task termination by calling halt() method (Listing A). 另一个重要的方法是handleError(),它带有一个java.lang.Throwable的输入参数。在run()方法每次发生错误时调用这个方法。这依赖于你怎么实现错误处理。方法之一是写错误日志并通过调用halt()方法中止任务(参考程序清单A)。 The isCondition() method is used to tell whether execution of the work() method can be started, thus allowing granular control over a task. It is useful in event-triggered frameworks when execution of the work() method is pending until some condition?for example, a buffer is not empty?is fulfilled. In Worker’s implementation, the condition is checked upon a lock notification and periodically with a time interval you specify in the setTimeout() method (Listing A). If you don’t need any waiting blocks in a task, just make the isCondition() method always return true. isCondition()方法用于判断work()方法是否能够被执行。因此允许细粒度地控制任务。这在事件触发的框架中非常有用。当work()方法的执行条件未满足时,work方法将被挂起,直到条件完全满足(例如,缓存区非空)。在Worker的实现中这个条件将按在方法setTimeout()中指定的时间周期地检查一个锁通知。如果在任务中不需要任何等待阻塞,仅仅只要使isCondition()方法总是返回真值。 四、任务终止时机When to terminate You'll also need the isRunning(), broadcast(), and halt() methods. Querying isRunning(), you can check whether a task is still running and make a decision whether to terminate it. The broadcast() method just notifies the lock object and makes a task proceed if it has been waiting on this lock. The halt() method stops a task, so the run() method will exit as soon as the next isRunning() status is checked. Because this method notifies only one lock that may block this task’s thread, it is advisable to use the same lock object when you do blocking operations within the work() method ( Listing B). If you can't use the same lock object, such as when you're blocking on the java.io.InputStream.read() method, you should add explicit notification of all possible locks or add java.lang.Thread.interrupt() to your halt() method. The java.lang.Thread.interrupt() works if an object you are blocked on processes this signal correctly. For example, it works for InputStream.read() but doesn’t work for java.sql.PreparedStatement.execute(), so you have to test halt() method in each particular situation. 你还需要isRunning(), broadcast(), halt()方法。通过访问isRunning()方法,你将能检查某个任务是否正在运行,并决定是否中止它。broadcast()方法正确地通知锁对象,并且如果这个对象一直等待这个锁,那么就激活这个任务。halt()方法中止一个任务,因此下一isRunning()状态一旦被调用,run()方法就退出,因为这个方法只通知那个可能阻塞这个任务线程的锁。当在work()方法中执行阻塞作业时用相同的锁是明智的。如果你不能用相同的锁对象时,例如在执行java.io.InputStream.read()方法遇到阻塞时,你就应该添加所有可能锁的显式通知或者增加java.lang.Thread.interrupt()到halt()中。如果一个你阻塞的对象被正确处理,java.lang.Thread.interrupt()将会起作用。例如,它在InputStream.read()执行时有作用,但在执行java.sql.PreparedStatement.execute()不起作用,因此在每个特殊的条件下你必须测试halt()方法。 Once you are familiar with the Worker class, you can easily create your own implementation (Listing B). To run this class as a thread, simply use a new Thread(new WaitedWorker()).start. Applying Thread.interrupt() or Worker.halt() or a combination of them, you can control task execution precisely. For example, you can stop all workers when JVM shuts down by placing corresponding code in the java.lang.Runtime.addShutdownHook() method. 一旦你熟悉Worker类,你就很容易创建你自己的实现(参考程序清单B),为了把这类当作一个线程运行,仅仅只需简单地使用 new Thread(new WaitedWorker()).start。应用Thread.interrupt()或Worker.halt()或它们的组合,你就可以准确的控制任务的执行。例如当JVM通过在java.lang.Runtime.addShutdownHook()方法中放相应的代码停止时,你就能停止所有的任务。 四、结论Conclusion We've examined the long-running task framework and seen how to create new tasks based on its abstract class. Its architecture is clear and flexible and was designed with extensibility in mind. With this framework, you can avoid creating classes from scratch, and you'll be able to develop more efficient and reliable applications. 我们已经检查了长时间运行任务框架,并且看到怎样通过从创建一个基于它的抽象类的任务。它的构架是清晰和灵活的,并且被设计成可扩展的。用这个框架你能避免为创作类而绞尽脑汁,并且帮助你能够开发出高效、可靠的应用程序。 参考文献1、 Simon Brown 2、 Joseph L.Weber 致谢非常感谢曾一起工作的同事和为JAVA技术发展做出贡献的人们,没有他们的努力成果,我就不可能感受到JAVA语言的魅力;同时也要感谢我的上司周洪波博士和卢盛融总工程师,他们给予我许多有益的帮助。 关于译者胡继锋,软件工程师,清华同方应用信息系统本部ezONE研究院研发人员。曾经从事DEPHI、VB、VC、C、PHP、ASP、Oracle等的开发,现在热衷于JAVA技术。同时对资本市场有一定的兴趣。

JAVA程序求解

import java.util.Scanner;

public class test {

public static void main(String[] args) {

Scanner sca = new Scanner(System.in);

while (true) {

System.out.println("请输入用水类型:1 生活用水 ;2 工业用水;3退出");

int b = sca.nextInt();

if(b==3){

break;

}

System.out.println("请输入用水量(吨数,不足一吨按一吨计算):");

int a = sca.nextInt();

if (b == 1 a 15) {

System.out.println("水费是" + a * 3);

} else if (b == 1 a = 15 a 30) {

System.out.println("水费是" + (30 * 3 + (a - 30) * 6));

} else if (b == 1 a = 30) {

System.out.println("水费是" + a * 5);

} else if (b == 2) {

System.out.println("水费是" + a * 7);

}

}

}

}

Java中对象有什么用?

一切都是对象

“尽管以C++为基础,但Java是一种更纯粹的面向对象程序设计语言”。

无论C++还是Java都属于杂合语言。但在Java中,设计者觉得这种杂合并不象在C++里那么重要。杂合语言允许采用多种编程风格;之所以说C++是一种杂合语言,是因为它支持与C语言的向后兼容能力。由于C++是C的一个超集,所以包含的许多特性都是后者不具备的,这些特性使C++在某些地方显得过于复杂。

Java语言首先便假定了我们只希望进行面向对象的程序设计。也就是说,正式用它设计之前,必须先将自己的思想转入一个面向对象的世界(除非早已习惯了这个世界的思维方式)。只有做好这个准备工作,与其他OOP语言相比,才能体会到Java的易学易用。在本章,我们将探讨Java程序的基本组件,并体会为什么说Java乃至Java程序内的一切都是对象。

2.1 用句柄操纵对象

每种编程语言都有自己的数据处理方式。有些时候,程序员必须时刻留意准备处理的是什么类型。您曾利用一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C或C++里的指针)?

所有这些在Java里都得到了简化,任何东西都可看作对象。因此,我们可采用一种统一的语法,任何地方均可照搬不误。但要注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。在其他Java参考书里,还可看到有的人将其称作一个“引用”,甚至一个“指针”。可将这一情形想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。但一旦需要“换频道”或者“关小声音”,我们实际操纵的是遥控板(句柄),再由遥控板自己操纵电视机(对象)。如果要在房间里四处走走,并想保持对电视机的控制,那么手上拿着的是遥控板,而非电视机。

此外,即使没有电视机,遥控板亦可独立存在。也就是说,只是由于拥有一个句柄,并不表示必须有一个对象同它连接。所以如果想容纳一个词或句子,可创建一个String句柄:

String s;

但这里创建的只是句柄,并不是对象。若此时向s发送一条消息,就会获得一个错误(运行期)。这是由于s实际并未与任何东西连接(即“没有电视机”)。因此,一种更安全的做法是:创建一个句柄时,记住无论如何都进行初始化:

String s = "asdf";

然而,这里采用的是一种特殊类型:字串可用加引号的文字初始化。通常,必须为对象使用一种更通用的初始化类型。

2.2 所有对象都必须创建

创建句柄时,我们希望它同一个新对象连接。通常用new关键字达到这一目的。new的意思是:“把我变成这些对象的一种新类型”。所以在上面的例子中,可以说:

String s = new String("asdf");

它不仅指出“将我变成一个新字串”,也通过提供一个初始字串,指出了“如何生成这个新字串”。

当然,字串(String)并非唯一的类型。Java配套提供了数量众多的现成类型。对我们来讲,最重要的就是记住能自行创建类型。事实上,这应是Java程序设计的一项基本操作,是继续本书后余部分学习的基础。

2.2.1 保存到什么地方

程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的是内存的分配。有六个地方都可以保存数据:

(1) 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。

(2) 堆栈。驻留于常规RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,Java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java数据要保存在堆栈里——特别是对象句柄,但Java对象并不放到其中。

(3) 堆。一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!

(4) 静态存储。这儿的“静态”(Static)是指“位于固定位置”(尽管也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static关键字指出一个对象的特定元素是静态的。但Java对象本身永远都不会置入静态存储空间。

(5) 常数存储。常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。

(6) 非RAM存储。若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。Java 1.1提供了对Lightweight persistence的支持。未来的版本甚至可能提供更完整的方案。

2.2.2 特殊情况:主要类型

有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们。之所以要特别对待,是由于用new创建对象(特别是小的、简单的变量)并不是非常有效,因为new将对象置于“堆”里。对于这些类型,Java采纳了与C和C++相同的方法。也就是说,不是用new创建变量,而是创建一个并非句柄的“自动”变量。这个变量容纳了具体的值,并置于堆栈中,能够更高效地存取。

Java决定了每种主要类型的大小。就象在大多数语言里那样,这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。

主类型

大小

最小值

最大值

封装器类型

boolean

1-bit

Boolean

char

16-bit

Unicode 0

Unicode 216- 1

Character

byte

8-bit

-128

+127

Byte[11]

short

16-bit

-215

+215 – 1

Short1

int

32-bit

-231

+231 – 1

Integer

long

64-bit

-263

+263 – 1

Long

float

32-bit

IEEE754

IEEE754

Float

double

64-bit

IEEE754

IEEE754

Double

void

Void1

①:到Java 1.1才有,1.0版没有。

数值类型全都是有符号(正负号)的,所以不必费劲寻找没有符号的类型。

主数据类型也拥有自己的“封装器”(wrapper)类。这意味着假如想让堆内一个非主要对象表示那个主类型,就要使用对应的封装器。例如:

char c = 'x';

Character C = new Character('c');

也可以直接使用:

Character C = new Character('x');

这样做的原因将在以后的章节里解释。

1. 高精度数字

Java 1.1增加了两个类,用于进行高精度的计算:BigInteger和BigDecimal。尽管它们大致可以划分为“封装器”类型,但两者都没有对应的“主类型”。

这两个类都有自己特殊的“方法”,对应于我们针对主类型执行的操作。也就是说,能对int或float做的事情,对BigInteger和BigDecimal一样可以做。只是必须使用方法调用,不能使用运算符。此外,由于牵涉更多,所以运算速度会慢一些。我们牺牲了速度,但换来了精度。

BigInteger支持任意精度的整数。也就是说,我们可精确表示任意大小的整数值,同时在运算过程中不会丢失任何信息。

BigDecimal支持任意精度的定点数字。例如,可用它进行精确的币值计算。

至于调用这两个类时可选用的构建器和方法,请自行参考联机帮助文档。

2.2.3 Java的数组

几乎所有程序设计语言都支持数组。在C和C++里使用数组是非常危险的,因为那些数组只是内存块。若程序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果(注释②)。

②:在C++里,应尽量不要使用数组,换用标准模板库(Standard TemplateLibrary)里更安全的容器。

Java的一项主要设计目标就是安全性。所以在C和C++里困扰程序员的许多问题都未在Java里重复。一个Java可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。但由此换回的是更高的安全性,以及更高的工作效率。为此付出少许代价是值得的。

创建对象数组时,实际创建的是一个句柄数组。而且每个句柄都会自动初始化成一个特殊值,并带有自己的关键字:null(空)。一旦Java看到null,就知道该句柄并未指向一个对象。正式使用前,必须为每个句柄都分配一个对象。若试图使用依然为null的一个句柄,就会在运行期报告问题。因此,典型的数组错误在Java里就得到了避免。

也可以创建主类型数组。同样地,编译器能够担保对它的初始化,因为会将那个数组的内存划分成零。

数组问题将在以后的章节里详细讨论。

2.3 绝对不要清除对象

在大多数程序设计语言中,变量的“存在时间”(Lifetime)一直是程序员需要着重考虑的问题。变量应持续多长的时间?如果想清除它,那么何时进行?在变量存在时间上纠缠不清会造成大量的程序错误。在下面的小节里,将阐示Java如何帮助我们完成所有清除工作,从而极大了简化了这个问题。

2.3.1 作用域

大多数程序设计语言都提供了“作用域”(Scope)的概念。对于在作用域里定义的名字,作用域同时决定了它的“可见性”以及“存在时间”。在C,C++和Java里,作用域是由花括号的位置决定的。参考下面这个例子:

{

int x = 12;

/* only x available */

{

int q = 96;

/* both x q available */

}

/* only x available */

/* q “out of scope” */

}

作为在作用域里定义的一个变量,它只有在那个作用域结束之前才可使用。

在上面的例子中,缩进排版使Java代码更易辨读。由于Java是一种形式自由的语言,所以额外的空格、制表位以及回车都不会对结果程序造成影响。

注意尽管在C和C++里是合法的,但在Java里不能象下面这样书写代码:

{

int x = 12;

{

int x = 96; /* illegal */

}

}

编译器会认为变量x已被定义。所以C和C++能将一个变量“隐藏”在一个更大的作用域里。但这种做法在Java里是不允许的,因为Java的设计者认为这样做使程序产生了混淆。

2.3.2 对象的作用域

Java对象不具备与主类型一样的存在时间。用new关键字创建一个Java对象的时候,它会超出作用域的范围之外。所以假若使用下面这段代码:

{

String s = new String("a string");

} /* 作用域的终点 */

那么句柄s会在作用域的终点处消失。然而,s指向的String对象依然占据着内存空间。在上面这段代码里,我们没有办法访问对象,因为指向它的唯一一个句柄已超出了作用域的边界。在后面的章节里,大家还会继续学习如何在程序运行期间传递和复制对象句柄。

这样造成的结果便是:对于用new创建的对象,只要我们愿意,它们就会一直保留下去。这个编程问题在C和C++里特别突出。看来在C++里遇到的麻烦最大:由于不能从语言获得任何帮助,所以在需要对象的时候,根本无法确定它们是否可用。而且更麻烦的是,在C++里,一旦工作完成,必须保证将对象清除。

这样便带来了一个有趣的问题。假如Java让对象依然故我,怎样才能防止它们大量充斥内存,并最终造成程序的“凝固”呢。在C++里,这个问题最令程序员头痛。但Java以后,情况却发生了改观。Java有一个特别的“垃圾收集器”,它会查找用new创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根本不必操心内存的回收问题。只需简单地创建对象,一旦不再需要它们,它们就会自动离去。这样做可防止在C++里很常见的一个编程问题:由于程序员忘记释放内存造成的“内存溢出”。

2.4 新建数据类型:类

如果说一切东西都是对象,那么用什么决定一个“类”(Class)的外观与行为呢?换句话说,是什么建立起了一个对象的“类型”(Type)呢?大家可能猜想有一个名为“type”的关键字。但从历史看来,大多数面向对象的语言都用关键字“class”表达这样一个意思:“我准备告诉你对象一种新类型的外观”。class关键字太常用了,以至于本书许多地方并没有用粗体字或双引号加以强调。在这个关键字的后面,应该跟随新数据类型的名称。例如:

class ATypeName {/*类主体置于这里}

这样就引入了一种新类型,接下来便可用new创建这种类型的一个新对象:

ATypeName a = new ATypeName();

在ATypeName里,类主体只由一条注释构成(星号和斜杠以及其中的内容,本章后面还会详细讲述),所以并不能对它做太多的事情。事实上,除非为其定义了某些方法,否则根本不能指示它做任何事情。

2.4.1 字段和方法

定义一个类时(我们在Java里的全部工作就是定义类、制作那些类的对象以及将消息发给那些对象),可在自己的类里设置两种类型的元素:数据成员(有时也叫“字段”)以及成员函数(通常叫“方法”)。其中,数据成员是一种对象(通过它的句柄与其通信),可以为任何类型。它也可以是主类型(并不是句柄)之一。如果是指向对象的一个句柄,则必须初始化那个句柄,用一种名为“构建器”(第4章会对此详述)的特殊函数将其与一个实际对象连接起来(就象早先看到的那样,使用new关键字)。但若是一种主类型,则可在类定义位置直接初始化(正如后面会看到的那样,句柄亦可在定义位置初始化)。

每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。下面是定义了一些数据成员的类示例:

class DataOnly {

int i;

float f;

boolean b;

}

这个类并没有做任何实质性的事情,但我们可创建一个对象:

DataOnly d = new DataOnly();

可将值赋给数据成员,但首先必须知道如何引用一个对象的成员。为达到引用对象成员的目的,首先要写上对象句柄的名字,再跟随一个点号(句点),再跟随对象内部成员的名字。即“对象句柄.成员”。例如:

d.i = 47;

d.f = 1.1f;

d.b = false;

一个对象也可能包含了另一个对象,而另一个对象里则包含了我们想修改的数据。对于这个问题,只需保持“连接句点”即可。例如:

myPlane.leftTank.capacity = 100;

除容纳数据之外,DataOnly类再也不能做更多的事情,因为它没有成员函数(方法)。为正确理解工作原理,首先必须知道“自变量”和“返回值”的概念。我们马上就会详加解释。

1. 主成员的默认值

若某个主数据类型属于一个类成员,那么即使不明确(显式)进行初始化,也可以保证它们获得一个默认值。

主类型 默认值

Boolean false

Char '\u0000'(null)

byte (byte)0

short (short)0

int 0

long 0L

float 0.0f

double 0.0d

一旦将变量作为类成员使用,就要特别注意由Java分配的默认值。这样做可保证主类型的成员变量肯定得到了初始化(C++不具备这一功能),可有效遏止多种相关的编程错误。

然而,这种保证却并不适用于“局部”变量——那些变量并非一个类的字段。所以,假若在一个函数定义中写入下述代码:

int x;

那么x会得到一些随机值(这与C和C++是一样的),不会自动初始化成零。我们责任是在正式使用x前分配一个适当的值。如果忘记,就会得到一条编译期错误,告诉我们变量可能尚未初始化。这种处理正是Java优于C++的表现之一。许多C++编译器会对变量未初始化发出警告,但在Java里却是错误。

2.5 方法、自变量和返回值

迄今为止,我们一直用“函数”(Function)这个词指代一个已命名的子例程。但在Java里,更常用的一个词却是“方法”(Method),代表“完成某事的途径”。尽管它们表达的实际是同一个意思,但从现在开始,本书将一直使用“方法”,而不是“函数”。

Java的“方法”决定了一个对象能够接收的消息。通过本节的学习,大家会知道方法的定义有多么简单!

方法的基本组成部分包括名字、自变量、返回类型以及主体。下面便是它最基本的形式:

返回类型 方法名( /* 自变量列表*/ ) {/* 方法主体 */}

返回类型是指调用方法之后返回的数值类型。显然,方法名的作用是对具体的方法进行标识和引用。自变量列表列出了想传递给方法的信息类型和名称。

Java的方法只能作为类的一部分创建。只能针对某个对象调用一个方法(注释③),而且那个对象必须能够执行那个方法调用。若试图为一个对象调用错误的方法,就会在编译期得到一条出错消息。为一个对象调用方法时,需要先列出对象的名字,在后面跟上一个句点,再跟上方法名以及它的参数列表。亦即“对象名.方法名(自变量1,自变量2,自变量3...)。举个例子来说,假设我们有一个方法名叫f(),它没有自变量,返回的是类型为int的一个值。那么,假设有一个名为a的对象,可为其调用方法f(),则代码如下:

int x = a.f();

返回值的类型必须兼容x的类型。

象这样调用一个方法的行动通常叫作“向对象发送一条消息”。在上面的例子中,消息是f(),而对象是a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。

③:正如马上就要学到的那样,“静态”方法可针对类调用,毋需一个对象。

2.5.1 自变量列表

自变量列表规定了我们传送给方法的是什么信息。正如大家或许已猜到的那样,这些信息——如同Java内其他任何东西——采用的都是对象的形式。因此,我们必须在自变量列表里指定要传递的对象类型,以及每个对象的名字。正如在Java其他地方处理对象时一样,我们实际传递的是“句柄”(注释④)。然而,句柄的类型必须正确。倘若希望自变量是一个“字串”,那么传递的必须是一个字串。

④:对于前面提及的“特殊”数据类型boolean,char,byte,short,int,long,,float以及double来说是一个例外。但在传递对象时,通常都是指传递指向对象的句柄。

下面让我们考虑将一个字串作为自变量使用的方法。下面列出的是定义代码,必须将它置于一个类定义里,否则无法编译:

int storage(String s) {

return s.length() * 2;

}

这个方法告诉我们需要多少字节才能容纳一个特定字串里的信息(字串里的每个字符都是16位,或者说2个字节、长整数,以便提供对Unicode字符的支持)。自变量的类型为String,而且叫作s。一旦将s传递给方法,就可将它当作其他对象一样处理(可向其发送消息)。在这里,我们调用的是length()方法,它是String的方法之一。该方法返回的是一个字串里的字符数。

通过上面的例子,也可以了解return关键字的运用。它主要做两件事情。首先,它意味着“离开方法,我已完工了”。其次,假设方法生成了一个值,则那个值紧接在return语句的后面。在这种情况下,返回值是通过计算表达式“s.length()*2”而产生的。

可按自己的愿望返回任意类型,但倘若不想返回任何东西,就可指示方法返回void(空)。下面列出一些例子。

boolean flag() { return true; }

float naturalLogBase() { return 2.718; }

void nothing() { return; }

void nothing2() {}

若返回类型为void,则return关键字唯一的作用就是退出方法。所以一旦抵达方法末尾,该关键字便不需要了。可在任何地方从一个方法返回。但假设已指定了一种非void的返回类型,那么无论从何地返回,编译器都会确保我们返回的是正确的类型。

到此为止,大家或许已得到了这样的一个印象:一个程序只是一系列对象的集合,它们的方法将其他对象作为自己的自变量使用,而且将消息发给那些对象。这种说法大体正确,但通过以后的学习,大家还会知道如何在一个方法里作出决策,做一些更细致的基层工作。至于这一章,只需理解消息传送就足le

java什么叫类属性 实例属性 以及区别

一个是类的方法(也叫动态属性)和属性(静态属性),通过类名来访问

一个是对象的方法和属性,需要通过一个实例来访问。

静态属性程序一加载时 就初始化 存放在栈中

实例属性 需要实例化后 才加载 存放在堆中

java对象的作用

一切都是对象

“尽管以C++为基础,但Java是一种更纯粹的面向对象程序设计语言”。

无论C++还是Java都属于杂合语言。但在Java中,设计者觉得这种杂合并不象在C++里那么重要。杂合语言允许采用多种编程风格;之所以说C++是一种杂合语言,是因为它支持与C语言的向后兼容能力。由于C++是C的一个超集,所以包含的许多特性都是后者不具备的,这些特性使C++在某些地方显得过于复杂。

Java语言首先便假定了我们只希望进行面向对象的程序设计。也就是说,正式用它设计之前,必须先将自己的思想转入一个面向对象的世界(除非早已习惯了这个世界的思维方式)。只有做好这个准备工作,与其他OOP语言相比,才能体会到Java的易学易用。在本章,我们将探讨Java程序的基本组件,并体会为什么说Java乃至Java程序内的一切都是对象。

2.1 用句柄操纵对象

每种编程语言都有自己的数据处理方式。有些时候,程序员必须时刻留意准备处理的是什么类型。您曾利用一些特殊语法直接操作过对象,或处理过一些间接表示的对象吗(C或C++里的指针)?

所有这些在Java里都得到了简化,任何东西都可看作对象。因此,我们可采用一种统一的语法,任何地方均可照搬不误。但要注意,尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle)。在其他Java参考书里,还可看到有的人将其称作一个“引用”,甚至一个“指针”。可将这一情形想象成用遥控板(句柄)操纵电视机(对象)。只要握住这个遥控板,就相当于掌握了与电视机连接的通道。但一旦需要“换频道”或者“关小声音”,我们实际操纵的是遥控板(句柄),再由遥控板自己操纵电视机(对象)。如果要在房间里四处走走,并想保持对电视机的控制,那么手上拿着的是遥控板,而非电视机。

此外,即使没有电视机,遥控板亦可独立存在。也就是说,只是由于拥有一个句柄,并不表示必须有一个对象同它连接。所以如果想容纳一个词或句子,可创建一个String句柄:

String s;

但这里创建的只是句柄,并不是对象。若此时向s发送一条消息,就会获得一个错误(运行期)。这是由于s实际并未与任何东西连接(即“没有电视机”)。因此,一种更安全的做法是:创建一个句柄时,记住无论如何都进行初始化:

String s = "asdf";

然而,这里采用的是一种特殊类型:字串可用加引号的文字初始化。通常,必须为对象使用一种更通用的初始化类型。

2.2 所有对象都必须创建

创建句柄时,我们希望它同一个新对象连接。通常用new关键字达到这一目的。new的意思是:“把我变成这些对象的一种新类型”。所以在上面的例子中,可以说:

String s = new String("asdf");

它不仅指出“将我变成一个新字串”,也通过提供一个初始字串,指出了“如何生成这个新字串”。

当然,字串(String)并非唯一的类型。Java配套提供了数量众多的现成类型。对我们来讲,最重要的就是记住能自行创建类型。事实上,这应是Java程序设计的一项基本操作,是继续本书后余部分学习的基础。

2.2.1 保存到什么地方

程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的是内存的分配。有六个地方都可以保存数据:

(1) 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。

(2) 堆栈。驻留于常规RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,Java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java数据要保存在堆栈里——特别是对象句柄,但Java对象并不放到其中。

(3) 堆。一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!

(4) 静态存储。这儿的“静态”(Static)是指“位于固定位置”(尽管也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static关键字指出一个对象的特定元素是静态的。但Java对象本身永远都不会置入静态存储空间。

(5) 常数存储。常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。

(6) 非RAM存储。若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。Java 1.1提供了对Lightweight persistence的支持。未来的版本甚至可能提供更完整的方案。

2.2.2 特殊情况:主要类型

有一系列类需特别对待;可将它们想象成“基本”、“主要”或者“主”(Primitive)类型,进行程序设计时要频繁用到它们。之所以要特别对待,是由于用new创建对象(特别是小的、简单的变量)并不是非常有效,因为new将对象置于“堆”里。对于这些类型,Java采纳了与C和C++相同的方法。也就是说,不是用new创建变量,而是创建一个并非句柄的“自动”变量。这个变量容纳了具体的值,并置于堆栈中,能够更高效地存取。

Java决定了每种主要类型的大小。就象在大多数语言里那样,这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。

主类型

大小

最小值

最大值

封装器类型

boolean

1-bit

Boolean

char

16-bit

Unicode 0

Unicode 216- 1

Character

byte

8-bit

-128

+127

Byte[11]

short

16-bit

-215

+215 – 1

Short1

int

32-bit

-231

+231 – 1

Integer

long

64-bit

-263

+263 – 1

Long

float

32-bit

IEEE754

IEEE754

Float

double

64-bit

IEEE754

IEEE754

Double

void

Void1

①:到Java 1.1才有,1.0版没有。

数值类型全都是有符号(正负号)的,所以不必费劲寻找没有符号的类型。

主数据类型也拥有自己的“封装器”(wrapper)类。这意味着假如想让堆内一个非主要对象表示那个主类型,就要使用对应的封装器。例如:

char c = 'x';

Character C = new Character('c');

也可以直接使用:

Character C = new Character('x');

这样做的原因将在以后的章节里解释。

1. 高精度数字

Java 1.1增加了两个类,用于进行高精度的计算:BigInteger和BigDecimal。尽管它们大致可以划分为“封装器”类型,但两者都没有对应的“主类型”。

这两个类都有自己特殊的“方法”,对应于我们针对主类型执行的操作。也就是说,能对int或float做的事情,对BigInteger和BigDecimal一样可以做。只是必须使用方法调用,不能使用运算符。此外,由于牵涉更多,所以运算速度会慢一些。我们牺牲了速度,但换来了精度。

BigInteger支持任意精度的整数。也就是说,我们可精确表示任意大小的整数值,同时在运算过程中不会丢失任何信息。

BigDecimal支持任意精度的定点数字。例如,可用它进行精确的币值计算。

至于调用这两个类时可选用的构建器和方法,请自行参考联机帮助文档。

2.2.3 Java的数组

几乎所有程序设计语言都支持数组。在C和C++里使用数组是非常危险的,因为那些数组只是内存块。若程序访问自己内存块以外的数组,或者在初始化之前使用内存(属于常规编程错误),会产生不可预测的后果(注释②)。

②:在C++里,应尽量不要使用数组,换用标准模板库(Standard TemplateLibrary)里更安全的容器。

Java的一项主要设计目标就是安全性。所以在C和C++里困扰程序员的许多问题都未在Java里重复。一个Java可以保证被初始化,而且不可在它的范围之外访问。由于系统自动进行范围检查,所以必然要付出一些代价:针对每个数组,以及在运行期间对索引的校验,都会造成少量的内存开销。但由此换回的是更高的安全性,以及更高的工作效率。为此付出少许代价是值得的。

创建对象数组时,实际创建的是一个句柄数组。而且每个句柄都会自动初始化成一个特殊值,并带有自己的关键字:null(空)。一旦Java看到null,就知道该句柄并未指向一个对象。正式使用前,必须为每个句柄都分配一个对象。若试图使用依然为null的一个句柄,就会在运行期报告问题。因此,典型的数组错误在Java里就得到了避免。

也可以创建主类型数组。同样地,编译器能够担保对它的初始化,因为会将那个数组的内存划分成零。

数组问题将在以后的章节里详细讨论。

2.3 绝对不要清除对象

在大多数程序设计语言中,变量的“存在时间”(Lifetime)一直是程序员需要着重考虑的问题。变量应持续多长的时间?如果想清除它,那么何时进行?在变量存在时间上纠缠不清会造成大量的程序错误。在下面的小节里,将阐示Java如何帮助我们完成所有清除工作,从而极大了简化了这个问题。

2.3.1 作用域

大多数程序设计语言都提供了“作用域”(Scope)的概念。对于在作用域里定义的名字,作用域同时决定了它的“可见性”以及“存在时间”。在C,C++和Java里,作用域是由花括号的位置决定的。参考下面这个例子:

{

int x = 12;

/* only x available */

{

int q = 96;

/* both x q available */

}

/* only x available */

/* q “out of scope” */

}

作为在作用域里定义的一个变量,它只有在那个作用域结束之前才可使用。

在上面的例子中,缩进排版使Java代码更易辨读。由于Java是一种形式自由的语言,所以额外的空格、制表位以及回车都不会对结果程序造成影响。

注意尽管在C和C++里是合法的,但在Java里不能象下面这样书写代码:

{

int x = 12;

{

int x = 96; /* illegal */

}

}

编译器会认为变量x已被定义。所以C和C++能将一个变量“隐藏”在一个更大的作用域里。但这种做法在Java里是不允许的,因为Java的设计者认为这样做使程序产生了混淆。

2.3.2 对象的作用域

Java对象不具备与主类型一样的存在时间。用new关键字创建一个Java对象的时候,它会超出作用域的范围之外。所以假若使用下面这段代码:

{

String s = new String("a string");

} /* 作用域的终点 */

那么句柄s会在作用域的终点处消失。然而,s指向的String对象依然占据着内存空间。在上面这段代码里,我们没有办法访问对象,因为指向它的唯一一个句柄已超出了作用域的边界。在后面的章节里,大家还会继续学习如何在程序运行期间传递和复制对象句柄。

这样造成的结果便是:对于用new创建的对象,只要我们愿意,它们就会一直保留下去。这个编程问题在C和C++里特别突出。看来在C++里遇到的麻烦最大:由于不能从语言获得任何帮助,所以在需要对象的时候,根本无法确定它们是否可用。而且更麻烦的是,在C++里,一旦工作完成,必须保证将对象清除。

这样便带来了一个有趣的问题。假如Java让对象依然故我,怎样才能防止它们大量充斥内存,并最终造成程序的“凝固”呢。在C++里,这个问题最令程序员头痛。但Java以后,情况却发生了改观。Java有一个特别的“垃圾收集器”,它会查找用new创建的所有对象,并辨别其中哪些不再被引用。随后,它会自动释放由那些闲置对象占据的内存,以便能由新对象使用。这意味着我们根本不必操心内存的回收问题。只需简单地创建对象,一旦不再需要它们,它们就会自动离去。这样做可防止在C++里很常见的一个编程问题:由于程序员忘记释放内存造成的“内存溢出”。

2.4 新建数据类型:类

如果说一切东西都是对象,那么用什么决定一个“类”(Class)的外观与行为呢?换句话说,是什么建立起了一个对象的“类型”(Type)呢?大家可能猜想有一个名为“type”的关键字。但从历史看来,大多数面向对象的语言都用关键字“class”表达这样一个意思:“我准备告诉你对象一种新类型的外观”。class关键字太常用了,以至于本书许多地方并没有用粗体字或双引号加以强调。在这个关键字的后面,应该跟随新数据类型的名称。例如:

class ATypeName {/*类主体置于这里}

这样就引入了一种新类型,接下来便可用new创建这种类型的一个新对象:

ATypeName a = new ATypeName();

在ATypeName里,类主体只由一条注释构成(星号和斜杠以及其中的内容,本章后面还会详细讲述),所以并不能对它做太多的事情。事实上,除非为其定义了某些方法,否则根本不能指示它做任何事情。

2.4.1 字段和方法

定义一个类时(我们在Java里的全部工作就是定义类、制作那些类的对象以及将消息发给那些对象),可在自己的类里设置两种类型的元素:数据成员(有时也叫“字段”)以及成员函数(通常叫“方法”)。其中,数据成员是一种对象(通过它的句柄与其通信),可以为任何类型。它也可以是主类型(并不是句柄)之一。如果是指向对象的一个句柄,则必须初始化那个句柄,用一种名为“构建器”(第4章会对此详述)的特殊函数将其与一个实际对象连接起来(就象早先看到的那样,使用new关键字)。但若是一种主类型,则可在类定义位置直接初始化(正如后面会看到的那样,句柄亦可在定义位置初始化)。

每个对象都为自己的数据成员保有存储空间;数据成员不会在对象之间共享。下面是定义了一些数据成员的类示例:

class DataOnly {

int i;

float f;

boolean b;

}

这个类并没有做任何实质性的事情,但我们可创建一个对象:

DataOnly d = new DataOnly();

可将值赋给数据成员,但首先必须知道如何引用一个对象的成员。为达到引用对象成员的目的,首先要写上对象句柄的名字,再跟随一个点号(句点),再跟随对象内部成员的名字。即“对象句柄.成员”。例如:

d.i = 47;

d.f = 1.1f;

d.b = false;

一个对象也可能包含了另一个对象,而另一个对象里则包含了我们想修改的数据。对于这个问题,只需保持“连接句点”即可。例如:

myPlane.leftTank.capacity = 100;

除容纳数据之外,DataOnly类再也不能做更多的事情,因为它没有成员函数(方法)。为正确理解工作原理,首先必须知道“自变量”和“返回值”的概念。我们马上就会详加解释。

1. 主成员的默认值

若某个主数据类型属于一个类成员,那么即使不明确(显式)进行初始化,也可以保证它们获得一个默认值。

主类型 默认值

Boolean false

Char '\u0000'(null)

byte (byte)0

short (short)0

int 0

long 0L

float 0.0f

double 0.0d

一旦将变量作为类成员使用,就要特别注意由Java分配的默认值。这样做可保证主类型的成员变量肯定得到了初始化(C++不具备这一功能),可有效遏止多种相关的编程错误。

然而,这种保证却并不适用于“局部”变量——那些变量并非一个类的字段。所以,假若在一个函数定义中写入下述代码:

int x;

那么x会得到一些随机值(这与C和C++是一样的),不会自动初始化成零。我们责任是在正式使用x前分配一个适当的值。如果忘记,就会得到一条编译期错误,告诉我们变量可能尚未初始化。这种处理正是Java优于C++的表现之一。许多C++编译器会对变量未初始化发出警告,但在Java里却是错误。

2.5 方法、自变量和返回值

迄今为止,我们一直用“函数”(Function)这个词指代一个已命名的子例程。但在Java里,更常用的一个词却是“方法”(Method),代表“完成某事的途径”。尽管它们表达的实际是同一个意思,但从现在开始,本书将一直使用“方法”,而不是“函数”。

Java的“方法”决定了一个对象能够接收的消息。通过本节的学习,大家会知道方法的定义有多么简单!

方法的基本组成部分包括名字、自变量、返回类型以及主体。下面便是它最基本的形式:

返回类型 方法名( /* 自变量列表*/ ) {/* 方法主体 */}

返回类型是指调用方法之后返回的数值类型。显然,方法名的作用是对具体的方法进行标识和引用。自变量列表列出了想传递给方法的信息类型和名称。

Java的方法只能作为类的一部分创建。只能针对某个对象调用一个方法(注释③),而且那个对象必须能够执行那个方法调用。若试图为一个对象调用错误的方法,就会在编译期得到一条出错消息。为一个对象调用方法时,需要先列出对象的名字,在后面跟上一个句点,再跟上方法名以及它的参数列表。亦即“对象名.方法名(自变量1,自变量2,自变量3...)。举个例子来说,假设我们有一个方法名叫f(),它没有自变量,返回的是类型为int的一个值。那么,假设有一个名为a的对象,可为其调用方法f(),则代码如下:

int x = a.f();

返回值的类型必须兼容x的类型。

象这样调用一个方法的行动通常叫作“向对象发送一条消息”。在上面的例子中,消息是f(),而对象是a。面向对象的程序设计通常简单地归纳为“向对象发送消息”。

③:正如马上就要学到的那样,“静态”方法可针对类调用,毋需一个对象。

2.5.1 自变量列表

自变量列表规定了我们传送给方法的是什么信息。正如大家或许已猜到的那样,这些信息——如同Java内其他任何东西——采用的都是对象的形式。因此,我们必须在自变量列表里指定要传递的对象类型,以及每个对象的名字。正如在Java其他地方处理对象时一样,我们实际传递的是“句柄”(注释④)。然而,句柄的类型必须正确。倘若希望自变量是一个“字串”,那么传递的必须是一个字串。

④:对于前面提及的“特殊”数据类型boolean,char,byte,short,int,long,,float以及double来说是一个例外。但在传递对象时,通常都是指传递指向对象的句柄。

下面让我们考虑将一个字串作为自变量使用的方法。下面列出的是定义代码,必须将它置于一个类定义里,否则无法编译:

int storage(String s) {

return s.length() * 2;

}

这个方法告诉我们需要多少字节才能容纳一个特定字串里的信息(字串里的每个字符都是16位,或者说2个字节、长整数,以便提供对Unicode字符的支持)。自变量的类型为String,而且叫作s。一旦将s传递给方法,就可将它当作其他对象一样处理(可向其发送消息)。在这里,我们调用的是length()方法,它是String的方法之一。该方法返回的是一个字串里的字符数。

通过上面的例子,也可以了解return关键字的运用。它主要做两件事情。首先,它意味着“离开方法,我已完工了”。其次,假设方法生成了一个值,则那个值紧接在return语句的后面。在这种情况下,返回值是通过计算表达式“s.length()*2”而产生的。

可按自己的愿望返回任意类型,但倘若不想返回任何东西,就可指示方法返回void(空)。下面列出一些例子。

boolean flag() { return true; }

float naturalLogBase() { return 2.718; }

void nothing() { return; }

void nothing2() {}

若返回类型为void,则return关键字唯一的作用就是退出方法。所以一旦抵达方法末尾,该关键字便不需要了。可在任何地方从一个方法返回。但假设已指定了一种非void的返回类型,那么无论从何地返回,编译器都会确保我们返回的是正确的类型。

到此为止,大家或许已得到了这样的一个印象:一个程序只是一系列对象的集合,它们的方法将其他对象作为自己的自变量使用,而且将消息发给那些对象。这种说法大体正确,但通过以后的学习,大家还会知道如何在一个方法里作出决策,做一些更细致的基层工作。至于这一章,只需理解消息传送就足le

private在Java中是什么意思?

Private ,编程语句在模块级别中使用,用于声明私有变量及分配存储空间。

private

读法:英 [ˈpraɪvət]  美 [ˈpraɪvət]

1、adj. 私人的,私有的;私立的;私营的

2、adj. 私下的,不公开的,秘密的

3、adj. (场所)清静的;(人)不愿吐露心思的,内向的

4、adj. 无官职的

5、n. 列兵;二等兵

短语

1、Private Life 个人生活 ; 私生活 ; 私人生活 ; 香港小姐写真

2、Private placement 私募 ; 私募配售 ; 私募融资

3、Private Secretary 私人秘书 ; 私家秘书 ; 私家文秘 ; 小我私家秘书

4、private cloud 私有云 ; 私密之云

5、private key 私钥 ; 私密金钥 ; 私有密钥 ; 私人密钥

扩展资料

private近义词:chamber

读法:英 [ˈtʃeɪmbə(r)]  美 [ˈtʃeɪmbər] 

1、n. (身体或器官内的)室,膛;房间;会所

2、adj. 室内的;私人的,秘密的

3、vt. 把…关在室内;装填(弹药等)

短语

1、chamber pot 马桶 ; 便壶 ; 夜壶 ; 便桶

2、magma chamber [地物] 岩浆房 ; 岩浆储源 ; 岩浆库 ; 熔岩领地

3、air chamber 气室 ; [建] 空气室 ; 气腔 ; 空气包

4、echo chamber 回响室 ; 回音室 ; [声] 回声室 ; 回声室效应

5、cooling chamber 冷冻箱 ; 冷却室 ; 冷却腔

slifejava的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于、slifejava的信息别忘了在本站进行查找喔。

The End

发布于:2022-12-26,除非注明,否则均为首码项目网原创文章,转载请注明出处。