01JavaSE_04面向对象

1. 初识面向对象

1.1 面向过程VS面向对象

面向过程思想

​ 步骤清晰简单,第一步做什么,第二步做什么…;

​ 面向过程适合处理较为简单的问题;

面向对象思想

​ 物以类聚,分类的思维模式,思考问题首先会考虑解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索;

​ 面向对象适合处理复杂问题,适合处理需要多人协作的问题

对于复杂的事物,为了从宏观上把握,从整体上合理分析,需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路区处理

1.2 面向对象编程

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

抽象:抽取共性,归类

三大特征:封装、继承、多态

从认识论角度考虑是先有对象后有类;对象是具体的事物,类是抽象的,对对象的抽象

从代码运行角度考虑是先有类后有对象,类是对象的模板

2. 方法回顾和加深

2.1 方法的定义

修饰符:public/protected/private,static

返回类型:类型或void,void也可以有return;

break和return的区别:break跳出switch,结束循环(continue:结束一次循环);return结束方法,返回一个结果,也可能为空;

方法名:注意规范,驼峰命名、见名知意;

参数列表:参数类型 参数名,可变长参数;

异常抛出:throws;

//方法的定义实例:D01MethodDef.java
import java.io.IOException;
public class D01MethodDef {
    public static void main(String[] args) {

    }
    /*
    修饰符 返回值类型 方法名(形参,...) throws Exception,...{
        //方法体
        return 返回值;
    }
     */
    public String sayHello(){
        return "Hello World!";
    }
    public int add(int a,int b){
        return a>b?a:b; //三元运算符
    }
    public void print(){
        return; //可写可不写
    }
    public void readFile(String file) throws IOException{
        
    }
}

2.2 方法的调用,递归

静态方法:static修饰的方法,通过类名.方法名调用;和类一起加载的;

非静态方法:没有static修饰的方法,先创建对象,通过对象.方法名调用;类实例化之后才存在;

形参和实参:实际参数和形式参数的类型要一一对应,方法定义中的参数是形参,调用方法中的参数是实参;

值传递和引用传递:java是值传递;引用传递是传递一个对象,本质也是值传递;

this关键字:代表当前类或当前对象

非静态方法可以调用静态方法,同类方法可调用

//方法调用实例:D02MethodCall.java
public class D02MethodCall {
    public static void main(String[] args) {
        System.out.println("---调用学生类的静态方法和非静态方法---");
        Student.methodStudStatic(); //通过 类.方法 调用静态方法
        new Student().methodStud(); //先创建对象,再调用非静态方法
        new D02MethodCall().method();
    }
    //非静态方法,无参无返回值
    public void method() {
        System.out.println("---调用静态方法和非静态方法---");
        System.out.println("调用有返回值的静态方法: "+methodStatic());
        methodString("string");
    }
    //静态方法,有返回值
    public static String methodStatic() {
        return "静态方法:说话了";
        //say();  错误:静态方法不能直接调用非静态方法
    }
    //非静态方法,有参数
    void methodString(String str) {
        System.out.println("实际参数是:"+str);
    }
}
//学生类
class Student{
    public void methodStud(){
        System.out.println("我是:学生类非静态方法!");
    }
    public static void methodStudStatic(){
        System.out.println("我是:学生类静态方法!");
    }
}
/* 1个java文件中只能有1个public类和隐含类型类
public class Person(){
    
}
protected class Man(){
    
}
private class Woman(){
    
}
 */
//值传递VS引用传递 实例:D03MethodTransmit.java
public class D03MethodTransmit {
    public static void main(String[] args) {
        System.out.println("---值传递-----------------");
        int a=1;
        System.out.println("初始值a为:"+a); // a=1
        change(a);
        System.out.println("调用后a为:"+a); // a=1

        System.out.println("---引用传递----------------");
        Person person=new Person();
        System.out.println("缺省值为:"+person.name); // null
        D03MethodTransmit.change(person);
        System.out.println("修改后为:"+person.name); // TOM
    }
    //返回值为空
    public static void change(int a){
        a=10;
    }
    public static void change(Person person){
        person.name="TOM";
    }
}

class Person{
    String name;
}

3. 类与对象

3.1 类与对象的关系

类:是一种抽象的数据类型,它是对某一类事物整体(特点和行为)描述/定义,但并不代表某个具体的事物;

​ 动物、手机、电脑…

​ Person类,Pet类,Car类…

对象:是抽象概念的具体实例

​ 张三、小花、辽宁号航母…

​ 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念

类是模具,对象是某个产品

3.2 创建对象

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

类中的构造器:也称为构造方法,是在创建对象时必须要调用的;并且构造有两个特点:必须和类的名字相同,必须没有返回值类型且不能写void;

