逸学java【初级菜鸟篇】7.面向对象编程(00P)

hi,我是逸尘,一起学java吧


目标(任务驱动)

 1.请熟练掌握面向对象的核心概念,三大特征。

场景:工作第五天,你的好友小张告诉你他在他们公司旁边的店里找到一个女朋友,这时你想想自己也不是没有对象呀,于是你打开了电脑,复习了JAVA面向对象的知识点。

2.请掌握包,内部类,抽象类,接口的知识点。

场景:你在复习JAVA面向对象的知识点时又回顾了这些内容。

对象是什么以及和类的关系

在早期开发我们结构的开发,规模越来越大,会出现很多问题,后来,我们结合对现实世界的理解然后建模,把单个物体对象,拿过来使用,也就是目标对象,进行一个开发。

比如日常生活中的草扫把,他就可以理解为一个对象,一个对象他有他自身的属性,比如,扫把有杆子作为支撑,还有下面用来扫地的高梁穗,还有他的颜色阿黄色,还有他的功能可以扫地。

对象有这些行为(功能)和属性的实例(确确实实存在的例子)。

那么如果说都有这样一个特性的泛指(都有这样的行为和属性的共通)那么我们可以统一称为类,比如说扫把类,那他的对象可可能还有塑料扫把,他们都有这样的特点,都有杆子,扫地功能,颜色属性,只不过具体内容不一样。

我们可以把类看出图纸,而对象成设计出来的实例。

也是说,对象是类抽象的实例

所以用这样的观点,万物皆对象。

你也是对象,华为手机也对象 ,中华田园犬也是对象。

类的创建和对象的创建

在前面的学习中我们知道类是什么,类的关键字是class,想要对象肯定先需要我们有一个类,在前面,我们多次创建类,但是没有具体的说明

在类中我们说都有这样那样的特性的泛指(都有这样的行为和属性的共通)

也就说类有他的属性,行为 

这些对象的属性(类的属性)我们用成员变量(全局变量)来表示

这些对象的行为(类的行为)用成员方法来表示

同时我们类还有特殊的方法 构造方法(构造函数),可以为我们可以创建对象,相当于造图纸

在我们类还需要权限修饰符来修饰

同时类除了上面内容之外,还有一些高级特性,比如包和内部类,我们稍后会讲解。

我们先创建一个动物类

package com.ydrj.xb;

public class Animal {
    //属性 成员变量
    private int age;
    private String name;
    //行为 成员方法
    public void call(){
        System.out.println("叫");
    }
    //特殊的方法  构造方法(构造函数),只要当没有构造函数时才默认,当有
    public Animal(){
    }
    //类的主方法,类的入口点
    public static void main(String[] args) {
    }

}

构造方法

和类同名,我们要创建的对象就是通过构造方法完成的。

需要注意的是

1.构造方法是没有返回值且不用void的

2.名称是和类名一样

3.默认可以不写,自动是无参构造,但是如果定义了非无参构造,那么无参构造还得从新自己写。

比如在一个类中 

很像救济房一样,如果说没有房子,会给房,但是如果有别墅,就不给,但是需要救济房你可以额外的购买(在这里就是自己去定义)

有了这个构造函数我们就可以通过它来创建对象。

权限修饰符

另外我们还有权限修饰符主要有private,public和protected以及默认

修饰符同类中同一个包中(子类和无关类)不同包(子类)不同包(无关类)
publicYYYY
protectedYYYN
默认YYNN
privateYNNN

public都可以,private只要同类可以,protected保护在一个包,默认同包同类。

类除了成员变量,成员方法之外,还有一些高级特性,比如包和内部类。

包的作用是在大量的类中管理好文件,比如可以解决类重名问题。 

Java API中提供了成千上万的类,肯定有重复的类名,这个时候我们解决办法就是在不同包下。

 我们的包

也是我们开头的,我们的写法(idea会自动创建)

补充:

在我们的IDEA是这样调整文件的

import是导入确定的包,然后就可以使用对应的类了

当发生冲突时,可以用包名+类去解决,同包优先且可以省去包名,但是如果先导入安装导入来算

比如我们自己的包下有有一个Sacanner类和java.util包下的Sacanner类冲突

对象的创建

对象是一类事物抽取的特例

我们依托于我们的构造方法创建对象

类名  对象名=new 构造函数();

类名和构造函数的内容是一样的

如何访问对象的信息

因为对象是一个实例,要拿出对象信息用

对象名.成员方法

对象名.成员变量

比如我们创建一个动物类,需要创建一只哈士奇

package com.ydrj.xb;


//实际开发建议一个文件只定义一个class
public class Animal {
    //属性 成员变量
    private int age;
    private String name;
    //行为 成员方法
    public void call(){
        System.out.println(name+"在叫");
    }
    //特殊的方法  构造方法(构造函数),只要当没有构造函数时才默认,当有
    public Animal(){

    }
    public Animal(String name,int age){
        this.age=age;
        this.name=name;
    }
    //类的主方法,类的入口点
    public static void main(String[] args) {
        //创建对象
        Animal dog = new Animal("哈士奇",1);
        System.out.println(dog.name);
        //调用对象的方法
        dog.call();
    }

}

this关键字

this代表的是本类当前的对象

如果在构造方法中参数和成员变量相同名称,那么可以用this.成员变量相同名称代表对象的成员变量

简单的说在构造方法和成员方法代表当前对象地址

可以用于指定访问当前对象成员

对象的内存机制

方法区的方法去引用堆内存的引用地址的内容

栈内存存放的是对象的堆内存地址(对象名是存的引用地址)

堆内存是new出来的东西并且会开辟地址

垃圾回收

注意:当堆内存中的对象,没有被任何变量引用(指向)时,就会被判定为内存中的“垃圾”

