【Java学习】【Java基础】--第1篇:入门Java和对面向对象的理解

一、浅谈为何学习Java

24年本科毕业,从事电气工程师的岗位至今,工作内容愈发让自己觉得无聊。工作中接触到web开发的同事,便对此感兴趣。在学习过程中也验证了这个点,抛开之后是否能靠学这个转行不谈,投入到学习编程的过程中,能让我忘记时间、忘记疲惫,全身心地投入到其中。这也是我取名JustForFun的原因,希望在此过程中能收获快乐,并且能坚持下去。

二、对面向对象的理解

Java基础已经基本学的差不多了,个人觉得面向对象较为重要,并且有几个点不是很好理解,记录一下自己的理解,深入学习后继续更正

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程思想,将具有相同或类似属性、方法的对象抽象为一个类。面向对象有3个核心概念:封装、继承、多态。

1. 封装

封装比较好理解,将程序的核心功能封装在一个“黑匣子”里面,只给用户暴露使用的接口。
假设有这样一个场景,我们要定义两个人,他们有名字、年龄,并且会做自我介绍,按照面向过程的思路,应该这样实现:

public class Main {

    public static void main(String[] args) {

        // person1
        String p1Name = "小明";
        int p1Age = 18;
        // person2
        String p2Name = "小红";
        int p2Age = 20;

        introduce(p1Name, p1Age); // 我叫小明, 我今年18岁。
        introduce(p2Name, p2Age); // 我叫小红, 我今年20岁。

    }

    public static void introduce(String name, int age) {
        System.out.println("我叫" + name + ", 我今年" + age + "岁。");
    }

}

但是这样,又会暴露一些问题:
1.当我要定义再多一点人时,我需要重复定义新的name和age,每新增一个人,我都需要写一遍introduce(name, age)
2.introduce()这个方法应该是属于person的,因为只有人会做自我介绍(不考虑人工智能之类的),但如果我定义一个dogName = "旺财"; dogAge = 3,我同样可以调用introduce(),让一只狗做自我介绍,这明显是不对的。
在这种情况下,因为所有的人都有名字、年龄这两个属性,都有自我介绍这个行为或者方法,所以我可以将人抽象为一个类Person

class Person {
    public String name;
    public int age;

    Person() {}
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void introduce() {
        System.out.println("我叫" + name + ", 我今年" + age + "岁。");
    }
}

那么对于以上问题,我们可以这样解决:

public class Main {

    public static void main(String[] args) {

        Person[] persons = {
                new Person("小明", 18),
                new Person("小红", 20),
                new Person("小花", 18),
                new Person("小李", 19)
        };

        persons[3].age = 65536;

        for (Person p: persons) {
            p.introduce();
        }
        /*
        我叫小明, 我今年18岁。
        我叫小红, 我今年20岁。
        我叫小花, 我今年18岁。
        我叫小李, 我今年65536岁。
         */

    }

}

我不需要每次新增一个人,都去写一遍introduce()方法。同样的,由于introduce()被封装到Person类里了,其他的小狗小猫就无法调用这个函数了。
但是还存在问题,类里的属性是public的,意味着用户可以随意对这些属性进行更改,可能就会出现一个人65536岁的可能,这是不符合逻辑的。所以封装另一个思想就是只保留有限的接口给用户,而把内部复杂、核心的内容给隐藏起来:

class Person {
    private String name; // 私有化
    private int age; // 私有化

    Person() {}
    Person(String name, int age) {
        this.name = name;
        setAge(age);
    }

    public void introduce() {
        System.out.println("我叫" + name + ", 我今年" + age + "岁。");
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        // 防止用户输入非法年龄
        this.age = (age >= 0 && age <= 130)? age: 0;
    }
}

public class Main {

    public static void main(String[] args) {

        Person[] persons = {
                new Person("小明", 18),
                new Person("小红", 20),
                new Person("小花", 18),
                new Person("小李", 19)
        };

        // persons[3].age = 65536; 这句话编译已经无法通过了
        persons[3].setAge(65536);

        for (Person p: persons) {
            p.introduce();
        }
        /*
        我叫小明, 我今年18岁。
        我叫小红, 我今年20岁。
        我叫小花, 我今年18岁。
        我叫小李, 我今年0岁。
         */

    }

}

我们可以根据用户的输入,在内部通过我们自己的规则进行处理,而非把所有权限暴露给用户,让用户可以随意更改