//类与对象实例:D03ClassObject.java
public class D03ClassObject {
    public static void main(String[] args) {
        //类-->对象:抽象的,实例化
        Stud stud1=new Stud();
        Stud stud2=new Stud();
        //给对象属性赋值
        stud1.name="Tom";
        stud1.age=10;
        System.out.println("学生"+ stud1.name+"年龄是:"+stud1.age);
        System.out.println("默认"+stud2.name+"年龄是:"+stud2.age);
        //变量改变
        stud1.SUBJECT="Chinese"; //静态变量的值可以改变?
        System.out.println("stud1公共课程是:"+stud1.SUBJECT);
        Stud.SUBJECT="English"; //?
        System.out.println("Stud公共课程是:"+Stud.SUBJECT);
        //Stud.name="Name"; 非静态变量不能通过 类.属性 访问
    }
}
class Stud{
    //全局变量,属性,字段
    String name;
    int age;
    //类变量、静态变量
    public static String SUBJECT="Math";
    static int NUM;
    static int NUMBER=10;
    //方法
    public void eat(){
        System.out.println(this.name+" 学习");
        //Stud.name="A"; 非静态变量不能通过 类.属性 访问
        name="A";
        this.name="B"; //this. 可以不要
        SUBJECT="Music"; //可以改变静态变量?
        NUMBER=20;
    }
}

3.3 构造器

特点:方法名称与类名相同,没有返回值且不要void;

作用:new调用构造方法创建对象,初始化对象的值;

注意点:定义了有参构造,就必须显式的定义无参构造

【提示】alt+insert 生成构造方法

​ this.name=name; this指本类或本方法

//构造器实例:D05Constructor.java
public class D05Constructor {
    public static void main(String[] args) {
        Teacher teacher1=new Teacher();
        Teacher teacher2=new Teacher("Rose");
        System.out.println("无参构造器: "+teacher1.name);
        System.out.println("有参构造器: "+teacher2.name);
    }
}
class Teacher{
    String name;
    int age;
    //无参构造器
    public Teacher(){
        this.name="Tom";
        age=20;
    }
    //有参构造:一旦定义了有参构造,就必须显式的定义无参构造(方法重载)
    public Teacher(String name) {
        this.name = "Rose";
    }
}

3.4 创建对象内存分析

4. 面向对象三大特征

4.1 封装(Encapsulation)

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

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

属性私有,get/set

提高程序的安全性,保护数据

隐藏代码的实现细节

统一接口

增加系统可维护性

//封装实例:D06Encapsulation.java
public class D06Encapsulation {
    public static void main(String[] args) {
        Driver driver=new Driver();
        //driver.name="Rose"; 私有属性,无法直接访问,即封装的思想
        driver.setName("Tom");
        System.out.println(driver.getName());
        driver.setAge(10);//不合法
        System.out.println("dirver的年龄为缺省值:"+driver.getAge());
    }
}
class Driver{
    //属性私有
    private String name;
    private int age;
    //alt+insert快捷键插入方法
    //方法公有
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        //加入细节处理
        if (age>70 | age<18){
            System.out.println("不合法");//快捷输入 "不合法".sout
        }else {
            this.age = age;
        }
    }
    //自定义方法
    public void drive(){

    }
}

4.2 继承(Inheritance)

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模

extends 子类(派生类)是父类(基类)的扩展:子类 extends 父类

java中类只有单继承,没有多继承

私有的属性、方法无法被继承

继承是类与类之间的一种关系,除此之外,类与类之间还有依赖、组合、聚合等关系;

子类和父类之间,从意义上讲应该具有“is a”的关系,子类 is a 父类

【快捷键】ctr+h 打开继承关系视图

输出内容.sout 生成打印输出语句

**Object类 ** java中所有类都默认继承object类

super/this

1. 调用父类的构造方法,必须在子类构造器代码的第一行,默认调用父类的无参构造器;
2. 必须只能出现在子类的方法或构造方法中;
3. super和this不能同时调用构造方法;

this

代表的对象不同,this本身调用者这个对象;super代表父类对象的引用;

前提:this没有继承也可以使用,super只能在继承的条件才可以使用

构造方法:this()本类的构造方法,super()父类的构造方法

方法重写 和属性无关,子类重写父类方法,仅方法体不同

1. 方法名必须相同;
2. 参数列表必须相同;
3. 修饰符范围可以扩大public>protected>default>private;
4. 不能是静态方法?
5. 抛出的异常可以缩小

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

//继承实例:D07Inheritance.java
public class D07Inheritance {
    public static void main(String[] args) {
        PetDog petDog=new PetDog();
        petDog.print();
        petDog.showName("xDog");
    }
}
class Dog {
    public String name="dog";
    private void run(){
        System.out.println("Dog跑一段");
    }
    public void print(){
        System.out.println("Dog的print方法");
    }
}
//PetDog继承Dog
class PetDog extends Dog{
    public String name="petDog";
    private void play(){
        System.out.println("PetDog玩一会");
    }
    //重写print()
    public void print(){
        super.print();
        System.out.println("PetDog的print方法");
    }
    //this super使用
    public void showName(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
}

【快捷键】alt+insert 重写、重载、get/set…

4.3 多态(Polymorphism)

多态:同一个方法可以根据发送对象的不同而采取多种不同的行为方式;一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关心的类)。

