Day 10~21 面向对象 简述

面向对象

一、初识面向对象

面向过程思想:

  • 步骤清晰简单,线性过程,第一步做什么,第二步做什么…
  • 面向过程适合处理一些简单的问题

面向对象思想:

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独的思考。最后,才对某个分类下的细节进行面向过程的思索。
  • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题!

面向对象的本质:以类的方式组织代码,以对象的组织封装数据。

面向对象是抽象的。面向对象的三大特征:封装、继承、多态

二、方法回顾和加深

1、方法的定义

  • 修饰符

  • 返回类型

  • break:跳出 switch,结束循环和return的区别

  • 方法名:注意规范,见名知意

  • 参数列表:(参数类型,参数名)…

  • 异常抛出:疑问 (后面详解)

    代码举例演示:

package oop.demo01;

public class Demo01 {
    public static void main(String[] args) {

    }
    /*
    修饰符 返回值类型 方法名(...){
    //方法体
    return 返回值;
    }
     */
    //return 结束方法,返回一个结果!
    public String sayHello(){
        return "hello,world";
    }
    public void print(){
        return;
    }
    public int max(int a,int b){
        return a>b ? a : b;//三元运算符!
    }
}

2、方法的调用

①静态方法与非静态方法

代码演示:

package oop.demo01;

public class Demo02 {
    public static void main(String[] args) {

        //静态方法 static
        //调用方式:类名.方法名
        Student.say1();
        //非静态方法
        /*
        调用方式:
        实例化这个类  new
        对象类型 对象名 = 对象值;
        */
        Student student = new Student();
        student.say2();
    }
    
    package oop.demo01;

//学生类
public class Student {

    //方法1.静态方法
    public static void say1(){
        System.out.println("学生说话了");
    }

    //方法2.非静态方法
    public void say2(){
        System.out.println("学生真的说话了");
    }
  }
}

结果输出:在这里插入图片描述

②形参和实参

代码演示:

package oop.demo01;

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

        System.out.println(add);
    }


    //回顾形式参数与实例参数
    public static int add(int a,int b){  //这里的a、b为形式参数
        return a+b;
    }
}

结果输出:在这里插入图片描述

③值传递和引用传递

代码演示1.

package oop.demo01;
//值传递
public class Demo04 {
    public static void main(String[] args) {
        int a = 1 ;

        System.out.println(a); //1

        Demo04.change(a);

        System.out.println(a); //1
    }
//返回值为空
    public static void change(int a){
        a = 10 ;
    }
}

结果输出:在这里插入图片描述

代码演示2.

package oop.demo01;
//引用传递:对象,本质还是值传递
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;
}

结果输出:在这里插入图片描述

④this关键字

三、对象创建分析

1、使用new关键字创建对象

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

代码演示:

package oop.demo02;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {

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

        Student xiaoming = new Student();
        Student xh = new Student();

        xiaoming.name="小明";
        xiaoming.age=3;

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

        xh.name="小红";
        xh.age=31;


        System.out.println(xh.name);
        System.out.println(xh.age);
    }
}
package oop.demo02;
//学生类
public class Student {

    //属性:字段
    String name;  //null
    int age;      //0

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

结果演示:在这里插入图片描述

类中的构造器也称构造方法,是进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void

构造器必须掌握

代码演示:

package oop.demo02;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {

        //快捷键:new 类名 后按alt + enter
        //实例化了一个对象
        Person person = new Person("lizhongxin",2);

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

    }
}
package oop.demo02;

public class Person {

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

    String name;
    int age ;

    //实例化初始值
    //1.使用new关键字,本质是在调用构造器
    //2.用来初始化值
    public Person(){
    }

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

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //快捷键 alt+insert 点击OK为有参 点击selectno为无参
    //注意:定义有参构造之后,如果想要使用无参构造,显示的定义一个无参的构造
}

结果输出:在这里插入图片描述

2、创建对象内存分析

在这里插入图片描述

程序演示:

package oop.demo02;

import oop.demo03.Pet;