用户无需担心废弃的对象占用内存,我们在java中也提供了一个finalize()的方法,可以清楚那些不new操作出来的的对象,这里我们不过多探究。

面向对象三大特征

封装,继承,多态

封装

将对象的行为和属性进行隐藏起细节,保证了类内部的完整性,使用户不能轻易的操作,只能执行公允的数据,避免了外部操作对内部的影响。

如何进行封装更好
●一般建议对成员变量使用private(私有、隐藏)关键字修饰进(private修饰的成员只能在当前类中访问) 为每个成员变量提供配套public修饰的的getter,setter方法暴露 其取值和赋值。 

不对外暴露的私有的方法

单例模式

比如对成员变量使用private

 正确

package com.ydrj.xb;

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.setAge(12);
        System.out.println(student.getAge());
    }

}
package com.ydrj.xb;

public class Student {
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age>0&&age<150){
            this.age = age;
        }else {
            System.out.println("年龄异常");
        }

    }

    private int age;

}

JavaBean

那么我们也把分装数据的这个类叫JavaBean,也可以称为实体类。

继承

类与类之间有关联性,比如图形类和三角形类,这个就是继承的关联,继承是关联的一种,当然还有其他类与类的关联,这里就不过多赘述。

格式

修饰符 class 子类 extends 父类 {

}

使用继承的好处就是可以提高代码的复用性.

比如我们写程序员类的代码可以拿人类的属性和行为,我们只是在程序员类进行补充或者修改这样提高代码的复用性,提高开发效率,减少错误。

比如老板类和程序员类,他们都有很多相同的属性和方法,那么如果继承人类将会提高复用性

 使用继承

父类

 子类(减少很多重复代码)

内存分析

子类

父类

测试

注意点

Java只支持单继承,不支持多继承。也就是只有一个父亲,但是可以多层继承,子类A继承父类B,父类B可以继承父类C ,爷父孙关系。

子类不能继承父类构造方法,但是子类构造器默认先访问(调用)父类构造器,然后执行自己的构造器。

super

我们说子类构造器默认先访问(调用)父类构造器,然后执行自己的构造器。

那么他是怎么调用父类构造器的呢?

子类构造器的第一行语句默认都是: super() 不写也存在 

就是子类有参构造器会默认调用父类无参构造器,用super才可以继承对应的父类有参构造器

我们最好写有参构造器的同时把无参构造器也写出来,如果不写(父类无参构造器),子类中用super(...),手动调用父类的有参构造器。

父类 

子类

这样子类就可以于调用父类(超类)的构造函数。

除了调用父类(超类)的构造函数外

1.super还可以通过super.变量名就可以在子类中访问父类的成员变量

2.对于可继承的成员方法,如果子类在重写父类的方法同时想要调用(实现)与父类相同的方法,那么就用super.func(obj,obj,…)。

与构造函数不同的是,super.func()可以不用放在函数一开始的位置,而构造方法的super()必须放在函数体中最前面的位置。

方法重写

override

在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。 

重写的是父类的方法内容

重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。 

也有我们的快捷方式

 

package com.ydrj.xb;

//人类
public class People {
    private int age;
    private String name;
    //肤色
    private String skin;

    //无参构造器 写有参构造器就要把他定义出来
    public People(){

    }

    //有参构造器
    public People(String skin){
        this.skin=skin;
    }


    //行为方法
    public void behavior(String name){
        this.name=name;
        System.out.println(name+"会劳动");
    }



    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package com.ydrj.xb;

//老板类
public class Boss extends People{
    //行为
    public void getPaid(){
        System.out.println("发工资");
    }
    //无参构造器
    public Boss(){
    //默认,不写也可以
        super();
    }
    //有参构造器
    public Boss(String skin){
        //有参,要写
        super(skin);
    }
//    //在子类中出现了和父类相同名称的方法我们就成为方法的重写
    @Override
    public void behavior(String name) {
        System.out.println("创办公司");
        super.behavior(name);
    }
}

多态

同类型的对象,执行同一个行为,会表现出不同的行为特征。

首先我们要强调一下  多态存在的三个必要条件

  1. 继承或实现:在多态中必须存在有继承或实现关系的子类和父类
  2. 方法的重写:子类对父类中的某些方法进行重新定义(重写,使用@Override注解进行重写)
  3. 基类引用指向派生类对象,即父类引用指向子类对象:这里的父类类型是指子类对象继承的父类类型,或实现的父接口类型

格式

父类类型     对象名称= new   子类构造器; 
接口            对象名称= new    实现类构造器; 

 这时我们的关系内容

我们主要看这个

 使用多态的成员访问特点

成员方法

我们编译看左边,运行看右边

运行看右边

这种是向上转型,安全

可以换成new 子类() 便于解耦

解耦通俗解释就是好拆,像换电池

运行看右边我们已经很清楚了,就是调用子类重写父类的方法

编译看左边

成员变量

我们编译看左边,运行还是左边

因为我们的多态是侧重于行为的多态

多态下会产生的一个问题

在多态的情况下不能使用子类的独有功能

比如狗这个子类有独有的成员方法是play

独有的方法不能使用

因为在我们编译的时候,我们先编译我们父类,父类中没有这个方法直接报错,而我们的call,父类中有,运行的时候我们再去使用子类的方法,所以可以。

解决办法

首先要在编译时编译我们的子类,然后进行强制类型转换还是运行我们子类

父类类型对象转换为子类类型对象,这就是我们的向下类型转换

但是这种向下类型转换是不安全的,需要强制类型转换(父子之间要有继承关系)

但是又有一个问题

 如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException

解决办法

instanceof

我们需要判断一下是不是我们的子类对象

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员逸尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值