动态编译:类型在程序编译时确定,提高程序的扩展性;

要点

1. 多态是方法的多态,属性没有多态
2. 有继承关系,子类重写父类的方法,类型可以转换,ClassCastException
3. 父类的引用指向子类对象;
4. static方法(属于类,不属于实例)、final常量、private不能重写,也就不能存在多态

instanceof和类型转换

instanceof:判断引用指向的对象是否是其本身的类或其父类

父类引用指向子类对象

子类转换为父类,向上转型

父类转换为子类,向下转型,强制转换

方便方法调用,减少重复代码

//多态实例:D08Polymorphism.java
public class D08Polymorphism {
    public static void main(String[] args) {
        A x=new B();
        x.a();
        ((B) x).b();//强制转换
        A a=x;
        a.a();
        A y=new A();
        System.out.println(x instanceof B);
        System.out.println(x instanceof A);
        System.out.println(x instanceof Object);
        System.out.println(y instanceof B);
    }
}
class A{
    public void a(){
        System.out.println("A的Print方法");
    }
}
class B extends A{
    public void b(){
        System.out.println("B的Print方法");
    }
}

4.4 static

静态方法,静态属性,静态块,静态导入包

//static实例:D09Static.java
import static java.lang.Math.random; //静态导入包
import static java.lang.Math.PI;
public class D09Static {
    private static int age;
    private double score;
    //非静态方法:可通过类.调用静态方法
    public void run(){
        go();
    }
    //静态方法:不能直接或通过类.调用非静态方法,必须通过对象.调用
    public static void go(){
        //run();
    }
    //静态代码块:用于初始化属性,或建立共性工具
    static {
        age=10;
    }
    public static void main(String[] args) {
        D09Static stud1=new D09Static();
        System.out.println(D09Static.age);
        //System.out.println(D09Static.score);
        System.out.println("stud1.age");
        System.out.println("stud1.score");
        //run();
        stud1.run();
        go();
    }
}

5. 抽象类和接口

5.1 抽象类

  1. abstract修饰符用来修饰方法或类;抽象方法,抽象类;

  2. 抽象类中可以没有抽象方法,但有抽象方法的类一定要声明为抽象类

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

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

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

//abstract实例:D10Abstract.java
public class D10Abstract {
    public static void main(String[] args) {

    }
}
//抽象类
abstract class Father {
    public abstract void run(); //抽象方法
    public void work(){
    }
}
class Son extends Father{
    public Son() {
        super();
    }
    @Override
    public void run() { //非抽象类必须实现父类的抽象方法

    }    
}

5.2 接口

接口:只有规范!自己无法写方法——专业的约束!约束与实现分离,面向接口编程;

抽象类:具体实现和规范(抽象方法)都有

普通类:只有具体实现

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…,则必须能…”的思想;

接口的本质是契约,就像法律一样,制定好后,大家都遵守;

OO的精髓,是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++,java,C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象

【提示】声明接口的方式是 interface,实现是 implements,可以实现多个接口,用,分开;

接口的作用

  1. 约束
  2. 定义一些方法,让不同的人以不同的方式实现
  3. 接口中的属性都是 public abstract final
  4. 接口中的方法都是 public abstract
  5. 接口不能实例化,接口没有构造方法
  6. implements可以实现多个接口
  7. 实现接口必须要重写其方法
//接口实例:D11Interface.java
public class D11Interface {

}
//接口
interface UserService{
    //接口中所定义的属性都是常量 public static final
    int AGE=20;
    //接口中所有定义的方法,都是抽象的 public abstract
    void add(String name);
    void delete(String name);
}
interface TimeService{

}
//实现接口必须实现方法
class UserServiceImpl implements UserService,TimeService{
    @Override
    public void add(String name) {

    }
    @Override
    public void delete(String name) {

    }
}

6. 内部类及OOP实战

内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类就是A类的内部类,而A类就是外部类了;

成员内部类、局部内部类、静态内部类、匿名内部类

//内部类实例:D12InnerClass.java
public class D12InnerClass {
    public static void main(String[] args) {
        //通过外部内实例化内部类对象,访问属性
        Outer outer=new Outer();
        Outer.Inner inner=outer.new Inner();
        inner.in();
        inner.getID();
        //没有名字初始化类,不用将实例保存到变量中
        new Outer().out();
        //匿名内部类
        new UserService(){
            @Override
            public void add(String name) {

            }
            @Override
            public void delete(String name) {

            }
        };
    }
}
class Outer{
    private int id;
    public void out(){
        System.out.println("out方法");
    }
    //成员内部类
    class Inner{
        public void in(){
            System.out.println("in方法");
            //局部内部类
            class InnerM{

            }
        }
        //获得外部类的私有属性
        public void getID(){
            System.out.println(id);
            out();
        }
    }
    //静态内部类
    static class InnerS{

    }
}
posted @ 2022-03-17 19:20  老李学Java  阅读(50)  评论(0)    收藏  举报