一、类的继承
1、概念:在一个现有类的基础上去构建一个新的类,构建出来的新类称为子类,现有的类称为父类。子类继承父类的属性和方法,使得子类对象具有父类
的特征和行为。(用关键字 extends 表示继承关系)。
2、作用: 提高了代码的复用性。
让类与类之间产生了关系,有了这个关系,才有了多态的特性。
【注意】(1)在Java中,类只支持单继承,不允许多重继承。即,一个类只能有一个直接父类。
(2)多个类可以继承一个父类。
(3) 在Java中,多层继承也是可以的,即,一个类的父类可以再继承另外的父类。
(4)在Java中,子类和父类是一种相对的概念,一个类可以是某个类的父类,也可以是另一个类的子类。
二、方法的重写
1、概念:在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。在子类中重写的方法
需要和父类被重写的方法具有相同的方法名、参数列表和返回值类型,且在子类重写的方法不能拥有父类方法更加严格的访问权限。
2、【注意】(1)子类方法覆盖父类方法时,必须保证子类方法权限大于等于父类方法权限,才可以覆盖,否则编译失败。
public > protected > <default> > private
(2)静态方法只能重写(覆盖)静态方法(static)
(3)重载(overload):只看同名方法的参数列表,在同一个类中。
重写(override):子父类方法要一模一样(方法名、返回值、参数列表),在子父类中。
三、super关键字
1、概念:当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,而super关键字可以在子类中调用父类的普通属性、方法和构造方法。
2、具体用法:(1)使用super关键字访问父类的成员变量和成员方法。
super.成员变量
super.成员方法(参数1,参数2...)
(2)使用super关键字访问父类中指定的构造方法
super(参数1,参数2...)
【注意】super()语句必须定义在子类构造方法的第一行,并且只能出现一次。
super 的用法和 this 的用法很相似:this 代表的是本类对象的引用。super 代表的是父类。
四、final关键字
final:最终的,用于修饰类、变量和方法
➢ final 修饰的类,不可以被继承。
➢ final 修饰的方法,不可以被重写。
➢ final 修饰的变量(成员变量和局部变量),变为一个常量,只能赋值一次。
1、final关键字修饰类
Java中的类被final关键件字修饰后,该类将不可以被继承,即不能派生子类。
例如:
2、final关键字修饰类
当一个类的方法被final关键字修饰后,这个类的子类将不能重写该方法。
3、final关键字修饰变量
Java 中被final修饰的变量为常量,常量只能在声明时被赋值一次,在后面程序中其值不能给改变。如果再次对常量赋值,则程序会在编译时报错。
【注意】常量的书写规范:常量所有字母都大写,多个单词组成的话,中间用_连接。
五、抽象类和接口
1、抽象类
(1)特点:
* 方法只有声明没有实现内容时,该方法可以定义成抽象方法,使用 abstract 表示,方法不需要写方法体{},直接分号“;”结束就行。
抽象方法必须定义在抽象类中,该类也必须被 abstract 修饰。
*抽象类不可以被实例化。因为调用抽象方法没有意义(方法体没有被实现)
*抽象类必须有子类覆盖了所有的抽象方法后,该子类才能实例化。否则,这个子类还是抽象类。
(2)【注意】抽象类中有构造方法,用于给子类对象进行初始化。
抽象类可以不定义抽象方法,但是很少见,目的就是为了不让该类创建对象。
抽象 abstract 关键字不可以和哪些关键字共存?
*private 不行(子类无法覆盖)
*static 不行(类名调用没有内容)
*final 不行(final 方法不能被重写)
抽象类和一般类的异同点:
*相同点:抽象类和一般类都是用来描述事物的,都在内部定义了成员。
*不同点:a.一般类有足够的信息描述事物;抽象类描述事物的信息有可能不足。
b.一般类中不能定义抽象方法,只能定义非抽象方法;抽象类中可以定义抽象方法,也可以定义非抽象方法。
c.一般类可以被实例化;抽象类不可以被实例化。
抽象类一定是个父类,因为需要子类覆盖其方法后才可以对子类实例化。
2、接口
(1)概念:当一个抽象类中所有的方法都是抽象方法时,我们可以将该抽象类用另一种形式定义和表示,就是接口,使用关键字 interface 表示。
【注意】对于接口当中常见的成员:这些成员都有固定的修饰符:a.全局常量:public static final
b.抽象方法:public abstract
(2) 接口源文件也是.java 扩展名,在编译后也是生成的.class 文件。类与类之间是继承关系,类与接口之间是实现关系。接口不可以实例化。
只能由实现了接口的子类,并覆盖了接口中所有的抽象方法后,该子类才可以实例化。否则,这个子类就是一个抽象类。
(3)怎么使用接口呢?----实现,使用 implements 关键字
(4)一个类可以实现多个接口:
一个类在继承另一个类的同时,还可以实现多个接口:
(5)接口和接口之间还可以继承,而且接口可以多继承。但是,这个继承体系中的方法都要在子类中覆盖实现。
【注意】子类在实现接口的方法时,要把方法修饰成 public 的,因为接口在定义时,方法默认是 public,即使没有显式的写出来。
(6)接口和抽象类异同点:
*相同点:都是不断向上抽取而来的。
*不同点:a.抽象类需要被继承 extends,而且只能单继承;接口需要被实现 implements,而且可以多实现。
b.抽象类中可以定义抽象方法,也可以定义非抽象方法,子类在继承抽象类后,可以直接使用其中的非抽象方法;接口中只能定义抽象方法,必须由子类去实现。
c.抽象类的继承,是 is a 关系,他是在定义该体系中的基本共性内容;接口的实现,是 like a 关系,他是在定义体系的额外功能。
六、多态
1、概念:在同一个方法中,由于参数类型不同而导致执行效果各异的现象就是多态。
继承是多态得以实现的基础。
2、体现:父类或者接口的引用(引用型变量)指向自己的子类对象。
3、前提:必须是类与类之间有关系,要么继承 extends,要么实现 implements。
4、好处:多态的出现大大提高了程序的扩展性,前期定义的代码可以使用后期的内容。
弊端:只能使用父类的引用访问父类中的成员,前期定义的内容不能使用后期子类的特有内容。
5、多态的转型
(1)向上转型:
【注意】这样就无法调用猫中定义的专属功能了。(子类特有的功能就无法使用了)
向上转型:自动类型提升,子类对象转成父类类型。
猫对象提升成了动物类型,但是特有功能无法访问,子类特有方法被隐藏了。
(2)向下转型:
【注意】里面的小括号是强制性转换,外面的小括号是让它先执行。
如果想调用 Cat 类的特有方法,我们就必须强制将父类的引用转成子类类型。
【注意】多态自始自终都是子类对象在做着类型的变化。
七、关键字 instanceof (...的实例)
1、instanceof 运算符是用来在运行时指出对象是否是
特定类的一个实例,用来判断对象的具体类型,只能用于引用数据类型。
2、instanceof 通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。通常在向下转型前用于健壮性的判断。
八、Object类
1、概念:在 JDK 中提供了一个 Object 类,它是类层次结构的根类,每个类都直接或间接继承自该类,所有对象(包括数组)都实现了这个类的方法。
2、Object 类中的常用方法:
(1)toString()方法:
在测试类里直接调用toString()
在cat里面再定义一个构造方法,然后在测试类里在直接调用show方法
结果都为:
➢ getClass().getName()代表返回对象所属类的类名,即 Animal。
➢ hashCode()代表返回该对象的哈希值。这个方法将对象的内存地址进行哈希运算,返回一个 int 类型的哈希值。
➢ Integer.toHexString(hashCode())代表将对象的哈希值用 16 进制表示。
【注意】toString()方法也是可以被重写
在cat里面定义
(2)equals()方法 (用于测试两个对象是否相等。)
【注意】对于字符串来说,equals方法还可以比较两个字符串的值是否相等:
true
false
这样写也为true
九、包(Package)
1、声明包的语法格式:package 包名;
2、使用时需要注意以下四点:
(1)包名中字母必须都要小写;
(2)包的命名规则:将公司域名反转作为包名;
(3)package 语句必须是程序代码中的第一行可执行语句;
(4)package 语句最多只有一句。包与文件目录类似,可以分成多级,多级之间用点“.”进行分割。例如:package com.sdbi.www;
3、import 语句
在实际开发中,项目都是分模块开发的,对应模块包中的类,完成相应模块的功能。但有时模块之间的类要相互调用,我们就需要使用 import 语句来进行包的导入。例如:
import 包名.类名; // 导入单个类
import 包名.*; // 导入包下的全部类
【注意】java 是核心包,javax 是扩展包。
十、异常处理
1、异常:在程序运行过程中,会发生各种非正常状况,在 Java 语言中,引入了异常,以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。
2、异常的类型:
Throwable 类有两个直接的子类,Error 类和 Exception 类。其中,Error 代表程序中产生的
错误,Exception 代表程序中产生的异常。
(1)Error 类称为错误类,它表示 Java 运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠修改程序本身是不能恢复执行的。
在程序中,使用 Java 命令去执行一个不存在的类就会出现 Error 错误。
(2)Exception 类称为异常类,他表示程序本身可以处理的错误。在开发 Java 程序中进行的异常处理都是针对 Exception 类及其子类。
在 Exception 类的众多子类中有一个特殊 RuntimeException 类,该类及其子类用于表示运行时异常。除了此类,Exception 类下所有其他的子类都用于表示编译时异常。
3、异常处理:try…catch与finally
格式:
try {
//程序代码块
} catch( Exception 类及其子类 e ) {
//对异常的处理
}
其中在 try 代码块中编写可能发生异常的 Java 语句,catch 代码块中编写针对异常进行处理的代码。当 try 代码块中的程序发生了异常,系统会将这个异常的信息封装成一个异常对象,
并将这个对象传递给 catch 代码块。catch 代码块需要一个参数指明它所能够接收的异常类型,这个参数的类型必须是 Exception 类或其子类。
(2)在 try 语句块中,发生异常语句后面的代码是不会被执行的。但有时候,用户希望有些语句无论程序是否发生异常,都要执行,这时就可以在 try…catch 语句后加一个 finally 语句块。
4、throws 关键字
(1)Java 中允许在方法的后面使用 throws 关键字对外声明该方法有可能发生的异常,这样调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过。
(2)格式:修饰符 返回值类型 方法名(参数列表) throws Exceptiontype1[, Exceptiontype2]{
}
(3)解决:
a.使用 try…catch 语句捕获
public class Yichang {
public static void main(String[] args) {
try {
int result = divide(4, 0);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace(); }
System.out.println("程序继续向下执行...");
}
5
public static int divide(int x, int y) throws Exception {
int result = x / y;
return result;
} }
b.继续将异常向上抛出
如果在调用 divide 方法时,不知道如何处理声明抛出的异常,也可以使用 throws 关键字继续将异常向上抛出,这样程序编译也会通过,
但是需要注意的是,程序一旦发生异常,如果没有被处理,程序就会非正常终止。
public class Yichang {
public static void main(String[] args) throws Exception {
int result = divide(4, 0);
System.out.println(result);
System.out.println("程序继续向下执行...");
}
public static int divide(int x, int y) throws Exception {
int result = x / y;
return result;
} }
5、自定义异常
(1)在 Java 中允许用户自定义异常,定义自定义异常类时需要记住下面的几点:
➢ 所有异常都必须是 Throwable 的子类。
➢ 如果想定义一个检查性异常类,则需要继承 Exception 类。
➢ 如果想定义一个运行时异常类,那么需要继承 RuntimeException 类。
public class DivideByMinusException extends Exception {
public DivideByMinusException() {
super(); // 调用 Exception 无参的构造方法
}
public DivideByMinusException(String message) {
super(message); // 调用 Exception 有参的构造方法
} }
(2)用 throw 关键字
public class Yichang {
public static void main(String[] args) {
try {
int result = divide(4, -2);
System.out.println(result);
} catch (Exception e) { // 对捕获到的异常进行处理
e.printStackTrace(); // 打印捕获的异常信息
}
System.out.println("程序继续向下执行...");
}
public static int divide(int x, int y) throws Exception {
if (y < 0) { throw new DivideByMinusException("除数为负数!"); }
int result = x / y;
return result; //
7 } }
6、原则:在当前方法声明中使用 try-catch 语句捕获异常。
一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或其子类。
如果父类抛出多个异常,则覆盖方法必须抛出那些异常的一个子集,不能抛出新异常。