JavaSE继承
类、子类、超类
定义子类#
待续
覆盖方法#
待续
Super关键字#
子类中的方法不能够直接访问超类的私有域,只有超类本身才能够反问私有部分,如果子类一定要访问超类私有域,可以使用super关键字
public class Manager extends Employee{
...
//子类中获取薪水的方法
public double getSalary()
{
//调用父类中的获取薪水方法
double baseSalary = super.getSalary();
//返回Manager的薪水+奖金的总工资
return baseSalary + bonus;
}
...
}
子类构造器#
public Manager(String name, double salary, int year, int month, int day)
{
super(name, salary, year , month, day) ;
bonus = 0;
}
由于Manager 类的构造器不能访问Employee 类的私有域, 所以必须利用Employee 类 的构造器对这部分私有域进行初始化, 我们可以通过super 实现对超类构造器的调用。使用 super 调用构造器的语句必须是子类构造器的第一条语句。
阻止继承:final 类和方法#
有时候,可能希望阻止人们利用某个类定义子类。不允许扩展的类被称为final类
如果在定义类的时候使用了final修饰符就表明这个类是final 类。
public final class Executive extends Manager
{
...
}
类中的特定方法也可以被声明为final。
如果这样做,子类就不能覆盖这个方法( final 类中的所有方法自动地成为final 方法)
public class Employee
{
...
public final String getName(){
...
}
...
}
抽象类#
Person类作为Employee和Student的顶层类,拥有其子类很多共有的特征,可以使用抽象类来定义Person类,便于让子类进行扩展
- 包含一个或多个抽象方法的类本身必须被声明为抽象的
public abstract class Person
{
...
// 返回一个人的简短描述
public abstract String getDescription();
}
- 除了抽象方法之外,抽象类还可以包含具体数据和具体方法
public abstract class Person
{
private String name;
public Person(String name)
{
this.name = name ;
}
public abstract String getDescription();
public String getName0
{
return name;
}
}
PS:许多程序员认为,在抽象类中不能包含具体方法。建议尽量将通用的域和方法(不管是否是抽象的)放在超类(不管是否是抽象类)中
- 抽象类的两种选择方式
- 一种是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就必须将子类也标记为抽象类
- 另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了
受保护访问#
一般,将类中的域标记为private,而方法标记为public。任何声明为private 的内容对其他类都是不可见的
在有些时候,人们希望超类中的某些方法允许被子类访问,或允许子类的方法访问超类的某个域。为此,需要将这些方法或域声明为 protected
- 例如,如果将超类Employee中的实例域hireDay声明为proteced,而不是私有的, Manager中的方法就可以直接地访问它。
- 对控制可见性的4个访问修饰符进行总结:
- 仅对本类可见private
- 对所有类可见public
- 对本包和所有子类可见protected
- 对本包可见—默认(很遗憾),不需要修饰符
Object:所有类的超类
equals() 方法#
待续
hashCode() 方法#
散列码( hash code)是由对象导出的一个整型值。散列码是没有规律的。如果 x 和 y 是两个不同的对象, x.hashCode( ) 与y.hashCode( ) 基本上不会相同
hashCode 方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址
toString() 方法#
用于返回表示对象值的字符串
常用的方法汇总#
方法名 | 描述 |
---|---|
boolean equals(Object otherObject ) | 比较两个对象是否相等, 如果两个对象指向同一块存储区域, 方法返回true |
String toString( ) | 返冋描述该对象值的字符串。在自定义的类中, 应该覆盖这个方法 |
String getName( ) | 返回这个类的名字 |
Class getClass( ) | 返回包含对象信息的类对象 |
Class getSuperclass( ) | 以Class 对象的形式返回这个类的超类信息 |
对象包装器与自动装箱
- 将int 这样的基本类型转换为对象
- 所有的基本类型都有一个与之对应的类
例如,Integer 类对应基本类型int
通常, 这些类称为包装器( wrapper ) 这些对象包装器类拥有很明显的名字:Integer、Long、Float、Double、Short、Byte、Character 、Void 和Boolean ( 前 6 个类派生于公共的超类Number)
- 包装器类的特点
- 对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值
- 对象包装器类还是final , 因此不能定义它们的子类
假设想定义一个整型数组列表。而尖括号中的类型参数不允许是基本类型就用到了Integer 对象包装器类
ArrayList<Integer> list = new ArrayList<>();
而对此数组列表进行数值添加有
// 自动装箱
list.add(3)
//会自动变为
list.add(Integer.ValueOf(3));
以上变换被称为自动装箱(autoboxing)。相反,将一个Integer 对象赋给一个int 值时,将会自动地拆箱。
//自动拆箱
int n = list.get(i);
//拆箱
int n = list.get(i).intValue();
- 自动装箱注意事项:
- 由于包装器类引用可以为null,所以自动装箱有可能会抛出一个NullPointerException 异常
- 如果在一个条件表达式中混合使用Integer 和Double 类型,Integer 值就会拆箱,提升为double, 再装箱为Double
- 装箱和拆箱是编译器认可的,而不是虚拟机。编译器在生成类的字节码时, 插人必要的方法调用。虚拟机只是执行这些字节码。
Integer n = null;
System.out.println(2 * n); // Throws NullPointerException
Integer n = 1;
Double x = 2.0;
System.out.println(true ? n : x); // Prints 1.0
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Browser-use 详细介绍&使用文档
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