【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()方法,子类Teacher和Student都可以直接调用,进行自我介绍。但这样的自我介绍又太干巴了,希望子类在介绍自己的同时,可以说明一下自己的职业,此时就需要对继承于父类的方法进行重写:
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()方法,并且子类已经进行重写,此时父类会调用子类的方法,从而实现同一行为的不同表现。(静态方法不适用该情况,静态方法仍会调用父类的方法,具体原理还不懂)
三、总结
第一次写这么多内容,可能会有很多理解是错误或者不全面的,后面再做订正。

浙公网安备 33010602011771号