java基础Day7 面向对象(2)
六、继承 Inheritance
6.1
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends:扩展。子类(派生类)是父类(基类)的扩展。
继承是类与类之间的关系。
java中只有单继承,没有多继承:一个儿子只能有一个爸爸,一个爸爸可以有多个儿子。
Inheritance>Application & Person & Student
package Inheritance; public class Application { public static void main(String[] args) { Student student = new Student(); student.say(); System.out.println(student.money1); System.out.println(student.money2); //System.out.println(student.money3);//私有的,不属于子类 } }
package Inheritance; //人 public class Person { //public public int money1 = 100_0000; //default int money2 = 200_0000; //protected //private private int money3 = 10_0000_0000; public void say(){ System.out.println("说了一句话"); } }
package Inheritance; //学生 是 人 派生类、子类 //子类继承了父类,就会拥有父类的全部方法(public) public class Student extends Person { }
ctrl+h,打开层次结构:
在java中,所有类都默认直接或间接继承Object类
6.2 super
Inheritance>Application & Person & Student
package Inheritance; public class Application { public static void main(String[] args) { Student student = new Student(); student.test1("name in test"); student.test2(); } }
package Inheritance; //人 public class Person { //protected protected String name = "name in Person"; public void print(){ System.out.println("Person"); } //alt+insert-->构造函数-->无选择 public Person() { System.out.println("Person无参执行了"); } }
package Inheritance; public class Student extends Person { private String name = "name in Student"; public void test1(String name){ System.out.println(name);//name in test System.out.println(this.name);//name in Student System.out.println(super.name);//name in Person } public void print(){ System.out.println("Student"); } public void test2(){ print();//Student this.print();//Student super.print();//Person } public Student() { //隐藏代码:调用了父类的无参构造 //super();//且调用父类的构造器必须要在子类无参构造器的第一行 //this("Hello");//如果调用子类自己的有参构造器,也必须要在子类无参构造器的第一行,且子类的有参构造器和父类构造器只能调用一个 System.out.println("Student无参执行了"); } }
输出顺序是:
Person无参执行了
Student无参执行了
name in test
name in Student
name in Person
Student
Student
Person
Note:
- super是调用父类的构造方法,必须在构造方法的第一个;
- super必须只能出现在子类的方法或者构造方法中;
- super和this不能同时调用构造方法;
vs. this:
- 代表的对象不同:
this:本身调用着这个对象;
super:代表父类对象的引用。
- 前提:
this:没有继承也可以使用;
super:只能在继承条件下才可以使用
- 构造方法:
this():本类的构造;
super():父类的构造
6.3 方法重写 Override
Inheritance>Application & A & B
package Inheritance; public class Application { public static void main(String[] args) { B b = new B(); //b.test1();//输出Bteat() b.test2();//输出Bteat() //静态方法和非静态方法区别很大 A a = new B();//父类的引用指向了子类; //静态方法:方法的类型只和最左边‘A’有关 //a.test1();//输出Ateat() //非静态方法:子类重写了父类的方法 a.test2();//输出Bteat() } }
package Inheritance; //重写都是方法的重写,和属性无关 public class A { public static void test1() { System.out.println("Ateat()"); } public void test2() { System.out.println("Ateat()"); } }
package Inheritance; public class B extends A { public static void test1() { System.out.println("Bteat()"); } //alt+insert-->重写方法 @Override//注解,有功能的注释 public void test2() { System.out.println("Bteat()"); } }
这个标志为重写了
Note:
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大: public>protected>default>private
- 抛出的异常:范围可以被缩小,但不能扩大:ClassNotFoundException-->Exception(大)
为什么需要重写?
- 父类的功能子类不一定需要或满足;
Alt+insert-->override
七、多态 Polymorphism
7.1
动态编译
Polymorphism > Application & A & B
package Polymorphism; public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student; //new Person; //但可以指向的引用类型就不确定了 //Student能调用的方法都是自己的或者继承父类的 Student s1=new Student(); //Person可以指向子类,但是不能调用子类独有的方法 Person s2=new Student();//父类的引用指向子类 //String s2=new Student();//不行,String和Student没有关系 Object s3=new Student(); s2.run();//当子类中没有重写run()时,输出run in Person;当子类重写run()后,输出run in Student s1.run();//当子类中没有重写run()时,输出run in Person;当子类重写run()后,输出run in Student s1.eat(); //s2.eat();//不能调用子类的,对象能执行哪些方法主要看左边的类型,和右边关系不大 ((Student)s2).eat();//强制转换,高转低 } }
package Polymorphism; public class Person { public void run(){ System.out.println("run in Person"); } }
package Polymorphism; public class Student extends Person { @Override public void run() { System.out.println("run in Student"); } public void eat(){ System.out.println("eat"); } }
Note:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系,类型转换异常 ClassCastException
- 存在的条件:继承关系;方法需要重写;父类引用指向子类对象:Father s1=new Son();
(static方法,属于类,它不属于实例;final 常量;private方法 都不能重写)
7.2 instanceof
instanceof 引用类型转换:判断一个对象是什么类型
Polymorphism > Application
System.out.println(X instanceof Y);//能不能编译通过
package Polymorphism; public class Application { public static void main(String[] args) { Object s4=new Student(); System.out.println(s4 instanceof Student);//输出true System.out.println(s4 instanceof Person);//输出true System.out.println(s4 instanceof Object);//输出true System.out.println(s4 instanceof Teacher);//输出false System.out.println(s4 instanceof String);//输出false System.out.println("================="); Person s5=new Student(); System.out.println(s5 instanceof Student);//输出true System.out.println(s5 instanceof Person);//输出true System.out.println(s5 instanceof Object);//输出true System.out.println(s5 instanceof Teacher);//输出false //System.out.println(s5 instanceof String);//编译报错 System.out.println("================="); Student s6=new Student(); System.out.println(s6 instanceof Student);//输出true System.out.println(s6 instanceof Person);//输出true System.out.println(s6 instanceof Object);//输出true //System.out.println(s6 instanceof Teacher);//编译报错 } }
类型转换:
package Polymorphism; public class Application { public static void main(String[] args) { //类型之间的转换:父-->子 高-->低 //高 低 Person s7=new Student(); //student.eat();//报红 //将这个对象转换为Student类型,我们就可以使用Student类型的方法 ((Student)s7).eat(); Student s8=new Student(); Person person = s8;//低转高可以直接转,不过子类转换为父类可能丢失一些方法 } }
- 父类引用指向子类的对象
- 把子类转换为父类:向上转型,不用强制转换
- 把父类转换为子类:向下转型,强制转换
- 方便方法的调用,减少重复的代码
八、static关键字详解
StaticSummary > Student
package StaticSummary; //static public class Student { private static int age;//静态变量 private double score;//非静态变量 public void run(){ } public static void go(){ } public static void main(String[] args) { Student s1 = new Student(); System.out.println(Student.age); //System.out.println(Student.score);//报红 System.out.println(s1.age); System.out.println(s1.score); new Student().run(); Student.go(); go(); //run();//报红,和类一起加载 } }
package StaticSummary; public class Person { { //匿名代码块 System.out.println("匿名代码块"); } static{ //静态代码块 System.out.println("静态代码块"); } public Person() { System.out.println("构造方法"); } public static void main(String[] args) { Person person1 = new Person(); /* 输出顺序:静态代码块 匿名代码块 构造方法 */ System.out.println("===================="); Person person2 = new Person(); /* 输出:匿名代码块 构造方法 static{}没了,它只执行一次 static{}一般用来赋初始值,因为它和对象是同时产生的 */ } }
静态导入包:
package StaticSummary; import static java.lang.Math.random;//静态导入包 import static java.lang.Math.PI; public class Test { public static void main(String[] args) { //System.out.println(Math.random());//输出一个随机数 System.out.println(random()); System.out.println(PI); } }
被final修饰的类不能被继承
九、抽象类
AbstractClass > A & Action
package AbstractClass; //abstract 抽象类: 类 extends: 单继承 (接口可以多继承) public abstract class Action { //约束 有人帮我们实现 //abstract抽象方法,只有方法名字,没有方法的实现 public abstract void doSometing(); // 1. 不能new这个抽象类,只能靠子类去实现它;约束 // 2. 抽象类中可以写普通方法 // 3. 抽象方法必须要在抽象类中 public void hello(){ } // 抽象的抽象:约束 //new 存在构造器吗? //存在的意义:抽象出来,提高开发效率 }
package AbstractClass; //抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非子类也是抽象类 public class A extends Action{ @Override public void doSometing() { } }
十、接口
普通类:只有具体的实现;
抽象类:具体的实现和规范(抽象方法)都有;
接口:只有规范,自己无法写方法,专业的约束;约束和实现分离;面向接口编程
接口定义的是一组规则
接口的本质是契约
声明接口的关键字是interface
package Interface; //interfacce 定义的关键字,接口都需要有实现类 public interface UserService { //属性默认是常量 public static final int AGE = 99; //接口中的所有定义其实都是抽象的public abstract void add(String name); void delete(String name); void update(String name); void query(String name); }
package Interface; public interface TimeService { void timer(); }
package Interface; //一个类可以实现接口 //实现了接口的类,就需要重写接口中的方法 public class UserServiceImpl implements UserService, TimeService {//多继承,利用接口实现多继承 //alt+insert-->实现方法 @Override public void timer() { } @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } }
Note:
- 约束
- 定义一些方法,让不同的人实现
- 接口不能被实例化,接口中没有构造方法
- implements可以实现多个接口
- 实现了接口的类必须要实现接口中的方法
十一、内部类(奇葩代码)
package InnerClasses; public class Application { public static void main(String[] args) { Outer outer = new Outer(); //通过外部类来实例化内部类 Outer.Inner1 inner = outer.new Inner1(); inner.in(); inner.getID(); } }
package InnerClasses; public class Outer { private int id = 10; public void out(){ System.out.println("这是外部的方法"); } public class Inner1{ public void in(){ System.out.println("这是内部类的方法"); } //获得外部类的私有属性 public void getID(){ System.out.println(id); } } public static class Inner2{ } public void method(){ //局部内部类 class Inner3{ public void in(){ } } } } //一个java类中可以有多个class类,但是只能有一个public class class A{ public static void main(String[] args) { } }
package InnerClasses; public class Test { public static void main(String[] args) { Apple apple1 = new Apple(); //没有名字初始化类,不用将实例保存到变量中 new Apple().eat(); UerService uniservice=new UerService(){ @Override public void hello() { } }; } } class Apple{ public void eat(){ System.out.println("Apple eat"); } } interface UerService{ void hello(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现