//一个项目应该只存在一个main方法
public class Application {
    public static void main(String[] args) {

        Pet dog = new Pet();

        dog.name = "旺财";
        dog.age = 3 ;
        dog.shout();

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

        Pet cat = new Pet();

        cat.name = "猫猫";
        cat.age = 4;
        cat.shout();

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

    }
}
package oop.demo03;

public class Pet {
    public String name ;
    public  int age ;

    //无参构造
    public void shout(){
        System.out.println("叫了一声");
    }
}

结果输出:在这里插入图片描述

四、面向对象三大特征

1、封装
  • 该露的露,该藏的藏

我们程序设计要追求**“高内聚,低耦合”**。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

  • 封装(数据的隐藏)

通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

  • 记住这句话就够了:属性私有,get/set

代码演示:

package oop;

import oop.demo04.Student;

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

        Student s1 = new Student();
        s1.setName("小明");
        s1.setId(20180000);
        s1.setSex('男');
        System.out.println("姓名:"+s1.getName());
        System.out.println("学号:"+s1.getId());
        System.out.println("性别:"+s1.getSex());

        s1.setAge(999); //不合法的
        System.out.println("年龄:"+s1.getAge());
    }
}

package oop.demo04;
//封装
//类  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;
    }

    //快捷键:alt+insert  自动生成get/set方法


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age>120||age<0){
            this.age=3;
        }else{
            this.age = age;
        }

    }
}

/*
封装的好处
  1.提高程序的安全性,保护数据
  2.隐藏代码的实现细节
  3.统一接口
  4.系统可维护性增加
 */

结果输出:在这里插入图片描述

2、继承
①继承定义
  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
  • extends的意思是“扩展”。子类是父类的扩展。
  • Java中类只有单继承没有多继承!
  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
  • 子类和父类之间,从意义上讲应该具有“is a”的关系

代码演示:

package oop;

import oop.demo05.Person;
import oop.demo05.Student;

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

        Student student = new Student();
        student.say();

        System.out.println(student.getMoney());

    }
}

package oop.demo05;
//在Java中,所有的类都直接或者间接继承object
//Person 人 :父类
public class Person {

    //public
    //private
    //default  默认
    //private
    
    public String name="李忠鑫";

    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;
    }
}



package oop.demo05;
//Teacher is 人 :派生类 子类
public class Teacher extends Person{
}


package oop.demo05;
//Student is 人 :派生类,子类
//子类继承父类 ,就会继父类的全部的方法!
public class Student extends Person{
    //快捷键 ctrl+H  打开继承关系表
}

结果输出:在这里插入图片描述

②Super详解

代码演示1、

package oop;

import oop.demo05.Person;
import oop.demo05.Student;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("小明");
    }
}

package oop.demo05;
//Person 人 :父类
public class Person {
    protected String name = "kuangshen";
}

package oop.demo05;
//Student is 人 :派生类,子类
//子类继承父类 ,就会继父类的全部的方法!
public class Student extends Person{

    private String name = "qinjiang";
    public void test(String name){
        System.out.println(name);      //传递的参数 小明
        System.out.println(this.name); //当前类的定义,qinjiang
        System.out.println(super.name);//父类 kuangshen
    }
}

结果输出:在这里插入图片描述

代码演示2、

package oop;

import oop.demo05.Person;
import oop.demo05.Student;

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

        Student student = new Student();
        student.test1();

    }
}

package oop.demo05;
//Person 人 :父类
public class Person {

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

    protected String name = "kuangshen";

    //若改为private,变为私有,将无法被继承
    public void print(){
        System.out.println("Person");
    }
}

package oop.demo05;
//Student is 人 :派生类,子类
//子类继承父类 ,就会继父类的全部的方法!
public class Student extends Person{

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

    public void print(){
        System.out.println("Student");
    }
    public void test1(){
       print();      //Student
       this.print(); //Student
       super.print();//Person
    }
}

结果输出:在这里插入图片描述

super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中!
3.superthis不能同时调用构造方法!

