文章目录
一、面向对象基本概念
1.什么是面向对象?
1.面向对象的简单解释
JAVA的面向对象其实就是一种思想。 打个比方,在我们人常生活中,手机可以帮助我们完成很多事情,例如,午休点外卖,计算机算每日开销等等。有了这些功能我们不再需要自己动手做饭或者拿纸币计算开销,让我们的生活变得简单且方便。
这时候换成面向对象的角度看待手机。把手机当作Java中的类,而手机中的功能就是类中的方法。当我们想要使用这些功能的时候,就需要先拥有一台手机,也就是创建一个手机类。但刚拥有的手机中还没有你想使用的功能,这时候你就需要去下载相应的功能,也就是在手机类中创建相关方法。功能下载好之后,你想要使用这些功能的话,就需要用手机来打开这些功能,也就是声明类对象。最后打开功能完成你想做的事,也就是使用类对象调用类中的方法。这就是Java中的面向对象开发的过程。
- 面向对象开发
- 就是不断的创建对象,使用对象,指挥对象做事情。
- 面向对象设计
- 其实就是在管理和维护对象之间的关系。
- 面向对象特征
- 封装(encapsulation)
- 继承(inheritance)
- 多态(polymorphism)
面向对象其实是一种编程思维,也是一种思考问题的方式
如何建立面向对象的思维呢?
1、先整体,再局部
2、先抽象,再具体
3、能做什么,再怎么做
2、类与对象的关系
- 类: 是一组相关的属性和行为的集合
- 属性——事物的基本描述,行为——事物的功能 ,也就是方法
- Java语言中最基本的单位是类。所以,我们要用类来体现事物
- 对象: 是该类事物的具体体现
- 举例:
- 类 ——手机就是类
- 对象 ——华为手机就是一个对象
面向对象格式讲解;
//创建对象的语法 类名 类别名 = new 类的构造方法();
Student s = new Student();
3、 成员变量和局部变量的区别
- 在类中的位置不同
- 成员变量——直接定义在类中的变量,不在任何方法内。
- 局部变量——方法内或者方法声明上
- 在内存中的位置不同
- 成员变量——存储在堆内存
- 局部变量——存储在栈内存
- 生命周期不同
- 成员变量——随着对象的存在而存在,随着对象的消失而消失
- 局部变量——随着方法的调用而存在,随着方法的调用完毕而消失
- 初始化值不同
- 成员变量——有默认的初始化值
- 局部变量——没有默认的初始化值,必须先定义,赋值,才能使用。
4、匿名对象
匿名对象:就是没有名字的对象。
是对象的一种简化表示形式
- 匿名对象的两种使用情况
- 对象调用方法只有一次的时候
- 作为实际参数传递
代码示例
对象调用方法只有一次的时候
//正常写法
Student s = new Student();
s.age=23;
//匿名写法
new Student().age = 23;
//我们可以看到,用匿名写法时不用起名字就可以直接修改age的值了。
作为实际参数传递
// 输出学生的数量
System.out.println("一共有"+new Student().num + "个学生");
//这种方法就是作为实际参数传递
二、封装
1、什么是封装?
封装就是把类的属性和方法使用private修饰,不允许类的调用者直接访问。需要先创建被封装的类的类对象,在被封装的类中将封装的内容生成get()和set()方法,使用类对象调用对应的get()和set()方法才可以继续访问。
//set()方法的作用是接收调用方法时录入的数据,并存储在对应变量中。
//get()方法的作用是从对应变量中获取存储在其中的数据。
- 好处:
- 隐藏实现细节,提供公共的访问方式
- 提高了代码的复用性
- 提高安全性
- 原则:
- 将不需要对外提供的内容都隐藏起来
- 把属性隐藏,提供公共方法对其访问
Demo代码示例:
public class Demo02 {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三"); //给成员变量赋值
s.setAge(18); //调用方法
System.out.println(s);
}
}
class Student{
private String name;//姓名
private int 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; }
}
从运行结果可以看出,打印的是封装类的类对象,并不是我们想要打印的name和age的内容。这时候就需要将类对象中的内容转换成String字符串的格式,才可以正常使用。
加上toString方法,这时候就可以正常使用封装类中的内容了。
2、private关键字
- private 关键字(意思是私有的)
- 是一个权限修饰符。
- 可以修饰成员(成员变量和成员方法)
- 被private修饰的成员只在本类中才能访问。
- private最常见的使用方法:
- 把成员变量用private修饰
- 提供对应的getXxx()/setXxx()方法
Demo示例:
在上面这个Demo中,我们可以发现,当我们用private修饰Student类中的成员变量时,在Student类中我们就不能调用它的成员变量name了。
上面我们也讲到了, 被private修饰的成员只在本类中才能访问。
这个时候java就给我们提供了getXxx()以及setXxx()方法,供我们访问这些被private修饰的成员变量。
getXxx()方法作用是获取已经定义好的成员变量内容。
setXxx()方法作用是先没定义内容的成员变量中添加内容。
public class Demo02 {
public static void main(String[] args) {
Student s = new Student();
s.setName("张三"); //给成员变量赋值
s.study(); //调用方法
}
}
class Student{
private String name;//姓名
private int age; //年龄
//定义学习的方法
public void study(){
System.out.println(name+"爱学习");
}
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;
}
}
3、this关键字
this关键字:代表所在类的对象引用。简单的说,它就代表当前类的一个对象。
注:方法被哪个对象调用,在该方法内部的this就代表那个对象
- 作用:
- 当成员变量与局部变量同名时,用来区分成员变量和局部变量;
- 在构造函数中调用构造函数。
示例: 有时我们为了让变量更具有语义化,经常会出现成员变量和局部变量同名的问题,这时候就要用到this了,比如以下代码:
class Word{
public static void main(String[] args) {
Demo d=new Demo("张三");
}
}
class Demo{
String name;
Demo(String name){
this.name=name;
}
}
如果我们不加this关键字,打印出的结果是null;如果我们用this.name打印出的结果是张三,为什么呢?
当创建新对象的时候,构造函数会被自动调用,我们传的参数是“张三”,在构造函数Demo()里会定义一个名称为name的变量来接收这个数据“张三”,然后进行赋值的动作。 这时候如果写成name=name;就相当于我们把“张三”这个值又赋给了它自己,这个栈里的变量对自己进行重写,这是毫无意义的,所以我们怎么才能把它赋值给堆里的变量name(也就是成员变量name)呢?这就要用到关键字this了。 其实每个函数里面其实都有一个默认的this引用,当对象调用函数的时候,将对象的地址赋给this关键字,此时this关键字可以指向对象,通过this就可以访问成员变量了(就是对象的属性)。
三、构造方法
- 作用概述:
- 给对象的数据进行初始化
- 格式
- 方法名与类名相同
- 没有返回值类型,连void都没有
- 没有具体的返回值
代码示例:
class Student {
private String name; //null
private int age; //0
public Student() {
System.out.println("这是构造方法");
}
}
class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
}
}
注:构造方法如果不写的话,系统会主动提供默认的构造方法。如果写了,系统就不再提供了。而且构造方法也是可以重载的。
四、static关键字
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块。
1.static关键字特点
-
随着类的加载而加载
-
优先于对象存在
-
被类的所有对象共享
- 这也是我们判断是否使用静态关键字的条件
-
-
可以通过类名调用
2.static关键字的作用
- 方便在没有创建对象的情况下来进行调用(方法/变量)。
- 使用static关键字修饰一个属性:声明为static的变量实质上就是全局变量。
- 使用static关键字修饰一个方法:在一个类中定义一个修饰符为static的方法,那这个方法不用本类的对象也可以调用(类调用)。
- 使用static关键字修饰一个类(内部类):
3.static关键字注意事项
- 在静态方法中是没有this关键字的
- 静态方法只能访问静态的成员变量和静态的成员方法
- 它们不能以任何方式引用this或super。
- 不允许用来修饰局部变量
Demo代码示例:
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.num);
System.out.println(Student.num2);
System.out.println(s.num2);
}
}
class Student {
//非静态变量
int num = 10;
//静态变量
static int num2 = 20;
}
输出结果:10 20 20
可以看到,我们可以通过类名调用
4.main方法(扩展)
main方法就是静态的
public static void main(String[] args){
//代码块
}
public:公有的,最大的访问权限
static:静态的,无需创建对象
void::表示没有返回值,无需向JVM返回结果
main:方法名,固定的方法名
String[] args:表示参数为字符串数组,可以在调用方法时传入参数
五、继承
继承本质就是实现代码的复用,防止重复的代码多次书写,当一个类继承一个类的时候,该类中就会拥有另外一个类中的所有代码。
继承的语法:
class A{}
class B extends A{}
继承的特点:
- 子类继承父类,使用extends关键字。
- 子类可以调用父类中的非私有的属性和方法,当做自己的属性和方法去使用(只能是public、 protected修饰的)。
- 子类可以添加自己独有的属性和方法。
- 当子类重写父类的方法时,便执行子类的方法,父类方法不再调用。
- 类与类之间的继承关系
- Java 中类与类之间只能单继承,子类与父类是多对一的关系(一个儿子只能有一个父亲)
- 但一个父类可以有多个子类,父类和子类是一对多的关系(一个父亲可以有多个儿子)
- Java 中虽然不能多继承但是可以多层继承,套娃关系(子类继承父类,父类继承爷爷类)
- 在创建类时,如果不指定类的父类,便默认继承object类,object类是所有类的祖类。
使用继承的注意事项
-
子类只能继承父类所有非私有的成员(成员方法和成员变量)
- 其实这也体现了继承的另一个弊端:打破了封装性
-
子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
-
不要为了部分功能而去继承
-
我们到底在什么时候使用继承呢?
举例:水果和苹果,苹果是一种水果。
学生和人,学生是人的一种。
所以我们总结采用假设法。如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
方法重载与重写的区别:
-
方法重载(overload):在一个类中,方法名相同,参数不同
-
方法重写(override):在两个类中,子类继承父类,重写父类的方法
接下来展示不使用继承写类似代码的Demo示例:
public class Demo03 {
public static void main(String[] args) {
Students stu = new Students();
stu.eat();
stu.sleep();
Teacher tea = new Teacher();
tea.eat();
tea.sleep();
}
}
class Students {
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
class Teacher {
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
运行结果
使用继承在写相似的代码的Demo示例:
//使用继承后
//首先我们定义一个人类,因为老师、学生都属于人,都要吃饭和睡觉
public class Demo03 {
public static void main(String[] args) {
Students stu = new Students();
stu.eat();
stu.sleep();
Teacher tea = new Teacher();
tea.eat();
tea.sleep();
}
}
class Person {
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
class Students extends Person { }
class Teacher extends Person{ }
运行结果
可以看出继承可以将相似代码进行优化,代码量明显减少了。如果之后需要对代码进行修改,修改一处即可,方便代码的维护。
1、final 关键字
- final关键字是最终的意思,可以修饰类,成员变量,成员方法。
- 修饰类,类不能被继承
- 修饰变量,变量就变成了常量,只能被赋值一次
- 修饰方法,方法不能被重写
Java中在使用继承时,子类可能会重写父类的一些方法,导致父类的方法被覆盖,从而失去原有的功能,这时候便需要使用 final 关键字来解决这个问题。
public class Fu{
public final void show(){
System.out.println("十分重要的功能,不可覆盖!!!");
}
}
===============================================
public class Zi extends Fu{
//父类方法使用final关键字修饰,不可重写!产生编译器错误
/* public void show(){
System.out.println("我就要将此功能覆盖掉!");
}*/
}
===============================================
public class FinalDemo{
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
六、多态
-
多态是继封装、继承之后,面向对象的第三大特性。
-
什么是多态:
打个比方,现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
-
java中多态的体现
-
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
-
如Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。
-
最终多态体现为父类引用变量可以指向子类对象。
-
-
多态的注意事项
-
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
-
多态是方法的多态,属性没有多态。
-
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法,这样的作用是当父类子类中有同名方法时便于区分子类和父类的方法。
-
-
多态的定义与使用格式
-
多态的定义格式:就是父类的引用变量指向子类对象
-
父类类型 变量名 = new 子类类型();
-
变量名.方法名();
-
Demo代码示例:
//创建一个学生类,在其中定义一下学生独有的一些方法
public class Student extends People {
public void read(){
System.out.println("读书");
}
public void eat(){
System.out.println("吃饭");
}
public void sun(){
System.out.println("逃学");
}
}
//创建人类,在其中定义一些父类的方法
public class People {
//父类独有的方法
private final void god(){
System.out.println("上天");
}
public void eat(){
System.out.println("吃饭");
}
}
//多态
public class Demo01 {
public static void main(String[] args) {
//s1类对象只能调用子类本身存在的方法和继承父类的非私有方法
Student s1 = new Student();
s1.eat();
s1.read();
s1.sun();
s1.read();
//s2类对象只能调用父类本身的方法,子类中的方法无法调用
People s2 = new Student();
s2.eat();
}
}
注:多态是面向对象的一种抽象的思想,重在理解
收集一下好的博客:多态详解