老师总是说学习java一定要有面向对象的思维,那么究竟什么是面向对象呢?首先来总结一下面向过程。
C语言一般用的就是面向过程,所谓面向过程开发就是要实现一个功能,需要把功能的每一个步骤和过程一步一步用程序实现了。
但是,时间一长我们就会发现,好多代码都似曾相识,每次实现一次都需要重新写一次,这样代码不仅看起来比较繁琐而且冗余度特别大,不易修改和管理。就有人想到可以不可以把相同代码全部抽取出来封装成一个公用的方法, 每次需要只用短短的一行方法调用就可以解决了,这种封装的思想,就是面向对象编程的特点。
所谓面向对象,就是把功能类似的进行封装,封装成一类。用的时候只需要找到对应类就可以了,这就是面向对象的思想。比如你之前写一个排序,需要考虑用什么排序时间效率高,等等一系列问题。而现在你只需要查一查API看看有什么类的什么方法可以解决就好了。所谓万事万物皆对象。
继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展,通过继承创建的新类称为“子类”或“派生类”。被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。(后续补充)
封装:也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作。
多态:允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。(后续补充)
类:是一组相关的属性和行为的集合,比如我定一个猫类,我无需关注所有猫的自身特点,我只用把他们共有的一些特点封装起来,比如爱吃鱼,会抓老鼠等等。
对象:就是对类的具体实现,比如猫,当你创建一个猫对象,这个时候你就要关心它自身的特点,是什么品种,什么颜色,有什么喜欢等等。
一个类具有哪里属性呢?我们可以由现实推出这些抽象的
事物 | 类 |
属性 | 成员变量 |
行为 | 成员方法 |
这样就可以很容易看出来类就是一类具有相同属性事物的集合。
public class Student {
String name;
String sNum;//学号
int age ;
public static void study(){
System.out.println("好好学习,天天向上");
}
public static void doHomework(){
System.out.println("按时完成作业");
}
}
这里定义一个学生类,里面有三个成员属性(成员变量)分别是学生的姓名,学生的学号,学生的年龄,还有两个成员方法,也就是学生可以做哪里事情,分别是study()和doHomework()这两个功能。
学生类既然已经定义好了,下一步我们就来创建一个具体的学生对象。
public class TestStudent {
public static void main(String[] args) {
Student student = new Student();//创建一个学生对象
student.name="张三";
student.age=18;
student.sNum="1643320124";
student.study();
student.doHomework();
}
}
这里实例化了一个学生对象,并为其赋上了具体的值。
什么是构造方法呢?用于创建对象,给对象中的成员进行初始化。
比如上一个例子中我们创建一个学生类,Student student = new Student(); 后面的Student()就用到了无参构造方法。但是有一个疑惑,为什么明明我们在Student类中写构造方法,但是还可以用呢。其实很简单,每一个类在创建的时候,系统就会为其自动默认生成一个无参构造方法,但是不表现出来,这样我们就无需自己定义,直接用就可以了。
方法名与类名相同没有返回值类型,连void都没有,没有具体的返回值。
分为无参构造和有参构造,请看下面的代码:
public class Student {
String name;
String sNum;//学号
int age;
//无参构造
public Student() {
System.out.println("无参构造");
}
//有一个参数的构造
public Student(String name) {
this.name = name;
System.out.println("有一个参数的构造");
}
//有二个参数的构造
public Student(String name, String sNum) {
this.name = name;
this.sNum = sNum;
System.out.println("有二个参数的构造");
}
//有三个参数的构造
public Student(String name, String sNum, int age) {
this.name = name;
this.sNum = sNum;
this.age = age;
System.out.println("有三个参数的构造");
}
public static void study(){
System.out.println("好好学习,天天向上");
}
public static void doHomework(){
System.out.println("按时完成作业");
}
}
这个地方用到的构造方法的重载
接下来就分别执行:
public class TestStudent {
public static void main(String[] args) {
Student student = new Student();
Student student1 = new Student("张三");
Student student2 = new Student("李四","1643321001");
Student student3 = new Student("王五","1643321002",18);
}
}
执行结果如下
无参构造
有一个参数的构造
有二个参数的构造
有三个参数的构造
第一种也就是上面说到的通过有参构造方法,在创建对象的同时给成员变量赋值。
通过定义set方法,实现成员变量赋值。
在设置之前先总结一个关键字private 这个关键字,像这样的关键字其实还有三个(public protected 缺省),之前的那个学生类型就用的缺省值,这一类的关键字被称作权限修饰符。具体分类如下表:
使用范围 | public | protected | 缺省 | private |
同一类中 | √ | √ | √ | √ |
同包不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
其它包中的类 | √ |
public:公共修饰符,被其修饰的再同一项目下,都可以对其进行访问
protected:被保护的
缺省:不用自己写,系统默认的修饰符
private:稀有权限修饰符,只能在当前类中访问
由此可见,private是最安全的修饰符,凡是被他修饰过得成员属性,成员方法外界都不能直接访问。
事实上开发中实体类中的成员变量都是通过private进行修饰的,然后对外提供set方法,get方法进行赋值和取值。下面我们就来改进一下我们的Student类:
public class Student {
String name;
String sNum;//学号
int age;
public void setName(String name) {
this.name = name;
}
public void setsNum(String sNum) {
this.sNum = sNum;
}
public void setAge(int age) {
this.age = age;
}
public static void study(){
System.out.println("好好学习,天天向上");
}
public static void doHomework(){
System.out.println("按时完成作业");
}
}
再来通过set方法为其赋值,
public class TestStudent {
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
student.setAge(18);
student.setsNum("1643321001");
}
}
又出现了一个问题,我们光赋值了,那如何取值呢,其实这个问题刚才也说了,可以在设置一个get方法。程序必须要有一个出口嘛。
public class Student {
private String name;
private String sNum;//学号
int age;
public void setName(String name) {
this.name = name;
}
public void setsNum(String sNum) {
this.sNum = sNum;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public String getsNum() {
return sNum;
}
public int getAge() {
return age;
}
public static void study(){
System.out.println("好好学习,天天向上");
}
public static void doHomework(){
System.out.println("按时完成作业");
}
}
可以看出来每个成员变量,都有对应的set和get方法。
public class Student {
private String name;
private String sNum;//学号
int age;
public Student() {
}
public Student(String name, String sNum, int age) {
this.name = name;
this.sNum = sNum;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setsNum(String sNum) {
this.sNum = sNum;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public String getsNum() {
return sNum;
}
public int getAge() {
return age;
}
public static void study(){
System.out.println("好好学习,天天向上");
}
public static void doHomework(){
System.out.println("按时完成作业");
}
}
现在就可以得出一个结论,一个完整的类,需要具有三样属性,分别是构造方法,成员变量,成员方法。
注意:当你的类中自己定义了有参数的构造时,有参构造会覆盖掉系统自己生成的无参构造,这个时候必须自己手动生成一个无参构造。
类的位置 | 内存中的位置 | 生命周期 | 初始化值 | |
成员变量 | 类中定义 | 堆内存 | 随对象产生而才产生,消失而消失 | 有默认等等初始化值 |
局部变量 | 类内方法中或方法生命中 | 栈内存 | 方法调用产生,方法结束消失 | 没有默认的初始化值 |