对比this:
    代表对象不同:
       this:本身调用者这个对象
       super:代表父类对象的应用
    前提:
       this:没有继承也可以使用
       super:只能在继承条件下才可以使用
    构造方法的区别:
       this();本类的构造
       super();父类的构造!   
③方法重写
重写:需要有继承关系,子类重写父类的方法!
    1. 方法名必须相同
    2. 参数列表必须相同
    3. 修饰符:范围可以扩大但不能缩小 : Public>Protected>Default>Private
    4. 抛出的异常(后学):范围可以缩小但不能扩大:

重写,子类的方法和父类必须一致

为什么需要重写:
    1. 父类的功能,子类不一定需要,或者不一定满足!
    2. 快捷键 Alt+Insert: 选中override;  

代码演示:

package oop;

import oop.demo05.A;
import oop.demo05.B;

public class Application {

    //静态的方法和非静态的方法差别很大!
    //静态方法:法的调用只和左边,定义的数据类型有关
    //非静态:重写
    public static void main(String[] args) {

        //方法的调用只和左边,定义的数据类型有关
        A a = new A();
        a.test(); //A

        //父类的引用指向了子类
        B b = new A();//子类重写了父类的方法
        b.test(); //B

    }
}

package oop.demo05;
//注意:重写都是方法的重写,与属性无关
public class B {

    public  void test(){
        System.out.println("B=>test()");
    }

}
package oop.demo05;

//继承
public class A extends B {

    //override 重写
    @Override //注解:有功能的注释 后学
    public void test() {
        System.out.println("A=>test()");
    }
}

结果输出:在这里插入图片描述

3、多态
①多态定义
  • 即同一方法可以根据发送对象的不同而采用不同的行为方式。

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

  • 多态存在的条件:

​ 有继承关系

​ 子类重写父类的方法

​ 父类引用子类对象

  • 注意:多态是方法的多态 ,属性没有多态性
  • 关键词instanceof (类型转换) 引用类型
多态注意事项:
    1. 多态是方法的多态,属性没有多态
    2. 父类和子类,有联系  类型转换异常 ClassCastException!
    3. 存在条件: 继承关系 方法需要重写,父类引用指向子类对象!Father f1 = new son();
     不能被重写的方法:
        1. static方法  属于类,它不属于实例
        2. final 常量池
        3. private方法;私有不可重写     
package oop;

import oop.demo06.Person;
import oop.demo06.Student;

public class Application {

    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //new Student();
        //new Person();

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

        //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
        s2.run();//(重写前:子类继承了父类的全部方)。子类重写了父类的方法后,执行子类方法。
        s1.run();
        s1.eat();
        //思考?s2可以调用eat()方法吗?
        ((Student) s2).eat();//不可直接调用 idea会自动进行类型转换

    }
}
package oop.demo06;

public class Person {
    public void run(){
        System.out.println("run");
    }
}


package oop.demo06;

public class Student extends Person{
    @Override//重写父类的run()方法
    public void run() {
        System.out.println("son");
    }
    public void eat(){
        System.out.println("eat");
    }
}

结果输出:在这里插入图片描述

②instanceof和类型转换

判断一个对象是什么类型 ,判断两个类之间是否存在父子关系。

代码演示1、

package oop;

import oop.demo06.Person;
import oop.demo06.Student;
import oop.demo06.Teacher;

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

        //System.out.println(X instanceof Y);//能不能编译通过!取决于XY之间是否存在父子关系
        //Object > String
        //Object > Person > Teacher
        //Object > Person > Student
        Object object = new Student();
        System.out.println(object instanceof Student); //true
        System.out.println(object instanceof Person);  //true
        System.out.println(object instanceof Object);  //true
        System.out.println(object instanceof Teacher); //False
        System.out.println(object instanceof String);  //False
        System.out.println("===========分割线=============");
        Person person = new Student();
        System.out.println(person instanceof Student); //true
        System.out.println(person instanceof Person);  //true
        System.out.println(person instanceof Object);  //true
        System.out.println(person instanceof Teacher); //False
        //System.out.println(person instanceof String);  //编译报错!
        System.out.println("===========分割线=============");
        Student student = new Student();
        System.out.println(student instanceof Student); //true
        System.out.println(student instanceof Person);  //true
        System.out.println(student instanceof Object);  //true
        //System.out.println(student instanceof Teacher); //编译报错!
        //System.out.println(student instanceof String);  //编译报错!
    }
}
package oop.demo06;

