JavaOOP

Java面向对象

Object-Oriented Programming , 本质 : 以类的方式组织代码 , 以对象的组织(封装)数据

抽象

三大特性----封装 , 继承 , 多态

类与对象

类是抽象的,使用new创建对象

public class Application {
    public static void main(String[] args) {
        Student student=new Student();
        System.out.println(student.name);
        student.name="老王";
        System.out.println(student.name);
    }
}
======
public class Student {
    //属性 : 字段
    String name;
    int age;

    //方法  只存在这两个东西
    public void study(){
        System.out.println(this.name+"在学习哦");
    }
}

构造器

一个类即使什么都不写,也有个默认的构造器

  • 使用new关键字,本质是在调用构造器

  • 一旦定义了有参构造,无参就必须显示定义

  • 实例化初始值

IDEA快捷键 : alt+insert

public class Person {
    String name;
    int age;
    public Person(){
        this.name = "老王";
    }
    public Person(String name){
        this.name = name;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /*
    1. 和类名相同
    2. 没有返回值
    作用 :
    1. new 本质实在调用构造方法
    2. 初始化对象的值
    注意 :
    * 定义了有参之后,如果想使用无参,必须要显式定义无参
     */
}
======
public class Application {
    public static void main(String[] args) {
        //new实例化了一个对象
        Person person=new Person();
        System.out.println(person.name);

    }
}

内存对象分析

栈中加载方法 , 堆中有一块方法区

首先在栈中加载main()方法 , Cat c=new Cat(); , 栈中存放的是引用变量名,指向堆中的地址 , 对象是通过引用来操作的 ( 栈—>堆 )

public class Application {
    public static void main(String[] args) {
        Cat c=new Cat();
        c.name="咪咪";
        c.age=3;

        c.run();

        Cat b=new Cat();
    }
}
============
public class Cat {
    public String name;
    public int age;

    public void run(){
        System.out.println("猫猫跑了.");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cN5z7z8F-1638108154458)(C:\Users\Yu\Desktop\内存图.png)]

封装

数据的隐藏 , 该露的露 , 该藏的藏----->高内聚 , 低耦合

高内聚 : 类的内部数据操作细节自己完成 , 不允许外部干涉

低耦合 : 仅暴露少量的方法给外部使用

一句话 : 属性私有 , get/set

get : 获得这个数据

set : 给这个数据设置值

alt+insert快捷键

**意义 : **

  1. 提高程序的安全性 , 保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统可维护性增加了
public class Application {
    public static void main(String[] args) {
        Student s1=new Student();
        s1.getName();
        s1.setAge(150);
    }
}
==========
public class Student {
    private String name;    //姓名
    private int age;        //年龄
    private String sex;     //性别

    //提供get/set方法

    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return this.name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(this.age<=0 || this.age>120){
            System.out.println("不合法");
        }else{
            this.age = age;
        }
    }
}

重载

参照 : System.out.println(); //能输出很多东西

构造器用的重载较多

方法名相同 , 参数列表不同

继承

extends 子类是父类的扩展

继承是类和类 , 还有依赖 , 组合 , 聚合等

子类(派生类)----父类(积累)

子类继承父类 , 就会拥有父类的全部方法,属性 (非私有的)

ctrl+H快捷键打开继承树关系

所有的类都默认直接或者间接继承Object类

Java中只有单继承 , 没有多继承

super

super关键点 :

  • super调用父类的构造方法,必须在构造方法的第一个。
  • super必须只能出现在子类的方法或者构造方法中
  • super和this不能同时调用构造方法

super & this :

​ 代表的对象不同 :

  • this:本身调用这个对象
  • super:代表父类对象的引用

​ 前提:

  • this:没有继承也可以使用
  • 只能在继承条件才可以使用

​ 构造方法:

  • this():本类的构造
  • super():父类的构造
public class Application {
    public static void main(String[] args) {
        Teacher teacher=new Teacher();
        teacher.output("软件工程");
    }
}
=======
public class Person {
    public String name;
    public String dept="计算机学院";
    public Person(String name){
        this.name=name;
    }
    public Person(){} //如果没有无参的构造方法则会报错,因为没有了默认的构造方法
}
=======
public class Teacher extends Person{
    public int age;
    public String dept="计算机科学与技术";

    public Teacher(String name,int age){
        super(name);
        this.age=age;
    }
    public Teacher(){}

    public void output(String dept){
        System.out.println("super.dept = " + super.dept);
        System.out.println("this.dept = " + this.dept);
        System.out.println("dept = " + dept);
    }

}

方法重写

重写都是方法的重写

前提 : 需要有继承关系 , 子类重写父类的方法

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符 : 范围可以扩大 , 但是不能缩小
  4. 抛出的异常 : 范围可以被缩小 , 但不能扩大

----方法名相同 , 方法体不同

为什么需要重写 ?

–父类的功能子类不一定需要或者不满足

public class Application {
    public static void main(String[] args) {
        Son s=new Son();
        s.test();
        Father f=new Son();
        f.test();
    }
}

=========
    
public class Father {
    public void test(){
        System.out.println("我是father");
    }
}
=========
public class Son extends Father{
    @Override
    public void test() {
        System.out.println("我是son");
    }
}

多态

一个对象的实际类型是确定的 , 可以指向的引用类型就不确定了 : 父类的引用指向子类

多态注意事项:

  1. 多态是方法的多态
  2. 父类和子类有联系 , 否则类型转换异常 : ClassCastException!
  3. 存在条件 : 继承关系–方法重写–父类引用指向子类对象

