类和对象知识点梳理
1. 类和对象的概念
-
类是对一类事物的描述,是抽象的、概念上的定义。Java 中定义类的关键字是:class。
-
具有相同特征和行为的对象抽象成类,类描述了这一类对象的属性和方法:
- 属性(成员变量)用于存储对象的状态,格式:修饰符 类型 属性名
- 方法(成员方法)用于存储对象的行为,格式:修饰符 返回值 方法名(参数列表){方法体}
public class Emp{ public String name; public int age; public double salary; public void info(){ System.out.println(name+"=="+age+"=="+salary); } }
-
对象(实例):对象是某个类的实例,是实际存在的某个类的个体。
-
Java 中通过类创建对象的关键字是:new。
Emp e1=new Emp();//创建对象
2. 属性和方法
-
属性是用来描述具体某个对象的特征。描述的是对象的状态信息,通常以变量的形式进行定义。
-
方法描述类的行为,命名一般是动词,由方法三要素(返回值,方法名,参数列表)组成。
-
属性和方法的调用
- 属性:对象名.属性;//可赋值可取值
- 方法:对象名.方法名(参数)
Emp e1=new Emp(); e1.name="小王"; e1.info();
-
局部变量和成员变量
局部变量 | 成员变量 | |
---|---|---|
位置 | 方法内 | 类内方法外 |
作用域 | 方法内 | 类内 |
默认值 | 无 | 有 |
内存位置 | 栈 | 堆 |
生命周期 | 方法 | 对象 |
3. 类之间的关系
- 关联:对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系。
- 依赖:对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系
- 聚合:表示一种弱的‘拥有’关系,即 has-a 的关系,体现的是 A 对象可以包含 B 对象,但 B 对象不是 A 对象的一部分。 两个对象具有各自的生命周期。
- 组合:组合是一种强的‘拥有’关系,是一种 contains-a 的关系,体现了严格的部分和整体关系,部分和整体的生命周期一样。
- 实现:实现接口。
- 泛化:继承关系。
4. 封装
-
作用:提高程序的数据安全性。
-
操作:属性私有化,提供公共的 getter/setter 方法访问私有属性。
-
数据安全:数据校验、数据访问。
class Person { private int age; private String name; public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void result() { System.out.print(name+"今年"+age+"岁了!"); } }
5. 构造方法
-
构造方法(构造函数):用于给对象进行初始化,是给与之对应的对象进行初始化,它具有针对性,函数中的一种。
-
作用:完成属性数据初始化操作。
-
时间:对象实例化的时候被调用。
-
存在:若用户不定义,系统会自动生成一个无参的空的构造方法。反之,则系统不会自动生成无参构造方法。
-
特点:
- 方法名和类名相同。
- 没有返回值类型。
class Person { private int age; private String name; public Person(){ } public Person(String name){ this.name=name; } public Person(String name,int age){ this.name=name; this.age=age; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void result() { System.out.print(name+"今年"+age+"岁了!"); } }
6. this&super 关键字
-
this:用来引用当前类的实例变量。
-
this. 属性名:大部分时候,普通方法访问其他方法、成员变量时无须使用 this 前缀,但如果方法里有个局部变量和成员变量同名,但程序又需要在该方法里访问这个被覆盖的成员变量,则必须使用 this 前缀。
public class Person{ public Person(String name,int age){ this.name=name; this.age=age; } }
-
this. 方法名:this 关键字最大的作用就是让类中一个方法,访问该类里的另一个方法。
public class Dog { public void jump() { System.out.println("正在执行 jump 方法"); } public void run() { System.out.println("正在执行 run 方法"); this.jump(); } }
-
this( ) 访问构造方法
public class Person{ public Person(){ this("无名氏"); } public Person(String name){ this(name,20); } public Person(String name,int age){ this.name=name; this.age=age; } }
-
-
super: 可以用来访问父类的构造方法、普通方法和属性。
-
super. 属性名:当子类的成员变量或方法与父类同名时,可以使用 super 关键字来访问。
class Person{ String name="person"; } class Student extends Person{ String name="student"; public void info(){ System.out.println(this.name+"===="+super.name); } }
-
super. 方法名:如果子类重写了父类的某一个方法,即子类和父类有相同的方法定义,但是有不同的方法体,此时,我们可以通过 super 来调用父类里面的这个方法。
class Person{ public void eat(){ System.out.println("Person 吃饭~~~"); } } class Student extends Person{ public void eat(){ System.out.println("学生吃饭吃饭~~~"); } public void info(){ this.eat(); super.eat(); } }
-
super( ) 可以在子类的构造方法中显式地调用父类的构造方法
public class Person { public Person(String name) { } } public class Student extends Person { public Student(String name){ super(name); } }
-
7. 方法重载
-
同一个类中,方法名相同,参数不同(个数不同|类型不同|顺序不同),与方法返回类型和权限无关的方法。
public void println(int i){…} public void println(double d){…} public void println(String s){…}
8. 初始化块
- 作用:将构造方法中具有相同功能的代码抽象成的代码块。
- 本质:编译后,初始化块中的代码会被 copy 到构造方法中,初始化块消失。
- 优点:便于代码维护和扩展。
- 时间:先于构造方法执行。
- 属性值:默认值 -> 初始化块值 -> 构造方法值。
9. 权限修饰符
Java 中一共有四种访问权限控制,其权限控制的大小情况是这样的:public > protected > default(包访问权限) > private , 具体的权限控制看下面表格,列所指定的类是否有权限允许访问行的权限控制下的内容:
访问权限 | 同类 | 同包的类 | 子类 | 非子类的外包类 |
---|---|---|---|---|
public | 是 | 是 | 是 | 是 |
protected | 是 | 是 | 是 | 否 |
default | 是 | 是 | 否 | 否 |
private | 是 | 否 | 否 | 否 |
10. static 静态
- 属性 :静态属性。属于类所有。所有的对象共享。
- 方法 :静态方法。
- 代码块:静态块,静态属性初始化操作。
11. 继承
- 父类:子类相同的属性和行为抽象到父类,必须满足 is-a 关系。
- 都是类(class),父类更抽象、子类更具体。
- 继承:将相同的属性和方法抽象到父类中,子类继承 (extends) 父类,子类就可以继承父类中 public + protected 类型的属性和方法。
- 继承优点:提高维护性和扩展性。
- 子类会默认调用父类无参数的构造方法。
- 重写:父子类中,方法名、参数、返回值都相同。权限不能缩小。
12. 多态
-
定义:同一个对象在不同的环境(开发环境、运行环境)下表现出不同的类型(父类、子类)。
-
使用:在声明数据类型的时候,能用父类用父类,能用接口用接口。(重写父类方法)
-
意义:提高代码重用性,进而提升维护性和扩展性。
public class Test { public static void main(String[] args) { People p=new Stu(); p.eat(); //调用特有的方法 Stu s=(Stu)p; s.study(); //((Stu) p).study(); } } class People{ public void eat(){ System.out.println("吃饭"); } } class Stu extends People{ @Override public void eat(){ System.out.println("吃肉"); } public void study(){ System.out.println("好好学习"); } }
13. Object
Object 是 Java 类库中的一个特殊类,也是所有类的父类。也就是说,Java 允许把任何类型的对象赋给 Object 类型的变量。当一个类被定义后,如果没有指定继承的父类,那么默认父类就是 Object 类。
Object 常用方法:
方法 | 说明 |
---|---|
Object clone() | 创建与该对象的类相同的新对象 |
boolean equals(Object) | 比较两对象是否相等 |
void finalize() | 当垃圾回收器确定不存在对该对象的更多引用时,对象垃圾回收器调用该方法 |
Class getClass() | 返回一个对象运行时的实例类 |
int hashCode() | 返回该对象的散列码值 |
void notify() | 激活等待在该对象的监视器上的一个线程 |
void notifyAll() | 激活等待在该对象的监视器上的全部线程 |
String toString() | 返回该对象的字符串表示 |
void wait() | 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待 |
14. 深拷贝和浅拷贝
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,两个引用对象指向两个对象,但对象内容相同。
浅拷贝:对基本数据类型进行值传递,对引用数据类型复制一个引用指向原始引用的对象,就是复制的引用和原始引用指向同一个对象。
15. final
- 修饰类:最终类,不能被继承。代表是 String
- 修饰属性:常量,不能被修改。
- 修饰方法:最终方法,不能重写。
16. 抽象
- 抽象类:在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,那么这样的类称为抽象类。
- why:为了解决父类不需要实例化对象的问题。
- how:abstract class
- 抽象方法
- why:父类中的一些方法,无法编写合适的方法体。
- how:abstract foo();
- 特点:子类必须重写父类的抽象方法,除非子类也是一个抽象类。
17. 接口
-
接口:抽象类是从多个类中抽象出来的模板,如果将这种抽象进行的更彻底,则可以提炼出一种更加特殊的“抽象类”——接口(Interface)。
-
why:为了解决父类单根性。
-
特点:一个类只能继承(extends)一个父类,但是可以实现(implements)多个接口。
-
功能:1、体现类的能力。2、接口定义一种规范和标准。
-
语法:接口中的属性都是静态常量;接口中的方法都是抽象方法。接口可以多继承。
1.8 后接口中的可定义默认方法和静态方法,它们不算抽象方法。1.9 以后还可以有私有方法。
-
-
面向接口编程
- 定义接口(定义规范和标准)
- 各自按照接口进行开发(面向对象的思想)
- 模块集成 - 项目
18. JVM
当 Java 程序编译后成为 .class 文件 ==> 类加载器(ClassLoader)==> 将字节码文件加载进 JVM 中;
- 方法区、堆:方法区中保存的主要是类的信息(类的属性、成员变量、构造函数等)、堆(创建的对象)。
- 虚拟机栈、程序计数器、本地方法栈:堆中的对象调用方法时,方法会运行在虚拟机栈、程序计数器、本地方法栈中。
- 执行引擎:执行方法中代码时,代码通过执行引擎中的“解释器”执行;方法中经常调用的代码,即热点代码,通过“即时编译器”执行,其执行速度非常快。
- GC(垃圾回收机制):GC 是针对堆内存中没有引用的对象进行回收,可以手动也可以自动。
- 本地方法接口:因为 JVM 不能直接调用操作系统的功能,只能通过本地方法接口来调用操作系统的功能。
19. 单例
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。单例模式可以分为懒汉式和饿汉式等多种形式。
-
单例模式有以下特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
-
饿汉式:不论是否需要都创建对象。
public class Singleton { //先把对象创建好 private static final Singleton singleton = new Singleton(); private Singleton() {} //其他人来拿的时候直接返回已创建好的对象 public static Singleton getInstance() { return singleton; } }
我们上面的案例就是使用的饿汉模式。 这种模式是最简单最省心的,不足的地方是容易造成资源上的浪费,常创建好对象但是没人使用。
-
懒汉式:需要时创建,不需要不创建。
public class Singleton { private static Singleton singleton = null; private Singleton() {} //获取对象的时候再进行实例化 public static Singleton getInstance() { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } return singleton; } }
懒汉模式解决了饿汉模式可能引起的资源浪费问题,因为这种模式只有在用户要使用的时候才会实例化对象。但是这种模式在并发情况下会出现创建多个对象的情况。