Java面向对象OPP

面向对象(OPP)

强调:所有的知识点都是结合代码理解,代码记录了学习的详细笔记,需要结合代码去深刻理解所需要学习的知识点!!!

1. 面向过程 & 面向对象

  • 面向过程思想
    • 步骤清晰简单,第一步做什么,第二步做什么……
    • 面对过程适合处理一些较为简单的问题
  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
  • 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

2. 什么是面向对象

本质

  • 以类的方式组织代码,以对象的方式组织(封装)数据。

三大特性

  • 封装

  • 继承

  • 多态

3. 方法的定义(回顾)

  • 修饰符
  • 返回值类型
  • 方法名
    • 注意规范:首字母小写、驼峰原则
    • 见名知意
  • 参数列表:(参数类型 参数名,…)
  • 异常抛出
  • break 和 return 的区别
    • break:跳出Switch,结束循环
    • return:结束方法,返回一个结果,可以为空

4. 方法的调用(回顾)

  • 静态方法

    public static void a(){}
    
  • 非静态方法

    public void a(){}
    
  • 形式参数和实际参数

  • 值传递和引用传递

  • this关键字

代码

import java.io.IOException;

//Demo01 类
public class Demo01 {

    //Main 方法
    public static void main(String[] args) {

    }
    /*
    修饰符 返回值类型 方法名(....){
       //方法体
       return 返回值;
    }
    */

    //return 结束方法,返回一个结果  可以为空
    public String sayHello(){
        return "hello,world";
    }

    //int a ,int b 形式参数
    public int max(int a,int b){
        return a>b ? a : b; //三元运算符
    }

    //数组下标越界:Arrayindexoutofbounds
    // 抛出异常
    public void readFile(String file) throws IOException{

    }
}
public class Demo02 {

    //静态方法 static

    //非静态方法

    public static void main(String[] args) {

        //使用Student类中的非静态方法
        //需要实例化这个类 new
        //对象类型 对象名 = 对象值
        Student student = new Student();
        student.say();
    }

    // 和类一起加载的   先
    public static void a(){

    }
    //类实例化之后才存在 后
    public void b(){

    }
}
//学生类
public class Student {

    //非静态方法
    public void say(){
        System.out.println("学生说话了");
    }
}
public class Demo03 {

    public static void main(String[] args) {
        //实际参数和形式参数的类型要对应!
        int add = Demo03.add(1,2);
        System.out.println(add);
    }

    public static int add(int a,int b){
        return a+b;
    }
}
//值传递
public class Demo04 {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);

        Demo04.change(a);
        System.out.println(a); //1
    }
    // 返回值为空
    public static void change(int a){
        a = 10;
    }
}
//引用传递: 对象,本质还是值传递
public class Demo05 {
    public static void main(String[] args) {
        Person person = new Person();

        System.out.println(person.name); //null

        Demo05.change(person);

        System.out.println(person.name);//王
    }

    public static void change(Person person){
        // person是一个对象 指向 --->Person person = new Person();这是一个具体的人,可以改变属性
        person.name = "王";
    }
}

//定义了一个Person类 有一个属性:name
class Person{
    String name;
}

5.类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
    • 动物、植物、手机、电脑…
    • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
  • 对象是抽象概念的具体实例
    • 张三就是人的一个具体实例
    • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念

6.类与对象的创建

创建与初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

  • 类中的构造器也称为构造方法,是在进行创建对象时必须要调用的,并且构造器有一下俩个特点:

    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
  • 构造器必须要掌握!!!

代码
//一个项目应该只存在一个main方法
public class Application {
    
}
//学生类
public class Student {
    //属性 : 字段
    String name; // null
    int age; // 0

    //方法
    public void study(){
        System.out.println(this.name + "在学习");
    }
}

/*
    public static void main(String[] args) {

        //类:抽象的,需要实例化
        //类实例化后会返回一个自己的对象
        //student对象就是一个Student类的具体实例!
        Student student = new Student();
        Student xiaowang = new Student();

        xiaowang.name = "小王";
        xiaowang.age = 18;

        System.out.println(xiaowang.name);
        System.out.println(xiaowang.age);

        System.out.println(student.name);
        System.out.println(student.age);
    }
 */
