java面向对象

面向对象

  1. java语言属于面向对象的语言

  2. 面向对象本身不是一门具体的技术,符合人类思维的思想.

  3. 宗旨:把一个复杂的大型的业务,利用面向对象的思想进行面向对象的分析,

    接着面向对象的设计,最终进行面向对象的编程.

  4. 对象是数据在内存中的”载体”

重新认识类和对象

  1. 类是抽象的概念,对象是具体的概念

  2. 类是构建对象的蓝图/模板,对象是类的具体的实例化[表现]

  3. 类是用来描述对象的.

  4. 比如:

    类:水果 交通工具 学生

    对象:榴莲 飞机 小三

比如:

idusernameage
100jack18
101tom17

面向对象的思想

核心:”一切皆对象”

①分析出系统中业务的关键对象 - “找对象” - 未来页面上显示的数据

②找出对象的**”属性”** - “对象拥有什么”

③分析出对象的”方法” - “对象可以干什么,对象的功能”

④找出对象与对象之间的关系.

1:1 - 一个丈夫对应一个妻子,一个妻子对应一个丈夫.

1:N - 一个客户拥有多个订单.一个订单只能属于一个客户 - 70%

N:N - 一个学生可以选择多门课程,一门课程可以被多个学生来选择.

自关联 - 自己关联自己.

⑤最后一步才会去考虑具体怎么编码实现.可能也会考虑数据结构或者算法.

“相亲业务” -

  1. 媒婆帮你找一个”对象”
  2. 你要查看”对象”的属性
  3. 询问”对象”的功能
  4. 分析你和”对象”是否来电
  5. 考虑 - 追 - 彩礼 - 结婚 - 具体怎么实现!

面向过程的思想

C是典型的面向过程的思想

①优先考虑的就是算法和数据结构 - 考虑的就是具体怎么实现.

实体类

实体类就是用来描述对象的.

实体类中包含属性,构造方法,getter/setter方法,toString方法.

如何定义属性

语法:

修饰符 数据类型 属性名 [=初始值];

修饰符

public 公开的

private 私有的

数据类型

  1. 八种基本数据类型
  2. 内置对象类型以及自定义对象类型.

属性名

参考变量的命名 - “小驼峰”

三大特征 - 封装性

封装 - Encapsulation - 屏蔽底层的细节,数据提供保护的机制

  1. 属性私有化

  2. 提供getter/setter方法

    setter方法 - set属性名[首字母变大写] - 推荐的命名规则

    setter方法这种设置值的好处

    2-1. setter方法中是可以进行参数有效性判断的.

    2-2. 业务需求改变了 - 属性名称改变了,使用到这个属性的具体的地方都要发生改变 - “可维护性”

    2-3. 并不是所有的属性的值都是通过那么太简单的计算得到的.

public class Orders{
    private int id;

    private double price;

    private int count;

    private double total;

    //getter/setter - 提供好了

    public double getTotal(){
        double result = this.price * this.count;
        return result;
    }

}

Orders o = new Orders();
o.setPrice(100.0);
o.setCount(10);

//o.setTotal(o.getPrice()*o.getCount());
System.out.println(o.getTotal());

2-4. 并不是所有的属性都需要对外进行公开的.

this关键字

  1. 作用1 - 当前对象,区分方法中参数和实体类中的定义的属性 - 当两者同名的时候.

  2. 调用当前实体类中已经存在的另外一个构造方法.

    2-1. this()调动空参

    2-2. this(参数1,参数2) - 带参构造

    2-3. this调用构造的语句一定要在构造体的首行

  3. this和super语句的区别

toString方法

  1. 当我们直接输出对象的时候,默认一定会去调用toString方法 - 如果这个对象是null,那么不会调用toString方法的
  2. 当自定义的实体类中没有手动提供toString方法,那么这个对象会自动去调用java.lang.Object类中的toString方法
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
  1. java.lang.Object - 它是所有的类的根类,基类,超类,父类.

    如果某个类没有明确指定它的父类,那么这个类默认会直接继承java.lang.Object类

    “User类是Object类的儿子” - 规定 - “子类可以调用父类中所有的公开的成员

  2. Object类中提供的toString方法只能用来返回对象的内存地址 - 不满足实际的打印需求

    所以需要在实体类中重新重写这个toString方法.

  3. 当子类User类一旦重写了toString方法之后,那么就会采取”就近原则”,直接调用自己重写

    之后的toString方法.

构造方法-constructor

作用:创建对象的时候调用构造方法,通过new关键字

可以在创建对象的同时进行赋值操作,赋值的方式只有1次,setter赋值,可以多次赋值

特点

  1. 当实体类中如果没有手动提供任何一个构造方法的时候,那么系统会自动分配一个

    空参构造.如果实体类中一旦手动提供了带参构造之后,那么系统将不会再分配一个空参构造了.

  2. 定义的时候,不需要返回类型的

