java面向对象类和对象
类,字段,方法,构造函数和对象是基于对象的Java应用程序的构建块。 本教程教您如何声明类,通过字段描述属性,通过方法描述行为,通过构造函数初始化对象以及从类实例化对象并访问其成员。 在此过程中,您还将了解设置器和获取器,方法重载,设置字段,构造函数和方法的访问级别等。 请注意,本教程中的代码示例可在Java 12下编译并运行。
高级技术:Java中的字段和方法
学习使用字段和方法进行Java编程的七种高级技术 ,包括递归,方法链,按值传递参数和调用方法的规则。
类声明
类是用于制造对象的模板。 通过指定class
关键字后跟一个非保留的标识符对其进行命名,即可声明一个类。 一对匹配的打开和关闭大括号字符( {
和}
)跟随并界定了类的主体。 该语法如下所示:
class identifier
{
// class body
}
按照惯例,类名称的首字母大写,随后的字符小写(例如Employee
)。 如果名称由多个单词组成,则每个单词的首字母大写(例如SavingsAccount
)。 该命名约定称为CamelCasing 。
下面的示例声明一个名为Book
的类:
class Book
{
// class body
}
类的主体填充有字段,方法和构造函数。 将这些语言功能组合到类中称为封装 。 这种功能使我们可以在更高的抽象级别(类和对象)进行编程,而不必分别关注数据结构和功能。
什么是基于对象的应用程序?
基于对象的应用程序是一种应用程序,其设计基于声明类,从类创建对象以及设计对象之间的交互。
实用程序类
可以将一类设计为与对象制造无关。 相反,它作为类字段和/或类方法的占位符存在。 这样的类称为实用程序类 。 实用程序类的一个示例是Java标准类库的Math
类。 有关另一个示例,请参见Java技巧:Java中的字段和方法 。
多类应用程序和main()
Java应用程序由一个或多个类实现。 小型应用程序可以由一个类容纳,但是大型应用程序通常需要多个类。 在那种情况下,将其中一个类指定为主类,并包含main()
入口点方法。 例如,清单1展示了使用三个类A
, B
和C
构建的应用程序; C
是主要类。
清单1.具有多个类的Java应用程序
class A
{
}
class B
{
}
class C
{
public static void main(String[] args)
{
System.out.println("Application C entry point");
}
}
您可以在单个源文件中声明这三个类,例如D.java
。 然后,您将按照以下方式编译此源文件:
javac D.java
编译器生成三个类文件: A.class
, B.class
和C.class
。 通过以下命令运行此应用程序:
java C
您应该观察以下输出:
Application C entry point
或者,您可以在其自己的源文件中声明每个类。 按照约定,源文件的名称与类名称匹配。 例如,您将在A.java
声明A
然后,您可以分别编译这些源文件:
javac A.java
javac B.java
javac C.java
为了节省时间,您可以通过用星号替换文件名来一次编译所有三个源文件(但保留.java
文件扩展名):
javac *.java
无论哪种方式,您都可以通过以下命令运行该应用程序:
java C
公开课
Java使您可以通过public
关键字声明具有公共访问权限的类。 声明类public
,必须将其存储在同名文件中。 例如,您将public class C {}
存储在C.java
。 您只能在源文件中声明一个public
类。
在设计多类应用程序时,将这些类之一指定为主类,并在其中找到main()
方法。 但是,没有什么可以阻止您在其他类中声明main()
方法的,可能是出于测试目的。 清单2中显示了此技术。
清单2.声明一个以上的main()
方法
class A
{
public static void main(String[] args)
{
System.out.println("Testing class A");
}
}
class B
{
public static void main(String[] args)
{
System.out.println("Testing class B");
}
}
class C
{
public static void main(String[] args)
{
System.out.println("Application C entry point");
}
}
编译源代码之后,您将执行以下命令来测试助手类A
和B
,并运行应用程序类C
:
java A
java B
java C
然后,您将观察到以下输出行,每个java
命令一行:
Testing class A
Testing class B
Application C entry point
注意main()
在每个类中放置main()
方法可能会造成混淆,尤其是在您忘记记录主类的情况下。 此外,您可能会忘记在将应用程序投入生产之前删除这些方法,在这种情况下,它们的存在会增加应用程序的体积。 此外,某人可能会运行其中一个支持类,这可能会破坏应用程序的环境。
字段:描述属性
类根据状态(属性)对现实世界实体进行建模。 例如,车辆具有颜色,而支票帐户具有余额。 一个类也可以包括非实体状态。 无论如何,状态都存储在称为field的变量中。 字段声明具有以下语法:
[static] type identifier [ = expression ] ;
字段声明可以选择以关键字static
(对于非实体属性)开头,并以type
开头,后跟一个为字段命名的非保留identifier
。 可以通过指定=
后跟具有兼容类型的expression
来显式初始化该字段。 分号终止声明。
下面的示例在Book
声明一对字段:
class Book
{
String title;
int pubYear; // publication year
}
title
和pubYear
字段声明与我在“ Java 101:基本Java语言功能 ”中介绍的变量声明相同。 这些字段称为实例字段,因为每个对象都包含它们自己的副本。
title
和pubYear
字段存储特定书籍的值。 但是,您可能希望存储独立于任何特定书本的状态。 例如,您可能想要记录创建的Book
对象的总数。 这是您的处理方式:
class Book
{
// ...
static int count;
}
本示例声明一个count
整数字段,该字段存储创建的Book
对象的数量。 声明以static
关键字开头,以指示内存中此字段只有一个副本。 每个Book
对象都可以访问此副本,并且没有对象拥有自己的副本。 因此, count
被称为class字段 。
初始化
之前的字段未分配值。 当您不显式初始化字段时,它会隐式初始化,并将其所有位设置为零。 您将此默认值解释为false
(对于boolean
), '\u0000'
(对于char
), 0
(对于int
), 0L
(对于long
), 0.0F
(对于float
), 0.0
(对于double
)或null
(对于参考类型)。
但是,也可以在声明字段时显式初始化该字段。 例如,您可以指定static int count = 0;
(这是不必要的,因为count
默认为0), String logfile = "log.txt";
, static int ID = 1;
,甚至是double sinPIDiv2 = Math.sin(Math.PI / 2);
。
尽管您可以通过直接分配来初始化实例字段,但是在构造函数中执行此初始化更为常见,我将在后面进行演示。 相反,类字段(尤其是类常量)通常是通过将表达式直接分配给该字段来初始化的。
寿命和范围
实例字段是在创建对象时生成的,而在对象被垃圾回收时死亡。 类字段在加载类时诞生,并在卸载类或应用程序结束时终止。 此属性称为有效期 。
实例和类字段从其声明到声明类的末尾都是可访问的。 此外,如果给定了适当的访问级别,则外部代码只能在对象上下文(例如字段)或对象和类上下文(对于类字段)中访问它们。 此属性称为scope 。
方法:描述行为
除了对真实世界实体的状态建模之外,类还对行为进行建模。 例如,车辆支持运动,而支票账户支持存款和取款。 类也可以包含非实体行为。 无论如何,Java程序员使用方法来描述行为。 方法声明具有以下语法:
[static] returnType identifier ( [ parameterList ] )
{
// method body
}
方法声明可以选择从关键字static
(对于非实体行为)开始,并以returnType
开头,后跟一个为该方法命名的非保留identifier
。 然后,名称后跟一个以圆括号分隔的可选parameterList
。 用大括号分隔的主体,其中包含在调用该方法时要执行的代码。
返回类型标识通过return
语句从方法返回的值的类型,我将在后面讨论。 例如,如果方法返回字符串,则其返回类型将设置为String
。 当方法不返回值时,其返回类型设置为void
。
参数列表是用逗号分隔的参数声明列表:每个声明均由类型组成,后跟一个非保留的标识符,该标识符为参数命名。 参数是在调用方法或构造函数时接收参数 (其类型与其相应参数兼容的表达式值)的变量。
参数是其方法或构造函数的局部参数。 它在方法或构造函数被调用时存在,而在方法或构造函数返回其调用者时消失。 换句话说,它的生命周期就是方法的执行。 该方法中的任何代码都可以访问参数。 它的范围是整个方法。
下面的示例在Book
类中声明四个方法:
class Book
{
// ...
String getTitle()
{
return title;
}
int getPubYear()
{
return pubYear;
}
void setTitle(String _title)
{
title = _title;
}
void setPubYear(int _pubYear)
{
pubYear = _pubYear;
}
}
getTitle()
和getPubYear()
方法返回其各自字段的值。 他们使用return
语句将这些值返回给调用方。 请注意,此语句的表达式的类型必须与方法的返回类型兼容。
使用setTitle()
和setPubYear()
方法可以设置title
和pubYear
字段的值。 它们的返回类型设置为关键字void
以指示它们不向调用者返回任何值。 这四种方法都称为实例方法,因为它们仅影响调用它们的对象。
设置者和获取者
“ set
”前缀将setTitle()
和setPubYear()
标识为setter方法 ,这意味着它们可以设置值。 同样,“ get
”前缀将getTitle()
和getPubYear()
标识为getter方法 ,这意味着它们获取值。
如果您想知道是否需要setter / getter方法来代替直接访问title
和pubYear
,则可以在StackOverflow.com上的“ getter和setter的意义是什么? ”主题中找到一些很好的理由。
getTitle()
, getPubYear()
, setTitle()
和setPubYear()
方法影响单个对象的title
和pubYear
字段的副本。 但是,您可能想声明一个独立于任何特定书籍的方法。 例如,您可能想要引入一种输出Book
对象数量的方法,如下所示:
class Book
{
// ...
static void showCount()
{
System.out.println("count = " + count);
}
}
本示例声明了一个showCount()
方法,该方法将输出count
字段的值。 该声明以static
关键字开头,以指示此方法属于该类,并且无法访问单个对象状态。 无需创建对象。 因此, showCount()
被称为类方法 。
局部变量
在方法或构造函数中,可以声明其他变量作为其实现的一部分。 这些变量称为局部变量,因为它们在方法/构造函数中是局部的。 它们仅在执行方法或构造函数时存在,并且无法从方法/构造函数外部访问。 考虑以下示例:
static void average(double[] values)
{
double sum = 0.0;
for (int i = 0; i < values.length; i++)
sum += values[i];
System.out.println("Average: " + (sum / values.length));
}
翻译自: https://www.infoworld.com/article/2979739/java-101-classes-and-objects-in-java.html
java面向对象类和对象