[REPRINT] Java 101: Classes and objects in Java
http://www.javaworld.com/article/2979739/learn-java/java-101-classes-and-objects-in-java.html?page=3
class Book
{
// ...
static int count;
}
This example declares a count integer field that stores the number of Book objects created. The declaration begins with the static keyword to indicate that there is only one copy of this field in memory. Each Book object can access this copy, and no object has its own copy. For this reason, count is known as a class field.
The previous fields were not assigned values. When you don't explicitly initialize a field, it's implicitly initialized with all of its bits set to zero. You interpret this default value as false (for boolean), '\u0000' (for char), 0 (for int), 0L (for long), 0.0F (for float), 0.0 (for double), or null (for a reference type).
class Book
{
// ...
static void showCount()
{
System.out.println("count = " + count);
}
}
This example declares a showCount() method that will output the value of the count field. The declaration begins with the static keyword to indicate that this method belongs to the class and cannot access individual object state; no objects need to be created. For this reason, showCount() is known as a class method.
Method overloading
Java lets you declare methods with the same name but with different parameter lists in the same class. This feature is known as method overloading. When the compiler encounters a method-call expression, it compares the called method's comma-separated list of arguments with each overloaded method's parameter list as it looks for the correct method to call.
Two same-named methods are overloaded when their parameter lists differ in number or order of parameters. Alternatively, two same-named methods are overloaded when at least one parameter differs in type. For example, consider the following four draw() methods, which draw a shape or string at the current or specified draw position:
void draw(Shape shape)
{
// drawing code
}
void draw(Shape shape, double x, double y)
{
// drawing code
}
void draw(String string)
{
// drawing code
}
void draw(String string, double x, double y)
{
// drawing code
}
When the compiler encounters draw("abc")
;, it will select the third method because it offers a matching parameter list. However, what will the compiler do when it encounters draw(null, 10, 20)
;? It will report a "reference to draw is ambiguous" error message because there are two methods from which to choose.
You cannot overload a method by changing only the return type. For example, you couldn't specify int add(int x, int y)
and double add(int x, int y)
because the compiler doesn't have enough information to distinguish between these methods when it encounters add(4, 5); in source code. The compiler would report a "redefinition" error.
Constructors: Initializing objects
As well as explicitly assigning values to fields, a class can declare one or more blocks of code for more extensive object initialization. Each code block is a constructor. Its declaration consists of a header followed by a brace-delimited body. The header consists of a class name (a constructor doesn't have its own name) followed by an optional parameter list:
className ( [parameterList] )
{
// constructor body
}
The following example declares a constructor in the Book class. The constructor initializes a Book object's title and pubYear fields to the arguments that were passed to the constructor's _title and _pubYear parameters when the object was created. The constructor also increments the count class field:
class Book
{
// ...
Book(String _title, int _pubYear)
{
title = _title;
pubYear = _pubYear;
++count;
}
// ...
}
The parameter names have leading underscores to prevent a problem with the assignments. For example, if you renamed _title
to title
and specified title = title
;, you would have merely assigned the parameter's value to the parameter, which accomplishes nothing. However, you can avoid this problem by prefixing the field names with this.
:
class Book
{
// ...
Book(String title, int pubYear)
{
this.title = title;
this.pubYear = pubYear;
++count;
}
// ...
void setTitle(String title)
{
this.title = title;
}
void setPubYear(int pubYear)
{
this.pubYear = pubYear;
}
// ...
}
A parameter (or local variable) name that's identical to an instance field name shadows (meaning hides or masks) the field. Keyword this represents the current object (actually, its reference). Prepending this. to the field name removes the shadowing by accessing the field name instead of the same-named parameter.
Although you can initialize fields such as title and pubYear through the assignments shown above, it's preferable to perform the assignments via setter methods such as setTitle()
and setPubYear()
, as demonstrated below:
class Book
{
// ...
Book(String title, int pubYear)
{
setTitle(title);
setPubYear(pubYear);
++count;
}
// ...
}
Constructor calling
Classes can declare multiple constructors. For example, consider a Book constructor that accepts a title argument only and sets the publication year to -1 to indicate that the year of publication is unknown. This extra constructor along with the original constructor are shown below:
class Book
{
// ...
Book(String title)
{
setTitle(title);
setPubYear(-1);
++count;
}
Book(String title, int pubYear)
{
setTitle(title);
setPubYear(pubYear);
++count;
}
// ...
}
But there is a problem with this new constructor: it duplicates code setTitle(title);
located in the existing constructor. Duplicate code adds unnecessary bulk to the class. Java provides a way to avoid this duplication by offering this()
syntax for having one constructor call another:
class Book
{
// ...
Book(String title)
{
this(title, -1);
// Do not include ++count; here because it already
// executes in the second constructor and would
// execute here after this() returns. You would end
// up with one extra book in the count.
}
Book(String title, int pubYear)
{
setTitle(title);
setPubYear(pubYear);
++count;
}
// ...
}
The first constructor uses keyword this followed by a bracketed argument list to call the second constructor. The single parameter value is passed unchanged as the first argument, and -1 is passed as the second argument. When using this()
, remember that it must be the first piece of code in a constructor; otherwise, the compiler reports an error.
Objects: Working with class instances
Once you have declared a class, you can create objects from it. An object is nothing more than a class instance. For example, now that the Book class has been declared, you can create one or more Book objects. Accomplish this task by specifying the new operator followed by a Book constructor, as follows:
Book book = new Book("A Tale of Two Cities", 1859);
new loads Book into memory and then calls its constructor with arguments "A Tale of Two Cities" and 1859. The object is initialized to these values. When the constructor returns from its execution, new returns a reference (some kind of pointer to an object) to the newly initialized Book object. This reference is then assigned to the book variable.
Constructor return type
If you were wondering why a constructor doesn't have a return type, the answer is that there is no way to return a constructor value. After all, the new operator is already returning a reference to the newly-created object.
After creating a Book object, you can call its getTitle()
and getPubYear()
methods to return the instance field values. Also, you can call setTitle()
and setPubYear()
to set new values. In either case, you use the member access operator (.
) with the Book reference to accomplish this task:
System.out.println(book.getTitle()); // Output: A Tale of Two Cities
System.out.println(book.getPubYear()); // Output: 1859
book.setTitle("Moby Dick");
book.setPubYear(1851);
System.out.println(book.getTitle()); // Output: Moby Dick
System.out.println(book.getPubYear()); // Output: 1851
Messaging objects
Calling a method on an object is equivalent to sending a message to the object. The name of the method and its arguments are conceptualized as a message that is being sent to the object on which the method is called.
You don't have to create any Book objects to call class methods. Instead, you prepend the class name and member access operator to the class method's name when calling these methods:
Book.showCount(); // Output: count = 1
Finally, it's possible to get and set the values of Book's instance and class fields. Use an object reference to access an instance field and a class name to access a class field:
System.out.println(book.title); // Output: Moby Dick
System.out.println(Book.count); // Output: 1
book.pubYear = 2015;
System.out.println(book.pubYear); // Output: 2015
I previously mentioned that instance methods affect only the objects on which they are called; they don't affect other objects. The following example reinforces this truth by creating two Book objects and then accessing each object's title, which is subsequently output:
Book book1 = new Book("A Tale of Two Cities", 1859);
Book book2 = new Book("Moby Dick", 1851);
Book book3 = new Book("Unknown");
System.out.println(book1.getTitle()); // Output: A Tale of Two Cities
System.out.println(book2.getTitle()); // Output: Moby Dick
System.out.println(book3.getPubYear()); // Output: -1
Book.showCount(); // Output: count = 3
Information hiding and access levels
A class's body is composed of interface and implementation. The interface is that part of the class that's accessible to code located outside of the class. The implementation is that part of the class that exists to support the interface. Implementation should be hidden from external code so that it can be changed to meet evolving requirements.
Consider the Book class. Constructor and method headers form this class's interface. The code within the constructors and methods, and the various fields are part of the implementation. There is no need to access these fields because they can be read or written via the getter and setter methods.
However, because no precautions have been taken, it's possible to directly access these fields. Using the previous book reference variable, you could specify book.title and book.pubYear, and that would be okay with the Java compiler. To prevent access to these fields (or at least determine who can access them), you need to take advantage of access levels.
An access level is an indicator of who can access a field, method, or constructor. Java supports four access levels: private, public, protected, and package (the default). Java provides three keywords that correspond to the first three access levels:
- private: Only code in the same class as the member can access the member.
- public: Any code in any class in any package can access the member.
- protected: Any code in the same class or its subclasses can access the member.
If there is no keyword then package access is implied. Package access is similar to public access in that code outside of the class can access the member. However, unlike public access, the code must be located in a class that belongs to the same package (discussed later in the Java 101 series) as the class containing the member that is to be accessed.
You can prevent external code from accessing Book's title and pubYear fields so that any attempt to access these fields from beyond Book will result in a compiler error message. Accomplish this task by prepending private to their declarations, as demonstrated below:
[REPRINT] Java 101: Classes and objects in Java的更多相关文章
- Java Date Classes
References: [1] http://tutorials.jenkov.com/java-date-time/index.html [2] https://docs.oracle.com/ja ...
- Top 15 Java Utility Classes
In Java, a utility class is a class that defines a set of methods that perform common functions. Thi ...
- Java Nested Classes(内部类~第一篇英文技术文档翻译)
鄙人最近尝试着翻译了自己的第一篇英文技术文档.Java Nested Classes Reference From Oracle Documentation 目录 嵌套类-Nested Classes ...
- Linq to Objects for Java
好几年不写博客了,人也慢慢变懒了.然而想写了却不知道写点啥,正好最近手头有点小项目就分享一下经历. 现在 java 的大环境下,基本都是围着 spring 转,加上一堆其他的库.有了架子就开始搞业务了 ...
- Java Virtual Machine (JVM) objects 虚拟机实例的产生 退出 两种线程
Apache Spark is built around a distributed collection of immutable Java Virtual Machine (JVM) object ...
- Core Java Volume I — 1.2. The Java "White Paper" Buzzwords
1.2. The Java "White Paper" BuzzwordsThe authors of Java have written an influential White ...
- 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA
1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...
- 【Java】-NO.16.EBook.4.Java.1.007-【疯狂Java讲义第3版 李刚】- Java基础类
1.0.0 Summary Tittle:[Java]-NO.16.EBook.4.Java.1.007-[疯狂Java讲义第3版 李刚]- Java基础类 Style:EBook Series:J ...
- 20165230 《Java程序设计》实验二(Java面向对象程序设计)实验报告
20165230 <Java程序设计>实验二(Java面向对象程序设计)实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:田坤烨 学号:20165230 成绩: ...
随机推荐
- nyoj 1022:合纵连横(并查集删点)
题目链接 参考链接 只附代码好了 #include<bits/stdc++.h> using namespace std; ; int a[N],b[N],vis[N]; int n,m, ...
- [CSU1806]Toll
题目:Toll 传送门:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1806 题目简述:给定n个点m条有向边的有向图,每条边的花费是$b_i ...
- arm可以干什么
ARM开发可以控制各种电机.arm性能很强 ,内存更大, c语言当然可以.ARM是32位的,单片机是8位的,运行速度快很多,最关键的是可以跑操作系统.控制部分的内容ARM当然可以胜任,而且ARM的资源 ...
- GH001 on github
remote: warning: GH001: Large files detected. You may want to try Git Large File Storage - https://g ...
- Redis详细用法
Redis详细用法 1.redis启动命令 本机Redis 安装路径是在usr/local/redis 目录下 启动命令: ./redis-server redis.conf(启动时指定配置文件) 测 ...
- Html5 学习笔记 【PC固定布局】 实战2 导航栏搜索区域
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8& ...
- 如何制作一个可以用Bochs调试的最新内核系统盘
参考:http://blog.chinaunix.net/uid-26207112-id-3332621.html 1. 正确地创建一个包含启动分区的磁盘映像 1.1 创建磁盘映像文件 首先需要对磁盘 ...
- 【读书笔记】:MIT线性代数(5):Four fundamental subspaces
At the beginning, the difference between rank and dimension: rank is a property for matrix, while di ...
- FastJSON 远程执行漏洞,速速升级!
相信大家用 FastJSON 的人应该不少,居然有漏洞,还不知道的赶紧往下看,已经知道此漏洞的请略过-- 2019年6月22日,阿里云云盾应急响应中心监测到FastJSON存在0day漏洞,攻击者可以 ...
- ubantu18.04中mysql8.0设置远程连接的问题
在mysql8.0中的配置文件中默认是没有绑定地址的,但是可以自己配置,在my.cnf中 这里使用另一种方式: 首先先连接到自己的数据库执行: use mysql; select host,user ...