Java学习笔记 - 类的特征
Java笔记系列:
Java学习笔记–基础内容
Java学习笔记-类的基本概念
文章目录
1.包
-
包的作用:
- 区分相同名字的类,管理类。
- 控制访问范围。
-
基本语法:
package com.hspedu;
- package关键字,表示打包
- com.hspedu:表示包名
- 包的本质是创建不同的文件夹/目录来保存类文件
-
包的命名:
- 命名规则:只能包含数字、字母、下划线、小圆点.,不能用数字开头,不能是关键字保留字
- 命名规范:一般是小写字母+小圆点。例如,com.公司名.项目名.业务模块名
-
常用的包:
java.lang.*
lang包是基本包,默认引入,不需要再引入java.util.*
util包,系统提供的工具包,工具类,提供Scannerjava.net.*
网络包,网络开发java.awt.*
做Java界面开发,GUI
-
引入包:
import 包名;
package作用是声明当前类所在的包,要放在类的最上面,一个类中最多只有一句package
import指令位置放在package的下面,在类定义的前面,可以有多句而且没有顺序要求
2.访问修饰符
-
基本介绍
1)public:公开级别,对外公开
2)protected:对子类和同一个包中的类公开
3)默认:无修饰符,对同一个包的类公开
4)private:只有类本身可以访问,不向外公开
-
访问范围
访问级别 访问控制修饰符 同类 同包 子类 不同包 公开 public ✔ ✔ ✔ ✔ 受保护 protected ✔ ✔ ✔ ✖ 默认 没有修饰符 ✔ ✔ ✖ ✖ 私有 private ✔ ✖ ✖ ✖ -
使用注意
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和public才能修饰类,并遵循上述访问权限的特点
- 成员方法的访问规则和属性一样
3.封装
- 封装:封装就是把抽象出的数据**[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法]**,才能对数据进行操作。
- 可以隐藏实现细节,对数据进行验证,保证安全合理。
- 实现步骤:
- 1)将属性私有化private
- 2)提供一个公共的(public)set方法,用于对属性判断并赋值
- 3)提供一个公共的(public)get方法,用于获取属性的值
封装强迫其他程序一定要经历set方法,set可以检查参数并判断是否可以执行,set可以退回不合理的值或者抛出气场,或者自行修改。可以对数据进行校验,增加了业务逻辑。构造器可以与set方法结合。
4.继承
- 继承:当多个类存在相同的属性和方法时,可以从类中抽象出父类,在父类中定义这些相同的方法属性,子类就无需重新定义,只需要经过
extends
来声明继承父类。 - 基本语法:
class 子类 extends 父类{}
- 子类会自动拥有父类定义的属性和方法。
- 父类又叫超类,基类。
- 子类又叫派生类。
- 优点:提高了代码复用性、扩展性和维护性。
1)子类继承了父类所有的
public
类型的实例变量和方法,但不继承private
类型变量方法,在子类中可以有与父类的重名的private
方法变量。2)子类必须调用父类的构造器,要先完成父类的初始化
3)创造子类对象时,默认情况下会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化。
super(参数列表);
4)
super()
和this()
都只能放在构造器的第一行,两个方法不能共存在一个构造器5)Java所有类都是Object的子类,Object是所有类的基类
6)父类构造器的调用不限于直接父类,将一直向上追溯直至Object。Java为单继承制
7)子类和父类要满足is-a的逻辑关系。
X is-a Y
意味着X是Y的子类,而且 X 可以做出任何 Y 可以做的事情以及更多的行为。
5.super
-
super关键字
-
super:super代表父类的引用,用于访问父类的属性、方法、构造器,不能作为参数和返回值
-
基本语法:
- 访问父类的属性,但不能是private属性:
super.属性名;
- 访问父类的方法,但不能是private方法:
super.方法名(参数列表);
- 访问父类的构造器:
super(参数列表);
只能放在构造器的第一句,只能出现一句。
- 访问父类的属性,但不能是private属性:
-
super
的访问不限于直接父类,爷爷类和本类中有同名成员也可使用super
去访问。 -
当子类和父类中成员重名时,为了访问父类的成员,必须通
super
,如果没有重名,使用super
、this
、直接访问效果相同。 -
如果多个基类中有同名成员,使用
super
访问遵循就近原则。
-
-
super和this区别
区别点 this super 访问属性 访问本类属性,本类没有则找父类 从父类开始查找属性 调用方法 访问本类方法,本类没有则找父类 从父类开始查找方法 调用构造器 调用本类构造器,放首行 调用父类的构造器,必须放在首行 特殊 表示当前对象 子类中访问父类对象
6.方法重写/覆盖(override
-
方法覆盖是指如果子类的某个方法与父类的某个方法的名称、返回类型、参数一样,那么就说子类的方法覆盖了父类的方法。
- 子类方法的形参列表、方法名称要和父类的完全一样
- 子类的返回类型和父类的返回类型要一样或者是父类返回类型的子类。
- 子类方法不能缩小父类的访问权限(子类要支持父类所有对外的行为 public > protected > 默认 > private
-
重写和重载:
-
名称 发生范围 方法名 形参列表 返回类型 修饰符 重载(overload) 本类 必须一样 类型、个数、顺序至少要有一个不同 无要求 无要求 重写(override) 父子类 必须一样 相同 要求与父类的返回类型一致或者是其子类 子类方法不能缩小父类方法的访问范围
7.多态
-
概念:对象或方法具有多种形态,建立在封装和继承的基础上。
-
多态的体现:
-
- 方法的多态:重写和重载
-
-
对象的多态:
-
对象的编译类型和运行类型可以不一致。即对象的引用类型和实际对象类型可以不一致。
-
编译类型在定义时确定,不能改变,但运行类型可以变化
-
编译类型 = 运行类型;编译类型即引用类型,在 = 左边,运行类型为对象实际类型,在 = 右边。
Animal animal = new Dog();
编译类型为Animal,运行类型为Dog。animal = new Cat(); 编译类型仍Animal,但运行类型为Cat。 运行类型可以是编译类型的子类
-
-
-
-
多态的前提:对象类型间存在继承关系。
-
多态的应用:
- 1)多态数组:数组定义类型为父类类型,里面保存的实际元素类型可以为子类型
- 2)多态参数:方法定义的形参类型为父类类型,实参类型允许为子类类型
-
多态的向上转型:
-
本质:父类的引用指向了子类的对象
-
语法:父类类型 引用名 = new 子类类型();
-
特点:可以调用父类所有访问权限允许的成员,可以调用子类中被重写的方法不能调用子类特有成员。
-
public class Animal{
public void sleep(){
System.out.println("Animal sleep ...");
}
pulic void eat(){
System.out.println("Aniaml eat ...");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("Cat eat ...");
}//eat方法重写
public void catchMouse(){
System.out.println("Cat catch ...");
}//cat特有的方法
}
//向上转型
Animal animal = new Cat();
animal.sleep(); //Animal sleep...
animal.eat(); //Cat eat...
//animal.catchMouse(); //错误
-
多态的向下转型:
- 语法:子类类型 引用名 = (子类类型) 父类引用;
- 特点:
- 只能强行转化父类的引用而不能转换父类对象
- 要求父类引用必须指向当前目标类型的对象
- 向下转型后,可以调用子类类型的所有成员
instanceof
比较操作符:用于判断对象的运行类型是否为XX类型或者其子类。
public class Animal{
public void sleep(){
System.out.println("Animal sleep ...");
}
pulic void eat(){
System.out.println("Aniaml eat ...");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("Cat eat ...");
}//eat方法重写
public void catchMouse(){
System.out.println("Cat catch ...");
}//cat特有的方法
}
public class Dog extends Animal{
public void eat(){
System.out.println("Dog eat ...");
}//eat方法重写
}
//向上转型
Animal animal = new Cat();
animal.sleep(); //Animal sleep...
animal.eat(); //Cat eat...
//animal.catchMouse(); //错误
//向下转型
System.out.println(animal instanceof Cat); //true
Cat cat = (Cat) animal;
cat.sleep(); //Animal sleep...
cat.eat(); //Cat eat..
cat.catchMouse(); //Cat catch...
Dog dog = (Dog) animal; //语法上不会报错,但是运行时会异常,类型转换异常
//animal作为Animal的引用对象,指向的是Cat,Cat是Animal的子类,Animal类型的Cat对象可以转换为Cat类型(是动物,也是猫,所以可以在猫和动物之间转换)
//Dog是Animal的子类,但是与Cat无继承关系,Animal类型的Cat对象无法转化为Dog类型(是动物也是猫,但是不是狗,所以不能变成狗
//一个父类变量能不能转换为子类变量,取决于该父类的引用变量是不是要转换的类型的类或者子类。就是猫类是不是要转化的狗类的子类或者就是猫类
8.动态绑定机制
- Java的动态绑定机制:
- 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用,静态绑定
- 动态绑定的实现机制就是根据对象的实际类型(运行类型)查找要执行的方法,子类型找不到时查找父类
9.Object类
在Java中,即使没有声明,也有一个隐含的父类叫Object,没有定义属性但是定义了一些方法。所有的类都从Object类继承出来。
9.1 equals()方法
-
equals()
方法用于判断当前对象和参数传入的对象是否相同,Object类的默认实现是比较地址,只能判断引用类型。在子类中一般重写,用于判断内容是否相等。 -
与
==
区别:==
是一个比较运算符,既可以判断基本类型又可以判断引用类型。基本类型判断值是否相等,引用类型判断地址是否相等。//String中的equals方法为比较两个字符串是否相等 public boolean equals(Object obj){ if(this == obj){//判断是否为同一个对象 return true; } if(obj instanceof String){//判断类型 String str = (String) obj; //向下转型 int n = value.length; if( n == str.value.length){ //判断字符串长度是否相等 char v1[] = value; char v2[] = str.value; int i = 0; while(n-- != 0 ){ if(v1[i] != v2[i]){ return false; } i++; } return true; //比较完所有字符串都相等 } } return false; //如果比较的不是字符串,或者字符串长度不相等,直接返回false }
9.2 hashCode()方法
hashCode()
返回一个对象的哈希值,哈希值是一个int类型的数,由对象中一般不变的属性映射的来,用于快速区分对象、分组等。相同对象的哈希值必然一样。hashCode()
的默认实现一般是将对象的内存地址转化为整数,子类如果重写了equals
方法,也必须重写hashCode
方法。- 对于两个对象,如果
equals方法
返回tru
e,则hashCode
也必须一样,反之则不要求,但是最好equals返回false,hashCode值不一样。
9.3 toString()方法
-
默认返回:全类名 + @ + 哈希值的十六进制
-
子类往往重写toString方法,用于返回对象的属性信息
//object类中的toString方法 //Integer.toHexString(hashCode())将对象的hashCode值转成16进制字符串 public String toString{ return getClass().getName()+"@"+Integer.toHexString(hashCode()); }
9.4 finalize()方法
- 当对象被回收时,系统自动调用finalize方法,子类可以重写该方法,做一些释放资源的操作。
- 当某个对象没有任何引用时,jvm会使用垃圾回收机制来销毁该对象,销毁前会调用finalize方法。
- 垃圾回收制度,由系统自己决定,也可也通过
System.gc()
来主动触发。