//java文件 --编译--> class文件
public class Person {

    //一个类即使什么都不写,它也会存在一个方法
    //显示的定义构造器

    String name;
    int age;

    //实例化初始值
    //1.使用new关键字,必须要有构造器 本质是在调用构造器
    //2.用来初始化值
    public Person(){ //无参构造 默认的构造器
    }

    //有参构造 一旦定义了有参构造,无参构造就必须显式定义
    public Person(String name){//重载
        this.name = name;
    }

    //alt + insert 生成构造器


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

/*
    public static void main(String[] args) {

        //new 实例化了一个对象
        Person person = new Person("hahah");
        System.out.println(person.name);
    }

    构造器:
        1.和类名相同
        2.没有返回值
    作用:
        1.new 本质在调用方法
        2.初始化对象的值
    注意点:
        1.定义有参构造之后,如果向使用无参构造,现实的定义一个无参的构造

        Alt + Insert --> Constructor

        this.  =
 */

创建对象内存分析

image-20210805161003899

代码
public class Application {
    public static void main(String[] args) {

        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 21;
        dog.shout();

        System.out.println(dog.name);
        System.out.println(dog.age);

        Pet cat = new Pet();
    }
}
public class Pet {
    //属性 成员变量
    /*
    默认初始化
        数字:0  0.0
        char:u0000
        boolean:false
        引用类型:null
     */
    //属性的定义  修饰符 属性类型 属性名 = 属性值
    public String name;
    public int age;

    //有无参构造

    public void shout(){
        System.out.println("叫了一声");
    }
}

7. 封装

  • 该露的露,该藏的藏
    • 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
  • 封装(数据的隐藏)
    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
  • 记住这句话就够了: 属性私有 get/set

代码

public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();

        s1.setName("王");

        System.out.println(s1.getName());

        s1.setAge(999);//不合法的
        System.out.println(s1.getAge());
    }
}
//类  private 私有
public class Student {
    
    //属性 :名字 学号 性别
    private String name;
    private int id;
    private char sex;
    private int age;

    //提供一些可以操作这个属性的方法!
    //提供一些public的get、set方法

    //get 获得这个数据

    public String getName() {
        return this.name;
    }
    //set 给这个属性设置值
    public void setName(String name){
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age>120||age<0){//安全性验证判断 合理
            this.age = 3;
        }else{
            this.age = age;
        }
    }
    //Alt + Insert --> Getter and Setter
}

意义

  • 提高程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一接口
  • 系统的可维护性增加了

继承

  • 继承是类和类之间的一种关系:子类(派生类)、父类(基类),除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • extends:“扩展”,子类是父类的扩展,子类和父类间从意义上讲应该具有" is a "的关系
  • JAVA中类只有单继承,没有多继承!:一个爸爸可以有很多儿子,一个儿子只有一个爸

Object类

在Java中,所有的类都默认直接或间接继承object类

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.say();
        System.out.println(student.getMoney());
    }
}
//Person 人 :基类,父类
//在Java中,所有的类都默认直接或间接继承object类
public class Person {

    //public  公共的
    //protected 受保护的
    //default 默认的,
    //private 私有的

    private int money = 10_0000_0000;

