🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 1、继承 * 继承是一种类与类之间的关系 * 使用已存在的类的定义作为基础建立新类 * 作为基础的类一般称为父类(基类),创建的新类称为子类(派生类) * 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类 * 满足`A is a B`的关系就可以形成继承关系 ## 1.1 代码实现 在 Java 中使用`extends`关键字来实现类的继承,同时需要注意的是在 Java 中只能继承一个父类。 * 编写父类 ``` public class Animal { // 公共的属性和方法 } ``` * 编写子类,继承父类 ``` public class Dog extends Animal { // 子类特有的属性和方法 } public class Cat extends Animal { // ... } ``` ### 1.2 方法的重写 方法重写出现在有继承关系的子类中,以下几个要素都要与父类中允许继承的方法相同 * 方法名 * 方法参数(类型、顺序、个数) > 方法的访问修饰符是可以允许有变化的,重写方法的访问修饰符必须比父类方法的访问修饰符范围要大。 > 方法的返回值类型是可以允许有变化的,重写方法的返回值类型必须与父类方法的返回值类型相同或者是其派生类 【阅读】以下程序的输出结果是() ``` public class Father { public void print() { System.out.println("Father-->print"); } } public class Son extends Father { public void print() { System.out.println("Son-->print"); } public static void main(String[] args) { Father f = new Father(); f.print(); } } ``` 【选择】以下关于方法重载和方法重写描述正确的是()(选择一项) ``` A 方法重载和方法重写实现的功能相同 B 方法重载出现在父子关系中,方法重写是在同一类中 C 方法重载的返回类型必须一致,参数必须不同 D 方法重写需要出现在满足继承关系的子类中 ``` 【选择】那个选项中的方法插入到(1)处可以正确实现方法重写()(选择一项) ``` public class Animal { public void eat(String food) {} public static void bark() {} public final void display() {} } public class Cat extends Animal { // (1) } ``` ``` A public static void bark() {} B public final void display() {} C public void eat(String food) {} D public boolean eat(String food) {} ``` 【编程】接收用户输入的信息,选择需要完成的工作任务。其中,可供选择的有:测试工作和研发工作。程序运行参考效果图如下: ``` 父类信息测试:开心工作 测试工作类信息测试:测试工作的日报是:今天编写了10个测试用例,发现了5个bug 研发工作类信息测试:研发工作的日报是:今天编写了1000行代码,目前仍然有10个bug没有解决 ``` ``` public class Test { public static void main(String[] args) { System.out.print("父类信息测试:"); System.out.print("测试工作类信息测试:"); System.out.print("研发工作类信息测试:"); } } public class Work { private String name; // 属性:工作名 // 无参构造方法 // 带参构造方法,完成工作类型的赋值 // 公有的get***/set***方法完成属性封装 // 方法:工作描述,描述内容为:开心工作 public String work() { } } public class TestWork extends Work { // 属性:编写的测试用例个数、发现的Bug数量 // 编写构造方法,并调用父类相关赋值方法,完成属性赋值 // 公有的get***/set***方法完成属性封装 /** * 重写运行方法,描述内容为:**的日报是:今天编写了**个测试用例,发现了**bug。 * 其中**的数据由属性提供 */ public String work() { } } public class DevelopmentWork extends Work { // 属性:有效编码行数、目前没有解决的Bug个数 // 编写构造方法,并调用父类相关赋值方法,完成属性赋值 // 公有的get***/set***方法完成属性封装 /** * 重写运行方法,描述内容为:**的日报是:今天编写了**行代码,目前仍然有**个bug没有解决。 * 其中**的数据由属性提供 */ public String work() {} } ``` ### 1.3 访问修饰符的分类及使用 | 访问修饰符 | 本类 | 同包 | 子类 | 其他 | | :-: | :-: | :-: | :-: | :-: | | private | yes | no | no | no | | 默认 | yes | yes | no | no | | protected | yes | yes | yes | no | | public | yes | yes | yes | yes | 【选择】在下面程序的注释(1)处补充下列()方法,会导致在编译过程中发生错误(选择一项) ``` public class Father { public float getNum() { return 3.0f; } } public class Son extends Father { // (1) } ``` ``` A public float getNum() { return 4.0f; } B private float getNum() { return 4.0f; } C public void getNum(double d) {} D public double getNum(float d) { return 4.0f;} ``` 【选择】代码位置(1)处填写()选项,可以使代码编译通过。(选择三项) ``` public class Alpha { public void bar(int x) {} public void bar(int... x) {} } public class Beta extends Alpha { // (1) } ``` ``` A private void bar(int x) {} B public void bar(int x) {} C public int bar(String x) { return 1; } D public Alpha bar(int x) { return new Alpha(); } E public void bar(int x, int y) {} F public int bar(int x) { reutrn x; } ``` ### 1.4 `super`关键字 我们使用 super 关键字在子类中来表示对父类对象的引用。 * 访问父类成员方法 super.方法名(); * 访问父类属性 super.属性(); * 访问父类构造方法 super(); > 子类构造方法默认会调用父类的无参构造方法 > 可以通过 super() 调用父类允许被访问的其他构造方法 > super() 必须方法在子类构造方法有效代码第一行 【阅读】以下程序的输出结果是() ``` package foo; public class Father { public Father() { System.out.println("Father Create"); } } package test; import foo.Father; public class Child extends Father { public Child() { System.out.println("Child Create"); } public static void main(String[] args) { Father father = new Father(); Child child = new Child(); } } ``` 【阅读】如下源代码,编译并运行Child.java后,结果为() ``` public class Parent1 { public Parent1(String s) { System.out.println(s); } } public class Parent2 extends Parent1 { public Parent2() { System.out.println("parent2"); } } public class Child extends Parent2 { public static void main(String[] args) { Child child = new Child(): } } ``` 【选择】分析如下所示的Java代码,则选项中的说法正确的是()(选择一项) ``` public class Parent { public String name; public Parent(String name) { this.name = name; } } public class Test extends Parent { public Test(String name) { // (1) name = "hello"; // (2) super("kitty"); // (3) } } ``` ``` A 第(1)行错误,Test 类的构造函数中参数名称应与其父类构造函数中的参数名相同 B 第(2)行错误,应使用 super 关键字调用父类的 name 属性,改为 super.name = "hello" C 第(3)行错误,调用父类构造方法的语句必须放在子类构造方法的第一行 D 程序编译通过,无错误 ``` 【选择】关于 super 的说法正确的是()(选择一项) ``` A 是指当前子类的对象 B 是指当前类的对象 C 是指当前父类的对象 D 可以用在 mian() 方法中 ``` 【阅读】阅读下面代码片段,结果为() ``` public class Car { String color; String motor; public Car(String color, String motor) { this.color = color; this.motor = motor; } } public class Truck extends Car { double weight; public Truck() {} public Truck(String color, String motor, double weight) { super(color, motor); this.weight = weight; } public void display() { System.out.println("颜色:" + color); System.out.println("发动机的型号:" + motor); System.out.println("载重量:" + weight); } public static void main(String[] args) { Truck truck = new Truck("红色", "玉柴", 1.5); truck.display(); } } ``` 【选择】下列关于 super 和 this 的说法错误的是()(选择一项) ``` A this 关键字通常指当前对象 B super 关键字则指父类对象 C 在一个类中 this 只可以调用当前类中共有属性和方法 D 在一个类中 super 可以调用父类中允许被访问的属性和方法 ``` 【多选】某公司要开发“XX车行管理系统”,请使用面向对象的思想,设计自定义类描述自行车、电动车和三轮车。程序参考运行效果图如下: ``` 父类信息测试:这是一辆红颜色的,天宇牌的非机动车,有4个轮子,有2个座椅 自行车类信息测试:这是一辆黄颜色的,捷安特牌的自行车 电动车类信息测试:这是一辆使用飞鸽牌电池的电动车 三轮车类信息测试:三轮车是一款有3个轮子的非机动车 ``` ``` public class Test { public static void main(String[] args) { System.out.print("父类信息测试:"); System.out.print("自行车类信息测试:"); System.out.print("电动车类信息测试:"); System.out.print("三轮车类信息测试:"); } } public class NonMotor { // 私有属性:品牌、颜色、轮子(默认2个)、座椅(默认 1个) // 无参构造方法 // 双参构造方法,完成对品牌和颜色的赋值 // 四参构造方法,分别对所有属性赋值 // 公有的get***/set***方法完成属性封装 /** * 方法:运行,描述内容为:这是一辆**颜色的,**牌的非机动车,有**个轮子,有**个座椅的非机动车。 * 其中**的数据由属性提供 */ public String work() { } } public class Bicyle extends NonMotor { // 在构造方法中调用父类多参构造,完成属性赋值 // 重写运行方法,描述内容为:这是一辆**颜色的,**牌的自行车。其中**的数据由属性提供 } public class ElectricVehicle extends NonMotor { // 私有属性:电池品牌 // 公有的get***/set***方法完成属性封装 // 重写运行方法,描述内容为:这是一辆使用**牌电池的电动车。其中**的数据由属性提供 } public class Tricycle extends NonMotor { // 在无参构造中实现对轮子属性值进行修改 // 重写运行方法,描述内容为:三轮车是一款有**个轮子的非机动车。其中**的数据由属性提供 } ``` ## 2、Object 类 * `Object`类是所有类的父类 * 一个类没有使用`extends`关键字明确标识继承关系,则默认继承`Object`类(包括数组) * Java 中的每一个类都可以使用`Object`类中定义的方法 ### 2.1 `equals()`方法 * 继承`Object`中的`equals`方法时,比较的是两个引用是否指向同一个对象 * 子类可以通过重写`equals`方法的形式,改变比较的内容 ### 2.2 `toString()`方法 * 输出对象名时,默认会直接调用类中`toString()` * 继承`Object`中的`toString`方法时,输出对象的字符串表示形式:`类型信息@哈希码` * 子类可以通过重写`toString`方法的形式,改变输出的内容以及表现形式 【选择】下列关于 Object 类的描述错误的是()(选择一项) ``` A Object 类是所有类的父类 B 所有类都可以继承 Object 中允许被继承的方法 C 一个类没有使用 extends 关键字明确标识继承关系,则默认继承 Object 类 D 要想继承 Object 类,必须使用 extends 关键字标识继承关系,否则不会实现继承 ``` 【阅读】该段代码的运行结果为() ``` public class Father { private String name; private int age; public Father (String name, int age) { this.name = name; this.age = age; } public static void main(String[] args) { Father fa1 = new Father("小明", 13); Father fa2 = new Father("小明", 13); boolean flag = fa1.equals(fa2); System.out.println(flag); } } ``` 【编程】请使用面向对象的思想,设计自定义类 Person 继承 Object 类,重写 toString 方法实现对象信息输出。运行效果如下图所示: ``` 姓名:李明,年龄:18,性别:男 姓名:陈红,年龄:17,性别:女 ``` ``` public class Test { public static void main(String[] args) { // 实例化对象,传入属性值 // 打印输出对象信息 } } public class Person { // 私有属性:name(姓名)、age(年龄)、sex(性别) // 带参构造方法(name、age、sex为参数) // 通过封装实现对属性的get/set方法设定 // 重写toString方法,表示形式为:姓名:+**+ 年龄:+**+ 性别:+** } ``` ## 3、final 关键字 * 修饰类:该类不允许被继承 * 修饰方法:该方法不允许被重写 * 修饰成员属性:赋值必须在实例对象之前 赋值过程:1、定义直接初始化 2、构造代码块内 3、构造方法内 * 修饰局部变量:只要在使用之前进行赋值即可,一旦赋值不允许被修改 * 基本数据类型的变量:初始赋值之后不能改变 * 引用类型的变量:初始化之后不能再指向另一个对象 【选择】下列关于`final`的说法正确的是() ``` A final 修饰的变量值不允许被修改 B final 修饰的方法不可被重写 C final 可以修饰所有方法 D final 不可以修饰构造方法 ``` * `MAX_LENGTH`是`int`型`public`成员变量,数值保持为常量100,应该如何定义() ## 4、注解 * `JDK 1.5`版本引入的一个特性 * 可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释 按照运行机制分: * 源码注解:注解只在源码中存在,编译成`.class`文件就不存在了。 * 编译时注解:注解在源码和`.class`文件都存在。 * 运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解。 【编程】请使用面向对象的思想,实现杨梅和仙人蕉的信息描述。程序参考运行效果图如下: ``` 水果可供人们食用! fru1和fru2的引用比较:true ----------------------- 杨梅:紫红色、圆形、果味酸甜适中。 杨梅酸甜适中,非常好吃! 杨梅的信息:果实为圆形、紫红色、酸甜适中、非常好吃! ----------------------- 仙人蕉果形短而稍圆、果肉香甜、可供生食。 仙人蕉颜色为黄色 ``` ``` public class Test { public static void main(String[] args) { // 实例化2个父类对象,传入两组相同的参数值 // 调用父类eat方法 // 测试重写equals方法,判断两个对象是否相等 System.out.println("-----------------------"); // 实例化子类对象,并传入相关参数值 // 调用子类face方法和eat方法 // 测试重写toString方法,输出子类对象的信息 System.out.println("-----------------------"); // 实例化Banana类对象,并传入相关参数值 // 调用子类的advantage和它的重载方法 } } public class Fruits { // 私有属性:水果的形状(shape)和口感(taste) // 无参构造器 // 带参构造函数(参数为shape和taste) // 通过封装实现对私有属性的get/set访问 // 创建无参无返回值得方法eat(描述内容为:水果可供人们食用!) // 重写equals方法,比较两个对象是否相等(比较shape,taste) } public class Waxberry { // 私有属性:颜色(color) //创建构造方法,完成调用父类的构造方法,完成属性赋值 //创建不允许重写的face方法,描述为:杨梅:**、**,果味酸甜适中 //重写父类eat方法,描述为:杨梅酸甜适中,非常好吃! //重写toString方法,输出的表现形式不同(输出shape,color,taste) } public class Banana { // 私有属性:品种(variety) //创建带参构造方法为所有属性赋值 //创建无参无返回值的advantage方法,描述为:**果形**,果肉香甜,可供生食。 //创建重载advantage方法(带参数color),描述为:**颜色为** } ``` 【编程】请使用面向对象的思想,实现出租车和家用轿车的信息描述。程序运行参考效果如下: ``` 我是机动车! car1和car2的引用比较:true ======================== 张小泉的出租车是属于长生公司的 出租车是提高市民生活质量的重要条件之一 taxi的信息是:张小泉拥有一辆蓝色的出租车 ======================== 孙二娘拥有的紫色颜色的私家车,有7座位 家用汽车大多有5个座位 ``` ``` public class Test { public static void main(String[] args){ //实例化父类对象,并传入两组相同的属性值 //调用父类use方法 //通过重写equals方法,比较两个对象是否相等 System.out.println("========================"); //实例化子类Taxi对象,并传入属性值 //调用ride和use方法 //输出重写toString后的taxi信息 System.out.println("========================"); //实例化子类HomeCar对象,并传入属性值 //调用display方法及它的重载方法 } } public class Car { // 属性:车的颜色color、车主姓名userName // 无参构造函数 // 带参构造函数(参数为color和useName) // 通过封装实现对私有属性的get/set操作 // 创建无参无返回值得方法use(描述内容为:我是机动车!) // 重写equals方法,比较两个对象是否相等(比较color,userName) } public class Taxi extends Car{ // 私有属性:所属公司(company) // 无参构造方法 // 调用父类的构造方法,完成属性赋值 // 通过封装实现对私有属性的get/set操作 // 创建不允许重写的ride方法,描述为:**出租车是所属于***公司的。 // 重写父类use方法,描述为:出租车是提高市民生活质量的重要条件之一 // 重写toString方法,输出的表现形式不同(输出color,userName) } public final class HomeCar extends Car{ // 私有属性:载客数(num) // 带参构造方法为所有属性赋值 // 通过封装实现对私有属性的get/set操作 // 创建无参无返回值的display方法,表现为:**拥有的**颜色的私家车,有**座位 // 重载display方法(带参数num),描述为:家用汽车大多有**个座位 } ```