2.继承

当我们需要使用一个共同的类,但是又要有所特点时,就要用到继承。还是以Person类举例,根据职业,我们可以将人分为教师、学生等等,虽然都属于人这个大类,但每个小类都有自己不同之处。教师、学生都继承于人,拥有人的共同特点,但又因为职业不同,拥有属于自己的特点:

class Teacher extends Person {
    Teacher() {}
    Teacher(String name, int age) {
        super(name, age);
    }

    public void teach() {
        System.out.println(super.getName() + "正在教书");
    }
}

class Student extends Person {
    Student() {}
    Student(String name, int age) {
        super(name, age);
    }

    public void study() {
        System.out.println(super.getName() + "正在学习");
    }
}

public class Main {

    public static void main(String[] args) {

        Teacher teacher = new Teacher("王老师", 29);
        Student student = new Student("小明", 18);

        // 都能够调用父类的public方法
        teacher.introduce(); // 我叫王老师, 我今年29岁。
        student.introduce(); // 我叫小明, 我今年18岁。

        // 调用自己的方法
        teacher.teach(); // 王老师正在教书
        student.study(); // 小明正在学习

    }

}

3.多态

个人人为多态是面向对象最不好理解,也是最有趣的点,感觉多态就是面向对象最核心的概念。多态按照解释叫做:同一个行为在不同对象上表现出不同的形态。父类Person具有introduce()方法,子类TeacherStudent都可以直接调用,进行自我介绍。但这样的自我介绍又太干巴了,希望子类在介绍自己的同时,可以说明一下自己的职业,此时就需要对继承于父类的方法进行重写

class Teacher extends Person {
    Teacher() {}
    Teacher(String name, int age) {
        super(name, age);
    }

    public void teach() {
        System.out.println(super.getName() + "正在教书");
    }

    // 重写父类方法
    @Override
    public void introduce() {
        System.out.println("我叫" + super.getName() + ", 我今年" + super.getAge() + "岁, 我是一名老师。");
    }
}

class Student extends Person {
    Student() {}
    Student(String name, int age) {
        super(name, age);
    }

    public void study() {
        System.out.println(super.getName() + "正在学习");
    }

    // 重写父类方法
    @Override
    public void introduce() {
        System.out.println("我叫" + super.getName() + ", 我今年" + super.getAge() + "岁, 我是一名学生。");
    }
}

public class Main {

    public static void main(String[] args) {

        Teacher teacher = new Teacher("王老师", 29);
        Student student = new Student("小明", 18);

        teacher.introduce(); // 我叫王老师, 我今年29岁, 我是一名老师。
        student.introduce(); // 我叫小明, 我今年18岁, 我是一名学生。

    }

}

同一个行为introduce()在不同对象上表现出不同的形态,这就是多态。多态有个很妙的设定,叫做父类对象指向子类的引用,Person person = new Student()。还是以学生和老师为例,我现在建立一个函数introduceYourself(obj),希望传入里面的obj对象能做一个自我介绍,那这个obj对象,应该是老师,还是学生呢?如果我写成introduceYourself(Teacher teacher)的话,所有老师都可以传入其中进行自我介绍,但是学生呢?除了老师以外的Person呢?因为对象类型不同,无法传入函数。同样的,这个obj对象我指明是学生的话,也会出现同样的情况。
所以最好的方法应该将对象类型指明为他们的父类Person

public class Main {

    public static void main(String[] args) {

        Teacher teacher = new Teacher("王老师", 29);
        Student student = new Student("小明", 18);

        introduceYourself(teacher); // 我叫王老师, 我今年29岁, 我是一名老师。
        introduceYourself(student); // 我叫小明, 我今年18岁, 我是一名学生。

    }

    public static void introduceYourself(Person person) {
        person.introduce();
    }

}

父类对象Person,指向了子类Teacher和Student的引用,而由于他们都具有同样的introduce()方法,并且子类已经进行重写,此时父类会调用子类的方法,从而实现同一行为的不同表现。(静态方法不适用该情况,静态方法仍会调用父类的方法,具体原理还不懂)

三、总结

第一次写这么多内容,可能会有很多理解是错误或者不全面的,后面再做订正。

posted @ 2025-10-10 19:09  JustForFun1  阅读(10)  评论(0)    收藏  举报