    public void say(){
        System.out.println("说了一句话");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
// Student is 人 :派生类,子类
//子类继承父类,就会拥有父类的全部方法
public class Student extends Person{
    //Ctrl + H
}
//Teacher is 人 :派生类,子类
public class Teacher extends Person{
}

super类★

  • super是调用父辈的构造方法,必须在构造方法的第一个

  • super必须只能出现在子类的方法或者构造方法中!

  • super 和 this 不能同时调用构造方法!

  • Vs this

    • 代表的对象不同
      • this :本身调用者这个对象
      • super:代表父类对象的应用
    • 前提
      • this:没有继承也可以使用
      • super:只能在继承条件才可以使用
    • 构造方法
      • this(); 本类的构造
      • super(); 父类的构造
public class Application {
    public static void main(String[] args) {
        Student student = new Student();

        //student.test("王中王");
        student.test1();
    }
}
public class Person {

    public Person() {
        System.out.println("Person无参执行了");
    }

    protected String name = "王王";

    //private 私有的东西无法被继承
    public void print(){
        System.out.println("Person");
    }
}
public class Student extends Person{

    public Student() {
        //隐藏代码:调用了父类的无参构造
        //super();调用父类的构造器,必须要在子类构造器的第一行
        System.out.println("Student无参执行了");
    }

    private String name = "王";

    public void print(){
        System.out.println("Student");
    }

    public void test1(){
        print(); //Student
        this.print();//Student
        super.print();//Person
    }

    public void test(String name){
        System.out.println(name); //王中王
        System.out.println(this.name);//王
        System.out.println(super.name);//王王
    }
}

方法重写★

  • 首先区别静态方法
  public class Application {
  
      public static void main(String[] args) {
          //方法的调用只跟左边:定义的数据类型有关
          A a = new A();
          a.test();//A=>test()
  
          //父类的引用指向了子类
          B b = new A();
          b.test();//B=>test()
      }
  }
//重写都是方法的重写,和属性无关
public class B {
    public static void test(){
        System.out.println("B=>test()");
    }
}
//A是子类  A继承了B
public class A extends B{
    public static void test(){
        System.out.println("A=>test()");
    }
}
  • 非静态方法
  public class Application {
  
      public static void main(String[] args) {
          //方法的调用只跟左边:定义的数据类型有关
          A a = new A();
          a.test();//A=>test()
  
          //父类的引用指向了子类
          B b = new A();
          b.test();//A=>test() 父类方法被重写
      }
  }
//重写都是方法的重写,和属性无关
public class B {
    public void test(){
        System.out.println("B=>test()");
    }
}
//A是子类  A继承了B
public class A extends B{
    //Override 重写  Alt + Insert --> Override
    @Override //注解:有功能的注释
    public void test() {
        System.out.println("A=>test()");
    }
}
  • 总结

    • 静态与非静态方法的区别很大

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

      • Alt + Insert --> Override

      • 方法名必须相同

      • 参数列表必须相同

      • 修饰符的范围可以扩大,不可以缩小

        • ↓public
        • Default
        • Protected
        • ↑private
      • 抛出的异常范围可以被缩小,不可以扩大

        • 例如Exception --> ClassNotFoundException
    • 所以重写子类的方法和父类的方法必须要一致,方法体不同

    • 为什么需要重写

      • 父类的功能,子类不一定需要或不一定满足
    • 不能被重写的方法

      • static方法:属于类,不属于实例
      • final 常量
      • private 私有方法

多态

  • 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式

  • 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)

  • 存在条件

    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意事项

    • 多态是方法的多态,与属性无关
    • 父类子类要有联系
    • 类型转换异常 -->ClassCastException
public class Application {
    public static void main(String[] args) {

        //Student 子类 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person 父类 可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        //对象能执行哪些方法,只要看对象左边的类型,和右边关系不大
        s2.run();//子类重写了父类的方法,执行子类的方法
        s1.run();
        ((Student)s2).eat();//强制转换
        
    }
}
public class Person {

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

instanceof & 类型转换

  • Person类
public class Person {

    public void run(){
        System.out.println("run");
    }
}
  • Student类
public class Student extends Person{
    public void go(){
        System.out.println("go");
    }
}
  • Teacher类
public class Teacher extends Person{

}
  • instanceof
    • 万能公式:System.out.println(x instanceof y);
    • 判断两个类是否有关系
public class Application {
print static void main(String args[]){
//        Object > String
//        Object > Person > Student
//        Object > Person > Teacher
        Object object = new Student();

        //System.out.println(x instanceof y);//能不能编译通过,判断是否有关系

        System.out.println(object instanceof Student);//ture
        System.out.println(object instanceof Person);//ture
        System.out.println(object instanceof Object);//ture
        System.out.println(object instanceof Teacher);//false
        System.out.println(object instanceof String);//false

        Person person = new Student();
        System.out.println(person instanceof Student);//ture
        System.out.println(person instanceof Person);//ture
        System.out.println(person instanceof Object);//ture
        System.out.println(person instanceof Teacher);//false
        //System.out.println(person instanceof String);//编译报错 person和String没有半毛钱关系
    }
}
  • 类型转换
    • 把子类转换为父类,向上转换
    • 把父类转换成子类,向下转换,强制转换
      • 可能丢失一些方法
    • 方便方法的调用,减少重复的代码
public class Application {
    public static void main(String[] args) {
        //类型之间的转换:父 子

        //高------------------低
        Person person = new Student();

        //student将这个对象转换成Student类型,我们就可以使用Student类型的方法了
        /*Student person1 = (Student)person;
        person1.go();*/
        ((Student)person).go();

        //子类转换为父类,可能丢失自己的本来一些方法
        Student student = new Student();
        student.go();

    }
}

Static:静态

