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();
}
posted @   tse121  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示