第七章 类和对象
1.对象和类的定义
在Java语言中,类中对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,所以类包括对象的属性和方法。
2.三大特性:封装,继承和多态
2.1封装性
采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易地直接操作此数据结构,只能执行类允许公开的数据。这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。
2.2继承性
继承性主要利用特定对象之间的共有属性。
2.3多态性
多态。依然以图形类来说明多态,每个图形都拥有绘制自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是父类的实例对象 ,这样当绘制图形时,简单地调用父类也就是图形类绘制图形的方法即可绘制任何图形,这就是多态最基本的思想。
在Java语言中称这样的类为抽象类,抽象类不能实例化对象。在多态的机制中,父类通常会被定义为抽象类,在抽象类中给出一个方法的标准,而不给出实现的具体流程。实质上这个方法也是抽象的,如图形类中的“绘制图形"方法只提供-一个可以绘制图形的标准,并没有提供具体绘制图形的流程,因为没有人知道究竟
需要绘制什么形状的图形。
2.4接口
在多态的机制中,比抽象类更方便的方式是将抽象类定义为接口。由抽象方法组成的集合就是接口。接口的概念在现实中也极为常见,如从不同的五金商店买来螺丝帽和螺丝钉,螺丝帽很轻松地就可以拧在螺丝钉上,可能螺丝帽和螺丝钉的厂家不同,但这两个物品可以轻易地组合在一起,这是因为生产螺丝帽和螺丝钉的厂家都遵循着一个标准 ,这个标准在Java中就是接口。
3.类
3.1成员变量
在Java中对象的属性也称为成员变量。
3.2成员方法
在Java语言中使用成员方法对应于类对象的行为。
3.3权限修饰符
Java中的权限修饰符主要包括private、public和protected ,这些修饰符控制着对类和类的成员变量以及成员方法的访问。
3.3.1private
如果一个类的成员变量 或成员方法被修饰为private ,则该成员变量只能在本类中被使用,在子类中是不可见的,并且对其他包的类也是不可见的。
3.3.2public
如果将类的成员变量和成员方法的访问权限设置为public ,那么除了可以在本类使用这些数据之外,还可以在子类和其他包的类中使用。如果一个类的访问权限被设置为private ,这个类将隐藏其内的所有数据,以
免用户直接访问它。
如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为public访问权限。
3.3.3protected
如果一个类使用protected修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法。
注意:
- 当声明类时不使用public、protected和private修饰符设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以调用这个类的成员变量或成员方法。
- 因为Java语言规定,类的权限设定会约束类成员的权限设定。
3.4局部变量
局部变量是在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。
3.4this关键词
使用this关键字来代表本类对象的引用, this关键字被隐式地用于弓|用对象的成员变量和方法。
调用方式是使用“对象.成员变量”或“对象.成员方法”进行调用。
事实上,this引用的就是本类的一个对象。在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加this关键字明确引用的是类成员还是局部变量或方法参数。
3.类的构造方法
在类中除了成员方法之外,还存在- -种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化-个对象时,类都会自动调用构造方法。
构造方法的特点如下:
- 构造方法没有返回值。
- 构造方法的名称要与本类的名称相同。
public class AnyThting {
public AnyThting(){
this("this 调用有参构造方法");
System.out.println("无参构造函数");
}
public AnyThting(String name){
System.out.println("有参构造函数");
}
}
4.静态变量、常量和方法
在介绍静态变量、常量和方法之前首先需要介绍static关键字,因为由static修饰的变量、常量和方法被称作静态变量、常量和方法。
被声明为static的变量、常量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和"."运算符调用静态成员。
[例7.8]在项目中创建StaticTest类,该类中的主方法调用静态成员并在控制台中输出。
public class StaticTest {
final static double PI = 3.1415;
static int id;
public static void method1(){
System.out.println("method1");
}
public static void method2(){
System.out.println("static pi is " + StaticTest.PI);
System.out.println("static id is "+StaticTest.id);
StaticTest.method1();
}
}
[例7.9]在项目中创建StaticTest类,该类中的主方法调用静态成员并在控制台中输出。
public class StaticTest {
final static double PI = 3.1415;
static int id;
public static void method1(){
System.out.println("method1");
}
public static void method2(){
System.out.println("static pi is " + StaticTest.PI);
System.out.println("static id is "+StaticTest.id);
StaticTest.method1();
}
}
报错的原因:
在Java语言中对静态方法有两点规定:
- 在静态方法中不可以使用this关键字。
- 在静态方法中不可以直接调用非静态方法。
注意
在Java中规定不能将方法体内的局部变量声明为static的。例如下述代码就是错误的:
public static void method1(){
// System.out.println("method1");
static int i = 0;
}
技巧
如果在执行类时,希望先执行类的初始化动作,可以使用static定 义一个静态区域。例如:
public class StaticTest {
final static double PI = 3.1415;
static int id;
static {
id++;
}
public static void method1(){
// System.out.println("method1");
// static int i = 0;
}
当这段代码被执行时,首先执行static块中的程序,并且只会执行一次。
5.类的主方法
主方法是类的入口点,它定义了程序从何处开始;主方法提供对程序流向的控制, Java编译器通过主方法来执行程序。
public static void main(String[] args){
}
在主方法的定义中可以看到其具有以下特性:
- 主方法是静态的 ,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
- 主方法没有返回值。
- 主方法的形参为数组。其中
args[0]~args [n]
分别代表程序的第一个参数到第n个参数,可以使用args. length
获取参数的个数。
public static void main(String[] args){
if (args.length == 0){
System.out.println("this is empty! pleas input data");
}
else{
for (int i = 0; i < args.length; i++){
System.out.println(args[i]);
}
}
}
在idea中设置参数
Run->Edit configuration->program argument
**注:**参数之间用空格隔开
6.对象
Java是一门面向对象的程序设计语言, 对象是由类抽象出来的,所有的问题都通过对象来处理。对象可以操作类的属性和方法解决相应的问题,所以了解对象的产生、操作和消亡是十分必要的。
6.1对象的创建
对象可以认为是在一类事物中抽象出某一个特例,可以通过这个特例来处理这类事物出现的问题。
可以通过这个特例来处理这类事物出现的问题。在Java语 言中通过new操作符来创建对象。前文在讲解构造方法时绍过每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程。
每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由Java虚拟机自带的垃圾回收机制处理,不能再被使用。
public class CreateObject {
public CreateObject(){
System.out.println("创建对象");
}
public static void main(String args[]){
new CreateObject();
}
}
6.2访问对象的属性和行为
用户使用new操作符创建一个对象后,可以使用“对象.类成员”来获取对象的属性和行为。前文已经提到过,对象的属性和行为在类中是通过类成员变量和成员。
public class TransferProperty {
int i = 99;
public void call()
{
System.out.println("transfer call() method");
for (i = 0; i < 3; i++){
System.out.print(i + " ");
}
System.out.println();
}
public TransferProperty(){
}
public static void main(String[] args){
TransferProperty t1 = new TransferProperty();
TransferProperty t2 = new TransferProperty();
t2.i = 9;
System.out.println("first demo result is " + t1.i);
t1.call();
System.out.println("second demo result is " + t2.i);
t2.call();
}
}
6.2对象的引用
语法如下:
类名对象引用名称
注意
引用只是存放一个对象的内存地址,并非存放一个对象。严格地说,引用和对象是不同的,但是可以将这种区别忽略,如可以简单地说book是Book类的一个对象,而事实上应该是book包含Book对象的一个引用。
6.2对象的比较
在Java语言中有两种比较对象的方式,分别为"==" 运算符与equals()方法。
public class Compare {
public static void main(String[] args){
String c1 = new String(("qwe"));
String c2 = new String("asd");
String c3 = c1;
System.out.println("c2 == c3 result is " + (c1 == c3));
System.out.println("c2.equals(c3)" + (c1.equals(c3)));
}
}
6.2对象的销毁
6.2.1垃圾回收器
每个对象都有生命周期,当对象的生命周期结束时,分配给该对象的内存地址需要被回收。
虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象。
6.2.2finalize()
在Java中提供了一个finalize()方法,这个方法是0bject类的方法,它被声明为protected ,用户可以在自己的类中定义这个方法。如果用户在类中定义了finalize()方法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。
6.2.3System. gc ()
Java提供了System. gc ()
方法来强制启动垃圾回收器,这与给120打电话通知医院来救护病人的道理一样,主动告知垃圾回收器来进行清。