引
类和对象想必是每位学习Java同学的痛,因其概念多而杂又抽象。大家应该都听说过这么一句话——Java中一切皆对象!何为对象?对象又从哪里来呢?那么接下来就会为你一一解答。
什么是对象?
在了解什么是对象之前要先知道什么是类
对象是由类创建的由类产生对象的过程称为实例化(通过new关键字来实例化对象)
后面会详细讲到。
面向对象和面向过程
面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。
面向过程则是注重过程
何谓类
简单认识类
类是用来对一个实体(对象)来进行描述的,主要描述该实体(对象)具有哪些属性(外观尺寸等),哪些功能(用来干啥),描述完成后计算机就可以识别了
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.
- 类是一种自定义的类型,可以用来定义变量,但是在java中用类定义出来的变量我们成为对象.
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 通过new 关键字创建一个对象的实例
- 使用点【.】来访问对象中的属性和方法
- 同一个类可以创建多个实例
注意事项:
- 类名注意采用大驼峰定义
- 成员前写法统一为public
- 此处写的方法不带 static 关键字.
类的定义格式
在java中定义类时需要用到class关键字
class为定义类的关键字,ClassName为类的名字,{}中为类的主体
// 创建类
class ClassName{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
定义一个狗类
class PetDog {
public String name;//名字
public String color;//颜色
// 狗的属性
public void barks() {
System.out.println(name + ": 旺旺旺~~~");
}
// 狗的行为
public void wag() {
System.out.println(name + ": 摇尾巴~~~");
}
}
定义一个学生类
public class Student{
public String name;
public String gender;
public short age;
public double score;
public void DoClass(){}
public void DoHomework(){}
public void Exam(){}
}
类的实例化
什么是类的实例化
定义了一个类,就相当于在计算机中定义了一种新的类型,与int,double类似,只不intdouble是java语言自带的内置类型,而类是用户自定义了一个新的类型,比如上述的:Dog、Student类。它们都是类(一种新定义的类型)有了这些自定义的类型之后,就可以使用这些类来定义实例(或者称为对象)
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。
对象的构造及初始化
如何初始化对象
- 通过点这个符号来初始化
- 通过创建一个公开的set方法,然后通过调用这个set方法来初始化
- 通过构造方法来初始化
构造方法
构造方法(也称为构造器)是一个特殊的成员方法,**名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次 **
public class Date {
public int year;
public int month;
public int day;
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法
public Date(){
this.year = 1900;
this.month = 1;
构造方法是干嘛的?
构造方法是用来构造对象的
一个对象的产生-----对象的实例化
1.为对象分配内存
2.调用合适的构造方法(意味着构造方法不止一个)
注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间
构造方法的特点:
1)构造方法 是没有返回值的方法,方法名和类名是一样的
2)构造方法 不止一个,可以有多个,多个构造方法之间,就构成了重载
3)当我们写了一个类之后,没有写构造方法的时候,编译器就会帮我们默认生成一个不带参数的构造方法
4)一个类 至少有一个构造方法
5)构造方法 本质就是来实例化对象的时候调用的。1.分配内存。2.调用合适的构造方法
6)this可以调用本类中其他的构造方法。必须放第一行!所以,只能在当前构造方法当中,调用一个。
封装
什么是封装?
封装可以理解为将某个东西“包装”起来
封装的意义、作用:
封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性
继承
继承:继承从字面的意思就能知道它是拥有了某样的东西,即对共性的一个抽取,使用extends关键字来实现的
>语法:A extends B
则A称作子类,派生类
B称作父类,基类,超类
意义:为了代码的重复使用。
this关键字
java编译器给每个“成员方法“增加了一个隐藏的引用类型参数,该引用参数指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问
this的三种基本用法:
- this.data 调用当前对象的属性
- this.func() 调用当前对象的方法
- this() 调用当前对象的其他构造方法, **this(); 只能存在于构造函数当中! **
super 关键字
super:【不能出现在静态方法中】因为super代表对父类对象的引用
1.super(); 调用父类的构造方法 2.super.func(); 调用父类的普通方法 3.super.date; 调用父类的常用属性 4.super关键字是在子类对象内部指代其父类对象的引用
final 关键字
如果一个类 不想被继承,我可以设置为final修饰 final int a = 10; 修饰常量不能被修改 final class A 代表整个类不可以被继承 final 修饰方法 代表不允许任何从此类继承的类来重写这种方法
重写
在学习多态前,我们得了解一下什么是重写 覆盖/覆写/重写: a、方法名相同 b、参数列表相同(参数个数+参数的类型) c、返回值相同(特殊:返回值也可以是协变类型) 注意: 1.static方法不能重写 2.private修饰的方法 3.final修饰的方法 4.子类方法的访问权限要大于等于父类的访问权限
向上转型
向上转型的概念:即父类的引用 引用子类对象
Animal animal = new Bird();
Bird bird = (Bird) animal;
bird.fly();
向下转型
向下转型的概念:将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的 方法,此时:将父类引用再还原为子类对象即可,即向下转换
向下转型是不安全的。要用instanceof判断,是的话就向下转型,否则不
instanceof用法: 判断animal这个引用所引用对象是否和Bird这个类的实例化的对象相同,或者Bird这个类是animal这个引用的一个子类
Animal animal = new Dog();
if (animal instanceof Bird) {
Bird bird = (Bird) animal;
bird.fly();
}
运行时绑定
运行时绑定(也称动态绑定):通过父类引用 调用父类和子类同名的覆盖方法。即发生了重写(这是实现多态的基础也是必要条件)
编译时绑定
编译时绑定:通过函数的重载实现的。编译的时候,会根据你给的参数的个数和类型,在编译期,确定你最终调用的一个方法 注意: 1、子类继承了父类,那么子类在构造的时候,需要先帮助父类来进行构造。需要在子类的构造方法中,使用super关键字来显式调用父类的构造方法。 2、super和this的区别? 重写和重载的区别? 3、访问修饰限定符。 public:哪里都可以访问 protected:同一个包可以访问。不同包,必须是子类才能访问。 包访问权限:类名前什么都不写即默认为包访问权限,只能在同一个包里面访问 private:只有在当前类中可以访问
多态的好处
使用多态的好处:
- 类调用者对类的使用成本进一步降低。
- 封装是让类的调用者不需要知道类的实现细节
- 多态能让类的调用者连这个类的类型是什么都不必知道,只需知道这个对象具有某个方法即可,因此,多态可以理解成是封装的更进一步,让类调用者对类的使用车成本进一步减低
抽象类
类中有abstract 修饰的方法,称为抽象方法,抽象方法所在的类称为抽象类。
- 包含抽象方法的类,称为抽象类
- 什么是抽象方法,一个没有具体实现的方法,被abstract修饰
- 抽象类不能被实例化。new不了
- 因为不能被实例化,这个抽象类只能被继承!!!
- 抽象类当中,也可以包含,和普通类一样的成员和方法
- 一个普通类,继承了一个抽象类,那么这个普通类当中,需要重写这个抽象类的所有方法。
- 抽象类的最大作用就是为了被继承
- 一个抽象类A,如果继承了一个抽象类B,那么这个抽象类A,可以不实现抽象父类B的抽象方法
- 结合第点,当A类再次被一个普通类继承后,那么A和B这两个抽象类当中的抽象方法,必须被重写。
- 抽象类不能被final修饰,抽象方法也不可以被final修饰
接口
1.使用interface来修饰的 2.接口当中的普通方法,不能够有具体的实现,如果非要实现,只能 通过关键字default来修饰 这个方法。开头加default 3.接口当中可以有static的方法 4.里面的所有的方法都是public的 5.抽象方法,默认是public abstract 的(抽象方法没有具体实现) 6.接口是不可以通过关键字new来实例化的 7.类和接口之间的关系是通过implements实现的 8.当一个类,实现了一个接口,就必须要重写接口当中的抽象方法 9.接口当中的成员变量,默认是public static final 修饰的 10.当一个类实现一个接口之后,重写这个方法的时候,这个方法前面 必须加上public 11.一个类可以以通过关键字extends继承一个抽象类或者普通类,但是只能继承一个类。 同时,也可以通过implements实现多个接口,接口之间使用逗号隔开就好。 12.类和类之间,类和接口之间的关系是通过implements操作的。那么接口和接口之间是怎样的关系呢? 接口和接口之间可以使用extends来操作他们的关系,此时extends意为:拓展。一个接口通过extends来拓展另一个接口的功能。
接口的出现弥补了java中不能继承多个类的缺陷 某种意义上讲接口就是为了多继承而产生的
接口的注意事项:
- 使用interface定义一个接口
- 接口中的方法一定是public,因此可以省略public
- 接口中的方法一定是abstract的抽象方法,因此也可以省略abstract
- 使用implements实现接口,此时表达的不再是“扩展”而是“实现”
- 在调用的时候同样可以创建一个接口的引用,对应到一个子类的实例
- 接口不能单独被实例化
扩展(extends)和实现(implements)的区别:
-
扩展指的是当前已经有一定的功能了,进一步扩充功能
-
实现指的是当前什么都没有,需要从头构造出来
继承:is a的一个关系
接口:什么什么的特性
三个常用接口
Comparable
如果 自定义的数据类型 进行大小比较 一定要实现可以比较的接口 这个接口有一个很大的缺点:对类的入侵性非常强。一旦写好了, 不敢轻易改动。
Comparator
相比于Comparable灵活,对类的入侵性非常弱
Cloneable
用于clone的克隆接口
结语
通过类和对象我们引出了封装、继承、多态、接口等概念,我相信现在大家对类和对象应该有了一个更深刻的印象和理解。