public 类名([参数列表]){
    //构造体
}
  1. 构造允许重载的
  2. 实体类中推荐只用提供空参,全参

业务类和实体类合二为一

居然将业务方法放在了实体类中 - 违背了设计原则 - “单一职责原则”.不要给一个类增加太多的负担

实体类 - 主要是描述对象,数据在内存中的载体 - 注重的应该是数据的存储

业务类 - 存放的是业务方法 - 在于操作这些数据


员工类[编号id,姓名name,工资salary]

业务方法[crud增删改查]放在实体类中 - 【不合理的】

public class Emp{     
    private int id;

    private String name;

    private double salary;

    //一个上司拥有多个下属
    //一个下属对应一个上司

    //自关联
    private Emp[] emps;

    public Emp() {
    }

    public Emp(int id, String name, double salary, Emp[] emps) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.emps = emps;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Emp[] getEmps() {
        return emps;
    }

    public void setEmps(Emp[] emps) {
        this.emps = emps;
    }

    //给上司添加一个下属
    public void addEmp(Emp e){
        if (null!=emps){
            this.emps = Arrays.copyOf(emps,emps.length+1);
            emps[emps.length-1] = e;
        }else {
            System.out.println("你是一个员工,你没有资格添加!");
        }
    }
    //输出下属的个数
    public void printEmpCount(){
        if (null==emps){
            System.out.println("你是一个员工,怎么会有下属呢?你这不是扯蛋吗...");
        }else {
            System.out.println("您下属的个数为:" + emps.length);
        }
    }
    //输出某个上司所有的下属信息
    public void printEmp(){
        System.out.println("您下属的信息如下:");
        if(null!=emps && emps.length>0){
            System.out.println("下属信息如下: ");
            for (Emp emp : emps) {
                System.out.println("\t"+emp);
            }
        }else{
            System.out.println("\tsorry你是一个小员工,没有资格!");
        }
    }
}

//TestEmp.java
Emp boss = new Emp(1,"boss",100.0,new Emp[0]);

Emp e1 = new Emp(1,"boss",100.0,null);

业务类和实体类分开

业务方法应该专门抽取出来放到一个【业务类】中.

public class Emp {
    private int id;
    private String name;
    private double salary;
    private Emp[] emps;

    public Emp() {
    }

    public Emp(int id, String name, double salary, Emp[] emps) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.emps = emps;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Emp[] getEmps() {
        return emps;
    }

    public void setEmps(Emp[] emps) {
        this.emps = emps;
    }

    @Override
    public String toString() {
        return "Emp{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", salary=" + salary +
            ", emps=" + Arrays.toString(emps) +
            '}';
    }
}
public class EmpBiz {
    //将新的员工添加到boos的下属数组中
    public void addEmp(Emp boos,Emp e){
        Emp[] emps = boos.getEmps();
        if (null!=emps){
            emps = Arrays.copyOf(emps,emps.length+1);//扩容
            emps[emps.length-1] = e;
        }else {
            System.out.println("你没有资格!");
        }
        boos.setEmps(emps);   // 值 : 地址
    }

    public void printEmp(Emp boos){
        Emp[] emps =boos.getEmps();
        if (emps!=null && emps.length>0){
            System.out.println("您的下属信息如下:");
            for (Emp emp : emps) {
                System.out.println(emp);
            }
        }else {
            System.out.println("您是什么勾八,自己是一个员工,心里没点逼数吗?");
        }
    }
    //删除工资高于salary
    public void delBySalary(Emp boss,double salary){
        Emp[] emps = boss.getEmps();

        int count = 0;
        for (int i = 0; i < emps.length; i++) {  //统计薪资大于salary的数量
            if (emps[i].getSalary() > salary){
                count++;
            }
        }
        Emp[] temp = new Emp[emps.length-count];

        int index = 0;
        for (int i = 0; i < emps.length; i++) {
            if (emps[i].getSalary() < salary){
                temp[index++] = emps[i];
            }
        }
        boss.setEmps(temp);
    }
}

继承Inheritance

将多个具有共同特点的对象抽象出一个”父类”.

父类中存储的是各个子类共同的特点[属性]或者功能[方法]

继承的好处 - 提高了代码的复用性.使用多态的前提,为了代码的可拓展性.

继承的缺点 - 增加了类与类之间的关系.不太符合软件的设计原则”高内聚,低耦合”

——————低耦合 - 模块与模块之间/类与类之间的关系应该越弱越好 - 没有关系

——————高内聚 - 单个模块/类能够独立完成某个业务功能的能力比较强.

——————实际开发中,可以采用设计原则**”合成复用原则”** - 来替代继承的使用.

