没有合适的资源?快使用搜索试试~ 我知道了~
首页精通Java编程基础:从入门到精通的全面指南
"Apress.Beginning.Java.8.Fundamentals"
本书是针对初学者的Java 8编程基础教程,作者在1997年首次接触Java,并在之后的项目中深入学习和使用。作者发现市面上的书籍对Java的涵盖不够全面,于是决定编写一本详尽的Java教程,旨在帮助读者全面理解和掌握Java编程语言,同时也适用于准备Java程序员认证考试的人群。
书中的内容丰富详实,原计划在700至800页内涵盖所有关键主题,但随着写作深入,发现要详细讲解Java的所有要点,这个篇幅远远不够。因此,作者选择保留所有他认为对于Java开发者至关重要的细节,使得本书内容更为丰富。作者的目标是使这本书成为一本全面的、一站式的学习Java编程语言的参考书籍,避免读者需要阅读多本相关书籍。
书中遵循从基础知识入手的教学方法,每个主题都会先介绍基础概念,然后逐步深入。为了便于理解,作者尽可能地将编程实践与日常生活活动相联系,并且大量使用图表来辅助解释,使读者更容易理解和记忆。考虑到没有或只有少量编程经验的开发者,书中提供了超过240个完整的Java程序示例,可以直接编译运行,帮助读者实践和巩固所学知识。
作者进行了大量的研究工作,主要参考了Java语言规范、相关的白皮书、文章以及Java规范请求(JSRs)。有时为了深入理解一个主题,作者会花费几个月时间进行研究。此外,他还通过实际操作Java程序来测试和完善书中的内容。
书的目录包括了从编程概念到高级特性的广泛话题,如编程概念、编写Java程序、数据类型、运算符、语句、类和对象、对象和Object类、包装类、异常处理、断言、字符串、日期和时间、数据格式化、正则表达式、数组、继承、接口和枚举类型。还有两个附录分别关于字符编码和文档注释,为读者提供额外的信息和指导。
"Apress.Beginning.Java.8.Fundamentals"是一本注重实践、全面覆盖Java 8基础知识的教材,适合希望系统学习Java编程语言的新手和准备认证考试的开发者。
CHAPTER 1 ■ PROGRAMMING CONCEPTS
9
Suppose you want to represent real-world people in your program. You will create a Person class and its instances
will represent people in your program. The Person class can be defined as shown in Listing 1-1. This example uses the
syntax of the Java programming language. You do not need to understand the syntax used in the programs that you are
writing at this point; I will discuss the syntax to define classes and create objects in subsequent chapters.
Listing 1-1. The Definition of a Person Class Whose Instances Represent Real-World Persons in a Program
package com.jdojo.concepts;
public class Person {
private String name;
private String gender;
public Person(String initialName, String initialGender) {
name = initialName;
gender = initialGender;
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public String getGender() {
return gender;
}
}
The Person class includes three things:
Two instance variables: • name and gender.
One constructor: • Person(String initialName, String initialGender)
Three methods: • getName(), setName(String newName), and getGender()
Instance variables store internal data for an object. The value of each instance variable represents the value of a
corresponding property of the object. Each instance of the Person class will have a copy of name and gender data. The
values of all properties of an object at a point in time (stored in instance variables) collectively define the state of the
object at that time. In the real world, a person possesses many properties, for example, name, gender, height, weight,
hair color, addresses, phone numbers, etc. However, when you model the real-world person using a class, you include
only those properties of the person that are relevant to the system being modeled. For this current demonstration, let’s
model only two properties, name and gender, of a real-world person as two instance variables in the Person class.
A class contains the definition (or blueprint) of objects. There needs to be a way to construct (to create or to
instantiate) objects of a class. An object also needs to have the initial values for its properties that will determine its
initial state at the time of its creation. A constructor of a class is used to create an object of that class. A class can have
many constructors to facilitate the creation of its objects with different initial states. The Person class provides one
constructor, which lets you create its object by specifying the initial values for name and gender. The following snippet
of code creates two objects of the Person class:
Person john = new Person("John Jacobs", "Male");
Person donna = new Person("Donna Duncan", "Female");
CHAPTER 1 ■ PROGRAMMING CONCEPTS
10
The first object is called john with John Jacobs and Male as the initial values for its name and gender properties,
respectively. The second object is called donna with Donna Duncan and Female as the initial values for its name and
gender properties, respectively.
Methods of a class represent behaviors of its objects. For example, in the real world, a person has a name and his
ability to respond when he is asked for his name is one of his behaviors. Objects of the Person class have abilities to
respond to three different messages: getName, setName, and getGender. The ability of an object to respond to a message
is implemented using methods. You can send a message, say getName, to a Person object and it will respond by returning
its name. It is the same as asking “What is your name?” and having the person respond by telling you his name.
String johnName = john.getName(); // Send getName message to john
String donnaName = donna.getName(); // Send getName message to donna
The setName message to the Person object asks him to change his current name to a new name. The following
snippet of code changes the name of the donna object from Donna Duncan to Donna Jacobs:
donna.setName("Donna Jacobs");
If you send the getName message to donna object at this point, it will return Donna Jacobs and not Donna Duncan.
You may notice that your Person objects do not have the ability to respond to a message such as - setGender.
The gender of Person object is set when the object is created and it cannot be changed afterwards. However, you
can query the gender of a Person object by sending getGender message to it. What messages an object may (or may
not) respond to is decided at design-time based on the need of the system being modeled. In the case of the Person
objects, we decided that they would not have the ability to respond to the setGender message by not including a
setGender(String newGender) method in the Person class.
Figure 1-3 shows the state and interface of the Person object called john.
Figure 1-3. The state and the interface for a Person object
The object-oriented paradigm is a very powerful paradigm for modeling real-world phenomena in a computational
model. We are used to working with objects all around us in our daily life. The object-oriented paradigm is natural
and intuitive as it lets you think in terms of objects. However, it does not give you the ability to think in terms of objects
correctly. Sometimes the solution to a problem does not fall into the domain of an object-oriented paradigm. In such
cases, you need to use the paradigm that suits the problem domain the most. The object-oriented paradigm has a
learning curve. It is much more than just creating and using objects in your program. Abstraction, encapsulation,
polymorphism, and inheritance are some of the important features of the object-oriented paradigm. You must
understand and be able to use these features to take full advantage of the object-oriented paradigm. I will discuss these
features of the object-oriented paradigm in the sections to follow. In subsequent chapters, I will discuss these features
and how to implement them in a program in detail.
CHAPTER 1 ■ PROGRAMMING CONCEPTS
11
To name a few, C++, Java and C# (pronounced as C sharp) are programming languages that support the
object-oriented paradigm. Note that a programming language itself is not object-oriented. It is the paradigm that is
object-oriented. A programming language may or may not have features to support the object-oriented paradigm.
What Is Java?
Java is a general purpose programming language. It has features to support programming based on the
object-oriented, procedural, and functional paradigms. You often read a phrase like “Java is an object-oriented
programming language.” What is meant is that the Java language has features that support the object-oriented paradigm.
A programming language is not object-oriented. It is the paradigm that is object-oriented, and a programming
language may have features that make it easy to implement the object-oriented paradigm. Sometimes programmers
have misconceptions that all programs written in Java are always object-oriented. Java also has features that support
the procedural and functional paradigms. You can write a program in Java that is a 100% procedural program without
an iota of object-orientedness in it.
The initial version of the Java platform was released by Sun Microsystems (part of Oracle Corporation since
January 2010) in 1995. Development of the Java programming language was started in 1991. Initially, the language was
called Oak and it was meant to be used in set-top boxes for televisions.
Soon after its release, Java became a very popular programming language. One of the most important features
for its popularity was its “write once, run anywhere” (WORA) feature. This feature lets you write a Java program
once and run it on any platform. For example, you can write and compile a Java program on UNIX and run it on
Microsoft Windows, Macintosh, or UNIX machine without any modifications to the source code. WORA is achieved
by compiling a Java program into an intermediate language called bytecode. The format of bytecode is platform-
independent. A virtual machine, called the Java Virtual Machine (JVM), is used to run the bytecode on each platform.
Note that JVM is a program implemented in software. It is not a physical machine and this is the reason it is called a
“virtual” machine. The job of a JVM is to transform the bytecode into executable code according to the platform it is
running on. This feature makes Java programs platform-independent. That is, the same Java program can be run on
multiple platforms without any modifications.
The following are a few characteristics behind Java’s popularity and acceptance in the software industry:
Simplicity•
Wide variety of usage environments•
Robustness•
Simplicity may be a subjective word in this context. C++ was the popular and powerful programming language
widely used in the software industry at the time Java was released. If you were a C++ programmer, Java would provide
simplicity for you in its learning and use over the C++ experience you had. Java retained most of the syntax of C/C++,
which was helpful for C/C++ programmers trying to learn this new language. Even better, it excluded some of the most
confusing and hard-to-use-correctly features (though powerful) of C++. For example, Java does not have pointers and
multiple inheritance, which are present in C++.
If you are learning Java as your first programming language, whether it is a simple language to learn may not be
true for you. This is the reason why I said that the simplicity of Java or any programming language is very subjective.
The Java language and its libraries (a set of packages containing Java classes) have been growing ever since its first
release. You will need to put in some serious effort in order to become a serious Java developer.
Java can be used to develop programs that can be used in different environments. You can write programs in
Java that can be used in a client-server environment. The most popular use of Java programs in its early days was
to develop applets. An applet is a Java program that is embedded in a web page, which uses the HyperText Markup
Language (HTML), and is displayed in a web browser such as Microsoft Internet Explorer, Google Chrome, etc. An
applet’s code is stored on a web server, downloaded to the client machine when the HTML page containing the
reference to the applet is loaded by the browser, and run on the client machine. Java includes features that make
it easy to develop distributed applications. A distributed application consists of programs running on different
CHAPTER 1 ■ PROGRAMMING CONCEPTS
12
machines connected through a network. Java has features that make it easy to develop concurrent applications.
A concurrent application has multiple interacting threads of execution running in parallel. I will discuss these features
of the Java platform in detail in subsequent chapters in this book.
Robustness of a program refers to its ability to handle unexpected situations reasonably. The unexpected
situation in a program is also known as an error. Java provides robustness by providing many features for error
checking at different points during a program’s lifetime. The following are three different types of errors that may
occur in a Java program:
Compile-time error•
Runtime error•
Logic error•
Compile-time errors are also known as syntax errors. They are caused by incorrect use of the Java language
syntax. Compile-time errors are detected by the Java compiler. A program with a compile-time error does not compile
into bytecode until the errors are corrected. Missing a semicolon at the end of a statement, assigning a decimal value
such as 10.23 to a variable of integer type, etc. are examples of compile-time errors.
Runtime errors occur when a Java program is run. This kind of error is not detected by the compiler because
a compiler does not have all of the runtime information available to it. Java is a strongly typed languages and it has
a robust type checking at compile-time as well as runtime. Java provides a neat exception handling mechanism to
handle runtime errors. When a runtime error occurs in a Java program, the JVM throws an exception, which the
program may catch and deal with. For example, dividing an integer by zero (e.g. 17/0) generates a runtime error. Java
avoids critical runtime errors, such as memory overrun and memory leaks, by providing a built-in mechanism for
automatic memory allocation and deallocation. The feature of automatic memory deallocation is known as garbage
collection.
Logic errors are the most critical errors in a program, and they are hard to find. They are introduced by the
programmer by implementing the functional requirement incorrectly. This kind of error cannot be detected by a Java
compiler or Java runtime. They are detected by application testers or users when they compare the actual behavior of
a program with its expected behavior. Sometimes a few logic errors can sneak into the production environment and
they go unnoticed even after the application is decommissioned.
An error in a program is known as a bug. The process of finding and fixing bugs in a program is known as
debugging. All modern integrated development environments (IDEs) such as NetBeans, Eclipse, JDeveloper, JBuilder,
etc, provide programmers with a tool called a debugger, which lets them run the program step-by-step and inspect the
program’s state at every step to detect the bug. Debugging is a reality of programmer’s daily activities. If you want to
be a good programmer, you must learn and be good at using the debuggers that come with the development tools that
you use to develop your Java programs.
The Object-Oriented Paradigm and Java
The object-oriented paradigm supports four major principles: abstraction, encapsulation, inheritance, and
polymorphism. They are also known as four pillars of the object-oriented paradigm. Abstraction is the process of
exposing the essential details of an entity, while ignoring the irrelevant details, to reduce the complexity for the users.
Encapsulation is the process of bundling data and operations on the data together in an entity. Inheritance is used to
derive a new type from an existing type, thereby establishing a parent-child relationship. Polymorphism lets an entity
take on different meanings in different contexts. The four principles are discussed in detail in the sections to follow.
CHAPTER 1 ■ PROGRAMMING CONCEPTS
13
Abstraction
A program provides solutions to a real-world problem. The size of the program may range from a few lines to a few
million lines. It may be written as a monolithic structure running from the first line to the millionth line in one place.
A monolithic program becomes harder to write, understand, and maintain if its size is over 25 to 50 lines. For easier
maintenance, a big monolithic program must be decomposed into smaller subprograms. The subprograms are then
assembled together to solve the original problem. Care must be taken when a program is being decomposed. All
subprograms must be simple and small enough to be understood by themselves, and when assembled together, they
must solve the original problem.
Let’s consider the following requirement for a device:
Design and develop a device that will let its user type text using all English letters, digits,
and symbols.
One way to design such a device is to provide a keyboard that has keys for all possible combinations of all letters,
digits, and symbols. This solution is not reasonable as the size of the device will be huge. You may realize that we are
talking about designing a keyboard. Look at your keyboard and see how it has been designed. It has broken down the
problem of typing text into typing a letter, a digit, or a symbol one at a time, which represents the smaller part of the
original problem. If you can type all letters, all digits, and all symbols one at a time, you can type text of any length.
Another decomposition of the original problem may include two keys: one to type a horizontal line and another
to type a vertical line, which a user can use to type in E, T, I, F, H, and L because these letters consist of only horizontal
and vertical lines. With this solution, a user can type six letters using the combination of just two keys. However, with
your experience using keyboards, you may realize that decomposing the keys so that a key can be used to type in only
part of a letter is not a reasonable solution, although it is a solution.
Why is providing two keys to type six letters not a reasonable solution? Aren’t we saving space and number of
keys on the keyboard? The use of the phrase “reasonable” is relative in this context. From a purist point of view, it may
be a reasonable solution. My reasoning behind calling it “not reasonable” is that it is not easily understood by users.
It exposes more details to the users than needed. A user would have to remember that the horizontal line is placed at
the top for T and at bottom for L. When a user gets a separate key for each letter, he does not have to deal with these
details. It is important that the subprograms that provide solutions to parts of the original problem must be simplified
to have the same level of detail to work together seamlessly. At the same time, a subprogram should not expose details
that are not necessary for someone to know in order to use it.
Finally, all keys are mounted on a keyboard and they can be replaced separately. If a key is broken, it can
be replaced without worrying about other keys. Similarly, when a program is decomposed into subprograms, a
modification in a subprogram should not affect other subprograms. Subprograms can also be further decomposed by
focusing on a different level of detail and ignoring other details. A good decomposition of a program aims at providing
the following characteristics:
Simplicity•
Isolation •
Maintainability•
Each subprogram should be simple enough to be understood by itself. Simplicity is achieved by focusing on the
relevant pieces of information and ignoring the irrelevant ones. What pieces of information are relevant and what are
irrelevant depends on the context.
Each subprogram should be isolated from other subprograms so that any changes in a subprogram should have
localized effects. A change in one subprogram should not affect any other subprograms. A subprogram defines an
interface to interact with other subprograms. The inner details about the subprogram are hidden from the outside
world. As long as the interface for a subprogram remains unchanged, the changes in its inner details should not affect
the other subprograms that interact with it.
Each subprogram should be small enough to be written, understood, and maintained easily.
剩余809页未读,继续阅读
2015-05-07 上传
2024-10-15 上传
2024-10-15 上传
jerrylees2006
- 粉丝: 2
- 资源: 64
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C语言快速排序算法的实现与应用
- KityFormula 编辑器压缩包功能解析
- 离线搭建Kubernetes 1.17.0集群教程与资源包分享
- Java毕业设计教学平台完整教程与源码
- 综合数据集汇总:浏览记录与市场研究分析
- STM32智能家居控制系统:创新设计与无线通讯
- 深入浅出C++20标准:四大新特性解析
- Real-ESRGAN: 开源项目提升图像超分辨率技术
- 植物大战僵尸杂交版v2.0.88:新元素新挑战
- 掌握数据分析核心模型,预测未来不是梦
- Android平台蓝牙HC-06/08模块数据交互技巧
- Python源码分享:计算100至200之间的所有素数
- 免费视频修复利器:Digital Video Repair
- Chrome浏览器新版本Adblock Plus插件发布
- GifSplitter:Linux下GIF转BMP的核心工具
- Vue.js开发教程:全面学习资源指南
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功