【Java学习】- 面向对象

14 篇文章 0 订阅

N5 面向对象

作者:迷恋

一、面向过程&面向对象

面向过程思想

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

面向对象思想

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

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

  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

  • 三大特性:封装、继承、多态

  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
    从代码运行角度考虑是先有类后有对象。类是对象的模板。


二、类与对象的关系

类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物

  • 例如:动物、植物、手机、电脑…
  • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体事物应该具备的特点和行为。

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

  • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
  • 能够体现出特点,展现出功能的是具体饿实例,而不是一个抽象的概念。

三、创建与初始化对象

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
    • 1、必须和类的名字相同
    • 2、必须没有返回类型,也不能写void
    • 3、定义有参构造之后,如果想使用无参构造,就得显示地定义一个无参的构造。

实例:

//学生类
public class Student {
    //属性:字段
    //private私有:是保证封装性
    private String name;

    //构造函数,常用于属性的初始化
    public Student(){
        this.name = "小明";
    }
    //方法
    public void study(){
        System.out.println(this.name+"在学习");
    }

    //main方法
    public static void main(String[] args) {
        //类:抽象的,实例化
        //类实例化后会返回一个自己的对象
        //student对象就是一个student类的具体实例
        Student xiaoming = new Student();
        //调用xiaoming这个实例中的方法
        xiaoming.study();
    }
}

输出结果

小明在学习

四、封装

  • 通常,应该禁止直接访问一个对象中的数据的实际表示,而应该通过操作接口来访问,这称为信息隐藏。
  • 所谓类的封装是指在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有化属性只能在它所在的类中被访问。为了能让外界访问私有属性,需要提供一些使用public修饰公有方法,其中包括用于获取属性值的getXxx()方法和设置属性值的setXxx()方法。
  • 属性私有 ,get/set

实例:
1、首先创建一个Demo02.java如下:

package demo02;

public class Demo02 {
    //private私有的
    private String name;
    private int age;
}

2、同包下创建Main.java如下:

package demo02;

public class Main {
    public static void main(String[] args) {
        Demo02 demo = new Demo02();
        System.out.println(demo.name);
    }
}

3、最终IDEA显示错误:在这里插入图片描述
当一个类中的成员变量的修饰为private时,其它的类,像这里的Main类就无法直接获取类Demo02中的成员变量的值,当然也无法进行修改。

可以通过设置Demo02中一些方法来改变其值:
1、Demo03.java

package demo03;

public class Student {
    private String name = "小明";
    private int id;
    private int age;

    //get获得这个数据
    public String getName() {
        return this.name;
    }

    //set给这个数值赋值
    public void setId(int id) {
        this.id = id;
    }
    //可以在方法中添加一个条件判断,控制数据的合法性
    public void setAge(int age) {
        if (age>120||age<16){

        }else
            this.age = age;
    }

    //方便调用展示
    public void show(){
        System.out.println(this.id);
        System.out.println(this.age);
    }
}

2、同包下Main.java

package demo03;

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.getName());
        student.setId(2019220121);
        student.setAge(130);
        student.show();
    }
}

输出结果

小明
2019220121
0

在实例中,setAge方法中可以通过设置一些条件来筛选外界传入的参数,以此来保证传入参数的合法性。


五、继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends的意思是”拓展“。子类是父类的拓展。
Java中类只有单继承,没有多继承。
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为父类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
子类和父类之间,从意义上讲应该具有”is a“的关系。
子类会自动拥有父类所有可继承的属性和方法。
在Java中,所有的类,都默认直接或者间接继承Object

实例:
1、Person.java(父类)

package demo04;