无法重写 :

  1. static方法 , 属于类 , 不属于实例
  2. final 常量
  3. private方法
public class Application {
    public static void main(String[] args) {

        //s1调用的方法是Student独有的或者是继承父类的
        Student s1=new Student();
        //s2 左边编译 , 右边执行 , 不能调用子类独有的方法
        Person s2=new Student();
        Object s3=new Student();

        s2.eat();
    }
}
============
public class Person {
    public void eat(){
        System.out.println("father eat");
    }
}
============
public class Student extends Person{
    @Override
    public void eat() {
        System.out.println("son eat");
    }
}

instanceof

判断是否存在父子关系

理清关系即可

// Object > Person > Student
// Object > Person > Teacher
// Object > String
               Object s1=new Student();
        Student s2=new Student();

        boolean b1=s1 instanceof Object;
        boolean b2=s1 instanceof Person;
        System.out.println(b1+" "+b2);
        boolean b3=s1 instanceof String;
        System.out.println(b3);

        System.out.println("===============");
        Person p=new Student();
        boolean p1=p instanceof Person;
        boolean p2=p instanceof Object;
        System.out.println(p1+" "+p2);


true true
false
===============
true true

类型转换

  1. 父类引用指向子类的对象
  2. 把子类转换为父类 : 向上转型
  3. 把父类转换为子类 : 向下转型—强制转换
  4. 方便方法的调用 , 减少代码的重复
public class Application {
    public static void main(String[] args) {
        //高                     低
        //将 obj 转换为 Student 类型 , 就能使用 Student 独有的方法
        Person obj = new Student();
        //obj.sleep();
        Student student=(Student)obj;
        student.sleep();
        student.eat();
        //想要用子类的方法 , 把它强转为子类就行了
        ((Student)obj).sleep();

        Person person=student;
        //子类转换为父类 , 可能会丢失自己的方法
        //person.sleep();
    }
}
============
public class Person {
    public void eat(){
        System.out.println("father eat");
    }
}
============
public class Student extends Person{
    @Override
    public void eat() {
        System.out.println("son eat");
    }
    public void sleep(){
        System.out.println("Student sleep");
    }
}

static关键字

public class Student extends Person{
    {   //赋初始值
        //匿名代码块 , 构造器之前 , 不能主动调用
        System.out.println("我是son匿名");
        // --2
    }
    static{
        //静态代码块 , 加载初始化数据
        //类一加载就执行 , 只执行一次
        System.out.println("我是son static");
        // --1
    }
    public Student(){
        System.out.println("我是son构造");
        // --3
    }
}
===============
public class Person {
    {
        System.out.println("我是father匿名");
    }
    static{
        System.out.println("我是father static");
    }
    public Person(){
        System.out.println("我是father构造");
    }
}
===============
public class Application {
    public static void sleep(){

    }
    public void run(){
        sleep(); //非静态方法能调用静态方法或非静态
    }

    public static void main(String[] args) {
        // run(); static static方法只能调用static修饰的方法或变量
        sleep();
        Student s1=new Student();
        System.out.println("------------");
        Student s2=new Student();
        System.out.println("------------");
        System.out.println(random());
        System.out.println(PI);

    }
}

扩展 :

静态导入包

import static java.lang.Math.random;import static java.lang.Math.PI;System.out.println(random());System.out.println(PI);

顺序⭐⭐⭐⭐⭐⭐:

我是father static
我是son static
我是father匿名
我是father构造
我是son匿名
我是son构造

父类static块>子类static块>父类匿名块>父类构造>子类匿名块>子类构造

抽象类

  1. 不能new出实例 , 只能靠子类去实现它 , 约束
  2. 抽象类可以写普通方法 , 抽象类可以有构造器
  3. 抽象方法必须在抽象类中
public abstract class Animal {
    //所有的抽象方法在子类中都要重写,除非~
    public abstract void run();
    public Animal(){
        System.out.println("我存在");
    }
}
==============
public class Dog extends Animal{
    //如果子类也是抽象的 , 则可以不用重写父类的抽象方法
    @Override
    public void run() {

    }
}

接口

面向接口编程

接口就是一种规范 , 定义的是一组规则

接口作用:

  1. 一个约束
  2. 定义一些方法 , 让不同的人实现
  3. 方法都是 public abstract
  4. 变量都是 public static final
  5. 接口不能被实例化 , 接口没有构造方法
  6. 接口可以实现多个
  7. 实现接口必须要重写接口的方法

内部类

一个类中定义一个类

  • 成员内部类
public class Application {
    public static void main(String[] args) {
        Outer outer=new Outer();
        //Outer.Inner inner=new Outer().new Inner();
        Outer.Inner inner=outer.new Inner();
        System.out.println(inner.getAge());
        inner.inner();
    }
}
===============
public class Outer {
    private int age=20;
    public void outer(){
        System.out.println("我是外部类");
    }
    public class Inner{
        public void inner(){
            outer();
            System.out.println("我是内部类");
        }
        public int getAge(){
            return age;
        }
    }
}

  • 静态内部类
public class Outer {
    private int age=20;
    public void outer(){
        System.out.println("我是外部类");
    }
    public static class Inner{
        public void inner(){
            System.out.println("我是内部类");
        }
    }
}
  • 局部内部类
public class Application {
    public static void main(String[] args) {
        class Inner{
            public void inner(){
                System.out.println("局部内部类");
            }
        }
    }
}
  • 匿名内部类
public class Application {
    public static void main(String[] args) {
        new Apple().eat();
    }
}
class Apple{
    void eat(){}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值