public class Person {
    public void run(){
        System.out.println("run");
    }
}

package oop.demo06;

public class Teacher extends Person{

}
package oop.demo06;

public class Student extends Person{

}

运行结果:在这里插入图片描述

代码演示2、

package oop;

import oop.demo06.Person;
import oop.demo06.Student;

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

        //类型之间的转化:父  子
        //高                     低
        Person obj = new Student();//低转高 自动转。
        //obj.go(); //现在的obj是Person类,不能直接调用Student中的go()方法。需要类型转换
        Student student = (Student) obj;//高转低 强制转换
        student.go();//现在的student是Student类型,可以调用go()方法;
        //注意:子类转换为父类,可能丢失自己的一些方法
        
    }
}
/*
1.父类引用指向子类对象
2.把子类转换为父类 向上转型,自动转
3.把父类转换为子类,向下转换,强制转
4.方便方法的调用,减少重复代码  简洁
 */


package oop.demo06;

public class Person {
    public void run(){
        System.out.println("run");
    }
}

package oop.demo06;

public class Student extends Person{

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

运行结果:在这里插入图片描述

③补充:static关键字详解

代码演示:

package oop.demo07;
//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);


    }
}

代码演示2、

package oop.demo07;

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{
        //静态代码块
    }
 */

结果输出:在这里插入图片描述

代码演示3、

package oop.demo07;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }
}

运行结果:在这里插入图片描述

五、抽象类和接口

1、抽象类
  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

  • 抽象类中可以没有抽象方法,但是由抽象方法的类一定要声明为抽象类。

  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

package oop.demo08;
//abstract 抽象类;类  extends :单继承  。 (接口可以多继承)
public abstract class Action {

    //约束~有人帮我们实现
    //abstract,抽象方法,只有方法名字,没有方法的实现!
    public abstract void doSomething();

    //不能new这个抽象类,只能靠子类去实现它:约束!
    //抽象类中可以写普通方法,但抽象方法必须在抽象类中
    //抽象的抽象:约束
    //存在的意义: 抽象出共有属性 ,提高开发效率
}
package oop.demo08;
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法。除非子类也是抽象类。
public class A extends Action{

    @Override
    public void doSomething() {

    }
}
2、接口
  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。(如果你是汽车,则必须能跑)
  • 接口的本质是契约,就像我们人间的法律,制定好后大家都要遵守。
  • OO的精髓,是对对象的抽象,最能体现这一点的是接口。为什么我们讨论设计 模式都只针对具备了抽象能力的语言(如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

声明的关键字是class,声明接口的关键字是interface

作用:
    1. 约束
    2. 定义一些方法让不同的人实现
    3. 所有方法都默认是public abstract3
    4. 所有常量都默认是public static final
    5. 接口不能实例化,因为接口中没有构造方法
    6. implements可以实现多个接口
    7. 必须要重写接口中的方法   
package oop.demo09;

//抽象思维!!

//interface 定义的关键字,接口都需要有实现类
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 oop.demo09;

public interface TimeService {
    void timer();
}


package oop.demo09;
//抽象类:extends
//类 可以实现接口 implement
//实现接口的类,就需要重写接口中的方法

//从侧面实现了多继承  :利用接口
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() {

    }
}

六、内部类及OOP实践

1、内部类
  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对于B类来说就是外部类了。
    1. 成员内部类
    2. 静态内部类
    3. 局部内部类
    4. 匿名内部类

代码演示1、

package oop.demo10;

public class Outer {

    private int id = 20180;
    public void out(){
        System.out.println("这是外部类的方法");
    }
//  成员内部类
    public  class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //内部类可以获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
    }
}
package oop;

import oop.demo10.Outer;

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

        Outer outer = new Outer();
        outer.out();
        //通过这个外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getID();
    }
}

运行结果:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值