public class Person{
    String name;
    int age;

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

2、同包下的XiaoMing.java(继承Person的子类)

package demo04;

public class XiaoMing extends Person{

}

3、同包下的Main.java

package demo04;

public class Main {
    public static void main(String[] args) {
        XiaoMing xiaoming = new XiaoMing();
        xiaoming.name = "小明";
        xiaoming.age = 16;
        System.out.println(xiaoming.name+"的年龄是"+xiaoming.age);
        xiaoming.say();
    }
}

输出结果:

小明的年龄是16
说话

六、super

Java中专门提供了一个super关键字来用于访问父类的成员。例如访问父类的成员变量、成员方法和构造方法。

实例:
1、创建Person.java(父类)

package demo05;

public class Person {
    protected String name = "人类";
}

2、同包下创建Student.java(子类)

package demo05;

public class Student extends Person {
    private String name = "学生";
    public void test(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
}

3、同包下创建Main.java

package demo05;

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("测试");
    }
}

输出结果:

测试
学生
人类

实例2:
1、创建Person.java(父类)

package demo06;

public class Person {
    public Person(){
        System.out.println("父类的无参构造运行了");
    }
}

2、同包下创建Student.java(子类)

package demo06;

public class Student extends Person{
    public Student(){
        System.out.println("子类的无参构造运行了");
    }
}

3、同包下创建Main.java

package demo06;

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
    }
}

运行结果:

父类的无参构造运行了
子类的无参构造运行了

出现该结果的原因:

package demo06;

public class Student extends Person{
    public Student(){
        //因为继承自Person,此处默认隐藏含有一句
        super();
        System.out.println("子类的无参构造运行了");
    }
}

而当语句这么写的时候:

package demo06;

public class Student extends Person{
    public Student(){
        System.out.println("子类的无参构造运行了");
        super();
    }
}

直接报错
在这里插入图片描述
提示:调用父类的构造器,必须要放在子类构造器的第一行


七、方法重写

在继承关系中,子类会继承自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。需要注意的是,在子类中重写的方法需要和父类中被重写的方法具有相同的方法名、参数列表以及返回值类型。

实例:
1、创建Father.java(父类)

package demo07;

public class Father {
    public void test(){
        System.out.println("Father");
    }
}

2、同包下创建Son.java

package demo07;

public class Son extends Father{
    public void test(){
        System.out.println("Son");
    }
}

3、同包下创建Main.java

package demo07;

public class Main {
    public static void main(String[] args) {
        Son son = new Son();
        son.test();
    }
}

运行结果:

Son

八、多态

  • 即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
  • 多态存在的条件:
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态性。

实例:
1、创建Animal.java(父类)

package demo08;

public class Animal {
    public void shout(){
        System.out.println("父类");
    }
}

2、同包下创建Cat.java(子类)

package demo08;

public class Cat extends Animal{
    @Override
    public void shout() {
        System.out.println("Cat");
    }
}

3、同包下创建Dog.java(子类)

package demo08;

public class Dog extends Animal{
    @Override
    public void shout() {
        System.out.println("Dog");
    }
}

4、同包下创建Main.java

package demo08;

public class Main {
    public static void main(String[] args) {
        Animal cat = new Cat();
        Animal dog = new Dog();
        cat.shout();
        dog.shout();
    }
}

输出结果:

Cat
Dog

对象的类型转换

在多态中,涉及到将子类对象当做父类类型使用的情况,例如:

Animal an1 = new Cat();	//将Cat对象当作Animal类型来使用
Animal an2 = new Dog();	//将Dog对象当作Animal类型来使用

将子类对象当作父类使用时,不需要任何显式的声明,需要注意的是,此时不能通过父类变量去调用子类中的某些方法。例:
1、创建Animal.java

package demo09;

public class Animal {
    void shout(){

    }
}

2、同包下创建Cat.java

package demo09;

public class Cat extends Animal{
    public void shout(){
        System.out.println("喵喵...");
    }
    public void sleep(){
        System.out.println("猫睡觉...");
    }
}

3、同包下创建Test.java

package demo09;

public class Test {
    public static void main(String[] args) {
        Animal cat = new Cat();
        cat.shout();
        cat.sleep();
    }
}

此时报错如下:
在这里插入图片描述

可先将Animal类型的变量强制转换成Cat类型,如:

package demo09;

