挑灯夜读——Java(二):面向对象
面向对象思想介绍
-
很快就发现学习Java已经快五十天了,在其中收获也很多。下面我们就慢慢来研究Java的基础部分。首先我们就下面几个知识点,进行讨论与学习,我和大家一起学习其中的奥秘。
一、学习目录
- 面向对象思想:和你的对象面对面,才能领悟真谛,当然如果单身也可以面向一对象,俗话说的好,一个对象好的人才是一个好对象。
- 成员变量和局部变量:也就是其作用范围的不同,成员变量相当于在整部剧(整个程序)都活下来的角色,局部变量,就在某一部分出现,然后就没了,不存在了。
- 匿名对象:简单点就是说这个对象没有名字,正因为没有名字,就像你过年回家雇佣了一个对象,当双方完成交易,你没有留下她的联系方式,你就无法在下次雇佣(调用对象)的时候使用她了。
- 封装:也就是常说的构造方法、析构方法、方法重载、设置访问权限等来实现,官方书籍介绍其意义为:一、将数据和数据操作包装成一个对象类型,是对象成为包含一组属性和操作的运行单位。二、实现信息隐藏,类既要提供与外部联系的方法,又要尽可能地隐藏某些数据和实现细节。我认为其操作过程和C++中的结构体相似,将其包装为一个单位。
- this关键字:这个使用起来很简单,就是说我们在上面的封装函数(也就是构造函数中)容易见到如下所示( ) 可以知道的是,this后面紧跟着的year一定是本类中的变量,而等号后面的year是该构造函数中定义的局部变量。
public class MyDate { int year,month,day; public MyDate(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } }
- 构造函数:在5中我们肯定会介绍到,在这里我们会深入理解。
- 继承:这是一个很有意思的部分,首先我们通过继承二字来理解就是人类社会常说的继承家产等行为,这里说的是一个类为父类,我们不用定义它为父类,只需要像平常一样写出来这个类的变量、方法和操作过程等。在我们创建了另一个类后,该类在类名定义后加入了 “extends + 父类名“ 这样的结构,也就想让于继承了分类的变量和方法等属性。
- 多态:就是说我们在定义了一个方法后,需要对其传入值进行计算,但是我们传入的值是不定的,可能是int型,也可能是str型,也可能是一个,也可能是两个数值。这就很麻烦了,你想想,我们可能计算的不同种类有很多很多,倘若我们一个一个去定义,我相信这样的一个方法便能让我们绝望,因为太多了。下面我们就介绍一下实现多态的好方法。
- 抽象类:定义一个类,将其方法抽象化,也就是只有它的方法名称和标识符与数据类型等,内部没有任何行为。这样的目的就是约束我们的实现类行为的一种最好的体现,它的好在哪儿呢?让我们娓娓道来~
- 接口:接口就是由一组抽象方法、常量和内嵌类型的集合。也就是在一个项目中经常会提到的给你接口,你自己去编程序实现一个想要的功能。
- 内部类:累不累(内部类当然就要在十分累的情况下讲出幽默的感觉了,假如你觉得很长,一定要收藏然后慢慢来看了。
二、学习内容
一、面向对象的思想
- 都知道Java用一句话就能总结出来,那就是万物皆对象,相当于把语言实例化,这样就比较符合我们的客观世界。当然想要更形象的了解对象的概念,我们需要知道面向过程的思想是什么?面向对象的语言诸如C、C++。
- 下面我们分类举例如下:
把大象装入冰箱的步骤
面向过程:
1、打开冰箱门
2、把大象装入冰箱
3、关上冰箱门
也就是说,我们把整个完成的过程,都切分成每一个任务块,每个任务块只需要完成这个任务即可。
面向对象:
1、冰箱把门打开
2、大象你自己个儿进冰箱
3、冰箱你给我把门关上
相较于上面也就是说,每一个过程都是一个对象在做这些东西,不是任务而是个体完成一个自己的行为
经过上面的举例,我们也看到了关于对象的知识点很清晰形象,假如看上一次,我相信这个生动形象的例子会深深刻入你的脑海
二、成员变量与局部变量
- 成员变量
通俗讲成员变量也就是我们类中的一个全局变量,说到了全局,就是说它的作用区域为整个类的范围。如下:
public class Parents(){
private int year;
public Parents(){
this.year = 2021;
}
public void playChild(){
int month=5;
System.out.println("现在的年份是:"+year+"现在的月份是"+month);
}
//假如再创建一个方法,无法使用playChild方法中的month变量,因为其内存已经释放
}
- 局部变量
如上所示,可以看到playChild中的局部变量month,它的生命周期仅仅在它的创建以及到结束该方法后被释放,其生命周期只在局部,所以它的名称为局部变量,可以很形象的理解。
其实变量的类型很好理解,只要定义在方法外,初始化一般在构造函数内的变量,为成员变量,其它定义在方法内,就为局部变量。
三、匿名对象
- 匿名对象解释起来会很空洞,例如我就告诉大家,匿名对象就是没有名称的一个对象,大家肯定会觉得这解释的啥玩意儿?难道我理解起来就是有名字的,这不就是明明白白的道理吗?
//那么我相信,除了代码,没有什么能够让你我都能心灵相通了
public class Students(){
static class Childs2 implements Parents{
@Override
public void doIt(){
System.out.println("这是静态内部类");} //因为静态,所以此类
//是Students一部分,一起加载。
}
public static void main(String[] args){
Childs childs = new Childs();
childs.doIt(); //这是调用类外的方法,也是较为容易理解和掌握的方法
new Childs2().doIt(); //这是调用静态内部类的一种方法,该方法是上面方法一的改进
class Childs3 implements Parents{
@Override
public void doIt(){
System.out.println("这是局部内部类方法");}
}
new Childs3().doIt(); //这是调用局部内部类的方法,也和方法2一样是方法一的改进
//下面就为匿名内部类的写法
childs = new Parents(){
@Override
public void doIt(){
System.out.println("这是匿名内部类方法")}
}
childs.doIt(); // 匿名内部类的调用方法
}
}
interface Parents{
void doIt();
}
class Childs implements Parents{
@Override
public void doIt(){
System.out.println("这是类外定义方法");
}
可以看到,我们创建的匿名内部类,和其它类不一样,其它类都创建了类名,Childs,Childs1和Childs2都是我们对前三个方法创建的类名称,而第四个方法,就不需要定义类名了,只需要调用我们覆盖父类的方法就可以完成这项工作。
四、封装
- 封装这个知识点,用一句话概括为,将一种抽象性的函数接口的实现细节部分包装,隐藏起来的一种实现方法。
实现对外包装和隐藏最好的方法,不就是将其成员的修饰符写为私有,防止外部访问
public class Teacher{
private String name;
private int age;
}
- 上述就是我们实现一个简单对外隐藏的例子,但是我们外部也需要调用该类中的成员时,应该如何调用它?
public class Teacher{
private String name;
private int age;
public String getName(){
return name;
}
public int getAge(){
return age;
}
//上述为其它类得到该类中的成员变量数值的方法,get也就是得到的意思
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
//上述为其它类设置该类的成员数值时,调用此方法,对该方法的私有变量赋值
}
封装的具体解释,参照Java封装教程
五、this关键字
- 如果学到了这里,我们一定知道,this在上述的代码展示中出现过,如果仔细想一想就能明白它的意义是什么?
public class Book{
private int age;
private int soces;
private String name;
private boolean girlfriend;
//上面是定义成员变量
//下面是一个对该类成员变量赋值的方法
public setNum(int age,int soces,String name,boolean girlfriend){
this.age = age;
this.soces = soces;
......
}
}
this.age中的age是该类定义成员变量
而等于号后面的单个age,是我们调用该方法时传入到方法中的age值,也就是setNum(int age,)中的age值。
this就是为了指定谁才是成员变量,谁是我们传值时定义的局部变量,显然this后的为全局变量,也就是成员变量。
六、构造函数
- 构造函数的类型很多,简短的介绍反而会让我看感觉更糊涂。倒不如这样来理解,会让我们更好的理解构造函数的意义。
public classs car{
public static void main(String[] args){
Bus bus = new Bus();
//每当new这个类时,其中的构造函数就会一起被加载,这时其中的输出函数就会被执行
Boat boat = new Boat(12,12,100);
boat.play();
//可以看到上面我们在定义该函数时,将参数传入构造函数中,然后调用该类中play方法
}
}
class Bus{
public Bus{
//这是我们定义的一个无参数构造
System.out.println("叔告诉你,你把握不住!");
}
}
class Boat{
private int height;
private int width;
private int weight;
public Boat(int height,int width,int weight){
this.height = height;
this.width = width;
this.weight = weight;
}//此构造函数为有参构造
public Play(){
System.out.println("船长为:"+height+"船宽为:"+width+"船重为:"+weight);
}
}
观察了上面的的构造函数调用方法,就能够理解构造函数很大意义上和set函数一样,就是其它类想要设置该类的成员变量的数值,就可以通过构造函数的方式对其进行赋值,赋值的过程简单易懂,相信聪明的你已经学会了这么简单的函数。
七、继承
- 继承就是目录中提到了,子类继承父类的一种方式,实现的语句是public class 子类名称 extends 父类名称,实现过程如下:
public class Father{
public void Money(){
System.out.println("爸爸有很多钱!");
}
}
class Son extends Father{
public void Money(){
System.out.println("儿子也会有很多钱!来自父亲支持。");
}
}
- 更复杂的继承可不止这些,这只是简单的继承父类的方法,自己重写该方法,重载方法时,其参数个数,类型和返回值一致,不能加以改变它的各个属性,这和重载不一样,重载是在一个类中对其方法的定义不同,不同在于参数类型,个数或者返回值(一定要修改才能叫重载)。
上面我们已经知道了对于父类方法的重写,就是子类想要运用父类的方法和变量,就需要继承父类,然后也继承父类的方法和值,这是重写的过程,重写过程有以下几点注意!
注意点 | 修改 |
---|---|
参数类型 | 不能修改 |
形参个数 | 不能修改 |
异常处理 | 可以修改或者删除,不能增加 |
访问限制(修饰符) | 子类比父类更低 |
最后的访问限制也就是说父类是private方法时,我们继承不了,因为没有比private更低的修饰符,只有为public、protect和默认值时才能继承。
八、多态
- 多态的首先三个必要条件是:1、继承 2、重写 3、父类引用指向子类对象 Parent p = new Child();
- 而实习多态的方法也有三个:1、重写 2、接口 3、抽象方法和抽象类
我们先来谈谈多态的三个必要条件:
以上是我在java多态中找到的一张图,最左边是一个形状类,其中定义了画图的方式,有三个类继承了该形状类,想要在定义的子类中实现一个画图类,下面我们写出上述图表达的意思。
public class Shape{
public void draw(){
}
}
class Cricle extends Shape{
void draw(){
System.out.println("这里实现画圆");}
}
class Triangle extends Shape{
void draw(){
System.out.println("这里实现画三角形");}
}
class Square extends Shape{
void draw(){
System.out.println("这里实现画正方形");}
}
内部具体实现的内容就不做过多的介绍了,多说无意,不如点拨点拨,会让我们仔细去思考这个问题的核心内容。
- 实现多态的方法还有三种我们还需探究,那就是继承、接口和抽象类和抽象方法
- 继承:子类通过extends关键字继承父类的成员变量和方法,和我们社会关系中的继承家产的道路相同,其中还涉及到继承的权限扩大,当然根据我的编程思想(面向百度编程)又得知,子类可以继承父类的所有成员,包括私有成员,只是不能访问私有成员。而且根据Java思想得知,在使用子类的构造函数时,会先调用父类的构造函数。
- 接口:接口的实现是通过interface关键字进行的,它是一种抽象方法的集合,一个类只有通过继承接口的方式,才能达到实现抽象方法的目的。
这里引用菜鸟教程的一段严谨且容易理解的一句话:
1、 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。
2、 类描述对象的属性和方法。接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
3、接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
4、另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
——其中2中解释,实现接口中的方法的类,必须实现所有的方法,这在我们编程时会遇到,只有我们实现了该接口中的所有方法,也就是把它的方法拷贝到我们的实现方法中,他才能实现最终的效果。
- 抽象类和抽象方法:抽象方法的实现是通过关键字abstract,它拥有方法和成员变量,但是由于其是抽象类,所有不能对其进行初始化赋值,也就是说我们必须使用一个子类继承它,它才会有意义,当然在前期设计时,还需仔细思考,我们是否需要一个抽象类来实现我们想要的内容。
//我们实现一个抽象类如下
public abstract class Student{
private int number; //学号
private String name; //姓名
private String class; //班级
public Student(int number,String name,String class){
this.number = number;
this.name = name;
this.class = class;
}
public void study(){
System.out.println("该学号学生"+this.number+""+this.name);
}
public int .....//还可以写很多,只要不实例化就行。
}
发现没有,我这样一写,其实也并没有将知识点一一讲解就结束了好像,比如后面还有接口,抽象类和内
部类。这都在我们前面提到过,为什么会提到呢?因为这些知识点就是融会贯通的,它们不是单独存在的
下面就在推荐推荐一个好的视频学习网站吧,如果学到这里了,那就去开辟一块新天地吧,我这个内容和
记笔记的意思差不多,这边我已经回顾了一遍我的知识点,你也可以在看完视频后和我一起回顾
重点:B站搜索 “狂神说Java” 保证让你学到腿软!
- 下一期,我会就数据结构进行回顾,不知道会不会搬出我的python语言对数据结构进行编写,都习惯了!哈哈哈下期再见。