使用extends关键字来表示某个类继承某个父类

比如:

public class A{

}
public class B extends A{

}
BA的子类,AB的父类,基类,超类.
1. A的父类就是java.lang.Object - 当某个类如果没有明确指定它的父类是谁,那么这个类默认继承Object
2. 子类是可以访问到父类中所有的非私有的成员
3. java的类只支持单继承.一个类【只能继承一个父类】.避免出现网状结构,保证类的层次性.
   java中的接口是支持多重继承.一个【接口可以继承多个接口】.
4. 继承具有传播性.C extends B    B extends A
   C间接继承于A,C也是可以访问到A中的所有的非私有的成员
5. 不要滥用继承,前提B is A

super关键字

【必须只能放在构造方法的首行】

语法规则:一个构造方法第一行如果没有this(…);也没有显示的去调用super(…);

系统会默认调用super();

  1. 调用父类的构造

    在子类的构造中,如果没有出现任何的super语句.那么系统默认会给定super(); - 【调用父类的空参构造】

  2. 当在子类中调用了一个和父类中同名的成员的时候,需要通过super关键字来加以区分[强制调用父类中那个同名的成员]

    public class Animal {
        private String desc;
    
        public Animal() {
    
            System.out.println("====1====");
            this.desc = getDesc();
        }
    
        public String getDesc() {
            System.out.println("扰乱你,压根不会执行!");
            return "Animal";
        }
    
        public String toString() {
            return desc;
        }
    }
    
    
    public class Worf extends Animal {
        private String name;
        private double weight;
    
        public Worf(String name, double weight) {
            super();
            System.out.println("===3===");
    
            this.name = name;
            this.weight = weight;
        }
    
        public String getDesc() {
            System.out.println("===2===");
            return "Worf:" + name + "体重:" + weight;
        }
    
        public static void main(String[] args) {
            System.out.println(new Worf("羊", 10));
        }
        //结果:Worf:null体重:0.0
    }
    
    public class Super {
        int j = 10;
    
        public Super() {
            System.out.println("===1==");
            print();
            j = 20;
        }
    
        public void print() {
            System.out.println("没有关系");
            System.out.println(j);
        }
    }
    
    public class Sub extends Super {
        //子类的属性赋值时机等到父类走完!!!
        int j = 30;
    
        public Sub() {
            super();
            System.out.println(j);
            System.out.println("===3===");
            print();
            j = 40;
        }
        //子类重写了父类中的print方法,所以不会去调用父类
        public void print() {
            System.out.println("===2==4===");
            System.out.println(j);
        }
    
        public static void main(String[] args) {
            System.out.println(new Sub().j);
        }
        //结果:0 30 30 40
    }
    

多态 - polymorphism

对象有多种形态.发生前提是具有继承关系

相同的消息可能会送给多个不同的类别之对象,

而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作。

instanceof

进行类型的判断,只有为true的时候,才能够进行类型的转换[强制,向下]

如果没有进行类型的判断,随便进行了一个强制类型转换,可能会抛出java.lang.ClassCastException类型转换失败异常

三种场景应用

面向父类编程

  1. 对象的编译时类型写成父类,对象的运行时类型写成子类

    编译时类型 对象名 = new 运行时类型();

    对象的编译时类型决定了对象的访问能力 - “对象名只能访问到编译时类型中定义的成员”

    对象的运行时类型决定了对象的行为能力 - “子类中如果一旦重写了父类中的方法,那么运行期间调用的是子类重写之后的方法”

  2. 方法的参数类型写成父类,调用这个方法的时候,可以传入这个父类的任意一个子类对象

  3. 方法的返回类型写成父类,方法的返回结果可以是这个父类的任意一个子类对象 - “简单工厂设计模式”

final关键字

不可更改,不可变

  1. final修饰的变量/属性 - 不能够重新赋值
  2. final修饰的类 - 不能够被继承
  3. final修饰的方法不能够被重写.

修饰符

访问修饰符 - 决定了这个成员可以在哪里能够被访问.

所有包子类[可以不同,同包]同包本类
public 公共的,公开的
protected 受保护的×
默认的××
private 私有的×××

安全级别:private>默认的>protected>public

可见区域:public>protected>默认的>private

方法的重写

方法的重载和方法的重写有什么区别?

特点:

发生的前提是要有继承关系

  1. 重写有个特殊的场景 - 子类重写之后的方法的修饰符,返回类型,方法名,参数列表和父类中高度保持一致 - 重构
  2. 子类重写的方法的访问修饰符可以小于或者等于父类
  3. 方法名必须要一样.
  4. 子类重写的方法的返回类型可以小于[可以是父类方法的返回类型的子类类型]或者等于父类的那个方法
  5. 参数列表必须要高度保持一致
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值