  • 非静态方法可以调用静态方法,静态方法无法调用非静态方法
//Static :静态
public class Student {
    //静态变量
    private static int age;
    //非静态变量
    private double score;

    public void run(){}

    public static void go(){}

    public static void main(String[] args) {
        //j
        new Student().run();
        go();
        
        Student s1 = new Student();
        System.out.println(Student.age);
        //System.out.println(Student.score); 报错
        System.out.println(s1.score);
        System.out.println(s1.age);
    }
}
public class Person {
    {
        System.out.println("匿名代码块");//2.赋初始值
    }
    static {
        System.out.println("静态代码块");//1.只执行一次
    }

    public Person() {
        System.out.println("构造方法");//3.
    }

    public static void main(String[] args) {
        Person person = new Person();
        Person person1 = new Person();

    }
}
//静态导入包
import static java.lang.Math.random;
public class Test {

    public static void main(String[] args) {
        //random()返回一个随机数 静态导入包使Math.可省略
        System.out.println(Math.random());
    }
}

抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
//abstract 抽象类 类 extends:单继承 --> 接口多继承
public abstract class Action {
    //约束 有人帮我们实现
    //抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();

    /*
    特点
       1.不能new这个抽象类,只能靠子类去实现它:约束
       2.抽象类中可以写的方法
       3.抽象方法必须在抽象类中
     */
}
//抽象类的所有方法,继承了它的子类,都必须要实现他的方法,除非子类也是抽象类
public class A extends Action {
    @Override
    public void doSomething() {

    }
}
  • 总结
    • 有抽象方法的类必然是抽象类
    • 抽象类不可以被实例化,不能被new来实例化抽象类
    • 抽象类可以包含属性,方法,构造方法,但是构造方法不能用来new实例,只能被子类调用
    • 抽象类只能用来继承
    • 抽象类的抽象方法必须被子类继承
    • 意义
      • 为子类提供一个公共的类型
      • 封装子类中重复内容(成员变量和方法)
      • 定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的

接口

  • interface :接口
  //抽象的思维!!!
  //interface 定义的关键字  接口都需要有实现类
  public interface UserService {
      //接口中的所有定义的方法其实都是抽象的 public abstract
  
      //静态常量 public static final
      int AGE = 99;
  
      void add(String name);
      void delete(String name);
      void update(String name);
      void query(String name);
  }
public interface TimeService {
    void timer();
}
//一个类可以实现接口 implements 接口
//实现了接口的类,就需要重写接口的方法

//多继承 利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
    
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}
  • 作用
    • 定义一些方法,让不同的人实现
    • 接口中的方法会被隐式的指定为public abstract(只能是public abstract)
    • 接口的变量会被隐式的指定为public static final 变量(只能是public,用private修饰会报编译错误)
    • 接口不能被实例化,且接口中没有构造方法
    • 使用implements可以实现多个接口,在类声明中,Implements关键字放在class声明后面
    • 必须要重写接口中的方法

抽象类和接口的区别

  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

内部类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getID();
    }
}
public class Outer {
    private int id = 10;
    public void out(){
        System.out.println("外部类方法");
    }

    public class Inner{
        public void in(){
            System.out.println("内部类方法");
        }

        //可以获得外部类的私有属性,方法
        public void getID(){
            System.out.println(id);
        }
    }
}
//一个java类中可以有多个class类,但是只能有一个public class
public class Outer2 {
    //局部内部类
    public void method(){
        class Inner{
            public void in(){

            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();
        new UserService() {
            @Override
            public void hello() {

            }
        };
    }
}
class Apple{
    public void eat(){
        System.out.println("1");
    }
}

interface UserService{
    void hello();
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值