public class Test {
    public static void main(String[] args) {
        Animal cat = new Cat();
        animalShow(cat);
    }

    public static void animalShow(Animal animal) {

        Cat cat = (Cat) animal;
        cat.shout();
        cat.sleep();
    }
}

运行结果:

喵喵...
猫睡觉...
  • Java转型问题其实并不复杂,只需要记住一句话:父类引用指向子类对象。

例:有两个类,Father是父类,Son类继承自Father。
例1:

Father f1 = new Son();	//这就叫向上转型
//现在f1引用指向一个Son对象
Son s1 = (Son)f1;	//这就叫向下转型
//现在f1还是指向Son对象

例2:

Father f2 = new Father();
Son s2 = (Son)f2;	//出错,子类引用不能指向父类对象

你或许会问,第1个例子中:Son s1 = (Son)f1; 问为什么是正确的呢。

很简单因为 f1 指向一个子类对象,Father f1 = new Son(); 子类 s1 引用当然可以指向子类对象了。

而 f2 被传给了一个 Father 对象,Father f2 = new Father(); 子类 s2 引用不能指向父类对象。

  • 总结:

1、父类引用指向子类对象,而子类引用不能指向父类对象。

2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换吗,如:

Father f1 = new Son();

3、把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换,如:

f1 就是一个指向子类对象的父类引用。把f1赋给子类引用 s1 即

 Son s1 = (Son)f1;

其中 f1 前面的(Son)必须加上,进行强制转换。


九、抽象类

  • abstract修饰符可以用来修饰类,如果修饰方法,那么该该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,凡是有抽象方法的类一定要声明为抽象类。
  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

实例:
创建Actiom.java

package demo10;

//abstract抽象类
public abstract class Action {

    //抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();

    //1、不能new这个抽象类,只能靠子类去实现它:约束
    //2、抽象类中可以写普通的方法
    //3、抽象方法必须在抽象类中
    //抽象的抽象:约束
}

2、同包下创建Action2

package demo10;

public class Action2 extends Action{
    

}

结果显示错误:
在这里插入图片描述
说明了:子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。


十、接口

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!自己无法写方法,专业的约束!约束和现实分离:面向接口编程。
    接口中的方法默认是抽象方法。
    (不可以实例化,接口中没有构造方法)
  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑…
  • 接口的本质是契约。
  • 声明类的关键词是class,声明接口的关键词是interface。
    implements可以实现多个接口。
    实现接口必须重写接口中的方法。

实例:
1、创建UserService.java

package demo11;

//interface关键字定义接口都需要有实现类
public interface UserService {
    //接口中的所有定义都是抽象的abstract
    //接口方法中不能有方法主体
    public void run();
}

2、同包下创建UserServiceImp
(一般实现类的命名一般后缀使用Imp)

package demo11;

//抽象类:extends
//一般实现类使用关键字implements
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImp implements UserService{
    public void run() {

    }
}

当实现多个接口时:
(同包下还含有一个TimeService.java)

package demo11;

//抽象类:extends
//一般实现类使用关键字implements
//实现了接口的类,就需要重写接口中的方法
/**
public class UserServiceImp implements UserService{
    public void run() {

    }
}
 */
public class UserServiceImp implements UserService,TimeService{
    public void time() {
        
    }

    public void run() {

    }
}

(TimeService.java):

package demo11;

public interface TimeService {
    void time();
}

十一、内部类

内部类就是在一个类的内部再定义一个类,例如,A类中定义一个B类,那么B类相对A类来说就称为一个内部类,而A类相对于B类来说就是外部类了。

实例:
1、创建Outer.java

package demo12;

public class Outer {

    private int id = 2019;
    public void out(){
        System.out.println("这是外部类的方法");
    }

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

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

2、同包下创建Application.java

package demo12;

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

        Outer outer = new Outer();
        //通过外部类来实现实例化内部类
        Outer.Inner inner = outer.new Inner();
        //调用内部类的方法
        inner.in();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值