Java 初学 day07
Java 07
1、继承 extend
举例
我想养一只🐕,所以先创建一个Dog类,里面有姓名和年龄的属性,吃饭和睡觉的方法。
我还想养一只🐱,猫也有姓名和年龄,也有吃饭和睡觉的方法,按照之前的做法,我们可以按照Dog类的写法再写一遍Cat类
若我们还想养其它的动物的话,每个动物都有自己的名字和年龄,以及都会吃饭和睡觉,如果我们每一个类都写一遍的话,
就会觉得代码重复度非常的高。
继承的概述
java替我们考虑到了,我们可以使用另外一个A类,将重复的内容放到这个A类中,让B类和C类与A类,产生一个关系,
关系一旦建立,B类和C类中,也就拥有了A类中的内容。这个关系,就是继承。
java提供了一个关键字用来表示继承关系:extends
写法:class B extends A{} 表示B类继承自A类
这里的B称之为:子类,派生类
这里的A称之为:父类,基类或者超类
代码示例
class Animal{
String name;
int age;
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
class Dog extends Animal {
//子类相当于这里有一份父类中的非私有成员
public void lookDoor(){
System.out.println("看家");
}
}
class Cat extends Animal{
}
public class ExtendsDemo1{
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.sleep();
System.out.println(dog.name);
System.out.println(dog.age);
}
}
java中,类与类之间继承的时候,不允许一次继承多个类,只允许单继承,但是可以进行多重继承,形成继承体系
继承注意事项
1、子类无法继承父类中私有的成员
2、子类不能继承父类的构造方法
3、不要为了部分功能而去继承
子类寻找成员变量并使用的流程:
1、先就近原则,在方法内部中查找一次,若找到就使用
2、若方法内部没有需要的变量,去当前类成员变量的位置上查找,若找到就使用
3、若当前类成员变量的位置上没有需要的变量,去父类中的成员变量的位置上查找,若找到就使用
4、若上面3个地方都没有找到所需要的变量,就报错
2、super关键字
java中提供了另外一个关键字super,用法跟this很像,但是super代表的是当前子类的直接父类的引用
在子类中,可以通过super关键字使用直接父类中的非私有成员
代码示例
class Fu2{
int a = 10;
}
class Son2 extends Fu2{
int a = 20;
public void fun1(){
int a = 30;
System.out.println(a); // 30
System.out.println(this.a); // 20
// Fu2 fu2 = new Fu2();
// System.out.println(fu2.a);
System.out.println(super.a); // 10
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Son2 son2 = new Son2();
son2.fun1();
}
}
super关键字的使用注意事项:
1、super仅代表当前类中的直接父类,无法使用super获取父类的父类中的成员
2、super后面不能再调用super
3、继承和构造方法的关系
在java继承关系中,要想初始化子类,必须先初始化其父类,这里默认super()体现的就是这个意思
1、子类构造方法的第一句话,默认会有一个super(),对父类做初始化,只能在子类构造方法第一句出现。
问题:如果父类中没有无参构造方法呢?
1)使用super关键字调用父类中的有参构造方法,完成父类的初始化
2)调用当前类中其它有参的构造方法间接对父类做初始化
2、java中每一个只允许初始化一次
class Fu4{
// Fu4(){
// System.out.println("这是父类中的无参构造方法.....");
// }
Fu4(String s){
System.out.println("这是父类中有参数的构造方法....");
}
}
class Son4 extends Fu4{
Son4(){
//super()
super("数加");
// this("数加");
System.out.println("这是子类的无参构造方法.....");
// super("数加");
}
Son4(String s){
super(s);
}
}
public class ExtendsDemo6 {
public static void main(String[] args) {
Son4 son4 = new Son4();
}
}
4、继承与成员方法的关系:
当子类中的方法声明【方法的返回值类型,方法名和参数列表】与父类中的方法声明一致的时候,只是方法的实现不一样,这个现象叫做方法的重写【方法的覆盖】。
java提供了一个注解帮助我们判断是否是重写@Override
class Fu5{
public void fun1(){
System.out.println("这是父类中的fun1方法");
}
}
class Zi5 extends Fu5{
@Override
public void fun1(){
System.out.println("这是子类中的fun1方法");
}
public void fun2(){
System.out.println("这是子类中的fun2方法");
}
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi5 zi5 = new Zi5();
zi5.fun2();
zi5.fun1();
}
}
重写所需要注意事项:
1、子类无法重写父类中的私有方法
2、子类无法继承且重写父类中的静态方法
3、子类重写方法的权限,要大于等于父类的方法权限,推荐在没有要求的情况下,保持和父亲一致的权限就好了
面试题:重写和重载什么区别?【overload和override什么区别?】
1、重写是发生在继承关系中的,指的是子类方法的返回值类型和方法名以及参数列表与父类方法一致,只是实现不一样
2、重载是发生在同一个类中,值的是方法名一样,参数列表不同,与返回值无关的现象
class Fu6{
public void fun1(){
System.out.println("江川是世界上最帅的男人!");
}
void function1(){
System.out.println("这是父类中默认修饰符的成员方法,...");
}
public static void method(){
System.out.println("这是父类中的静态方法.....");
}
private void show1(){
System.out.println("好好学习,天天向上!");
}
}
class Zi6 extends Fu6{
@Override
public void fun1(){
System.out.println("吴问强很不服,他认为自己才是世界上最帅的男人!");
}
@Override
void function1(){
System.out.println("这是子类中默认修饰符的成员方法,...");
}
// @Override
public static void method(){
System.out.println("这是父类中的静态方法.....");
}
// @Override
private void show1(){
System.out.println("在数加好好学习!");
}
}
public class ExtendsDemo8 {
public static void main(String[] args) {
Zi6 zi6 = new Zi6();
zi6.fun1();
}
}
5、final关键字
概述
java提供了以关键字给我们使用,可以修饰父类成员方法,让其只能被子类使用,不能重写。
final: 最终的,不可改变的
final的用法
- 类:若修饰类,则该类不能被继承
- 变量:修饰变量,变量变成常量,不能修改被final变量的值,自定义常量
- 方法:若修饰方法,该方法不能被子类重写
class Fu8 {
final int a = 10;
int b = 10;
}
class Zi8 extends Fu8 {
public void fun1(){
// a = 20;
System.out.println(a);
}
}
public class FinalDemo1 {
public static void main(String[] args) {
// Zi8 zi8 = new Zi8();
// zi8.fun1();
final Fu8 f = new Fu8(); // 指的是地址值不能被修改
System.out.println(f.a);
System.out.println(f.b);
// f.a = 100;
f.b = 100;
System.out.println(f.b);
// f = new Fu8();
}
}
注意事项
被final所修饰的成员变量,必须要在构造方法结束之前给值
class Fu9 {
// {
// final int a;
// }
// final int a = 10;
final int A;
Fu9(){
A = 100;
}
}
public class FinalDemo2 {
public static void main(String[] args) {
}
}
6、多态
概述
它允许对象以多种形式出现。在 Java 中,多态意味着父类的引用可以指向子类的对象,并根据实际指向的对象调用相应的方法,从而实现灵活的代码设计和重用。
多态:指的是某一个事物,在不同时刻下的不同状态
举例:水【气态的水,液态的水,固态的水】
水果【🍉,🍇,🍎】
多态的三要素
- 要有继承关系
- 要有方法的重写【子类可以不重写父类中的方法,但是重写了会更好的体现子类的特点】
- 要有父类的引用指向子类的对象
多态访问成员的特点
/*
1、访问成员变量:编译看左,运行看左
2、访问成员方法:编译看左,运行看右
3、访问静态成员方法:编译看左,运行看左
*/
class Fu10 {
int a = 10;
public void fun1() {
System.out.println("好好学习,天天向上!");
}
public static void show1() {
System.out.println("这是父类中的静态方法show1");
}
}
class Zi10 extends Fu10 {
int a = 20;
@Override
public void fun1() {
System.out.println("在数加科技里好好学习!");
}
// public void fun1() {
// System.out.println("在数加科技里好好学习!");
// }
public static void show1() {
System.out.println("这是子类中的静态方法show1");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu10 f = new Zi10();
System.out.println(f.a);
f.fun1();
f.show1();
}
}
/*
输出:===========================
10
在数加科技里好好学习!
这是父类中的静态方法show1
*/
多态的好处
1、提高了程序的维护性(由继承保证)
2、提高了程序的扩展性(由多态保证)
多态的向下转型
格式: 子类类名 变量名 = (子类类名)要转型的变量名;
class Fu1{
public void fun1(){
System.out.println("好好学习,天天向上!");
}
}
class Zi1 extends Fu1{
@Override
public void fun1() {
System.out.println("李刚现在在数加好好学习,天天向上!");
}
public void show1(){
System.out.println("李刚现在没有睡觉...");
}
}
class Demo1 extends Fu1{
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu1 f1 = new Zi1();
f1.fun1();
Zi1 z1 = (Zi1)f1;
z1.show1();
//并不是任意两个类型之间都可以做向下转型,只有实际内存对象类型与要转的类型一样
// Demo1 d1 = (Demo1) f1; //ClassCastException
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!