1. 类和对象
1.1 概念
- 万物皆对象
- 面向对象指以属性和行为的观点去分析现实生活中的事物
- 面向对象编程指先以面向对象的思想进行分析,然后使用面向对象的编程语言进行表达的过程
- 对象主要指现实生活中客观存在的实体,在java语言中对象体现为内存空间(堆区)中的一块存储区域
- 类是对具有相同特征和行为的多个对象共性的抽象描述,在Java中体现为一种引用数据类型,里面包含描述属性的成员变量和描述行为的成员方法
1.2 类
类的定义
java class 类名 { 类体; } // 通常情况下,当类名由多个单词组成时,要求每个单词首字母大写
成员变量的定义
java class 类名 { 数据类型 成员变量名 = 初始值; } // 当成员变量由多个单词组成时,通常要求从第二个单词起每个单词的首字母大写
对象的创建
java new 类名(); // 1. 当一个类定义完毕后,可以使用new关键字来创建该类的对象,这个过程叫做类的实列化 // 2. 创建对象的本质是在堆区申请一块存储区域,用于存放该对象独有特征信息
引用的定义> 基本概念
- 使用引用数据类型定义的变量叫做引用性变量,简称为”引用”
- 引用变量主要用于记录对象在堆区中的内存地址信息,便于下次访问
语法格式 - 类名 引用变量名;
- 引用变量名.成员变量名;
Person p = new Person();
p.name = "张飞";
System.out.println(p.name); // 打印张飞
例子```java / 编程实现person类的定义 / public class Person {
// 数据类型 成员变量名 = 初始值; - 其中=初始值 通常省略不写 String name; // 用于描述姓名的成员变量 int age; // 用于描述年龄的成员变量
public static void main(String[] args) {
// 1.声明Person类型的引用指向Person类型的对象
// 数据类型(类名) 引用变量名 = new 类名();
Person p = new Person();
// 2.打印对象中的成员变量值
System.out.println("我是" + p.name + ", 今年" + p.age + "岁了!"); // null 0
System.out.println("-----------------------------------------------------");
// 3.修改成员变量的数值
p.name = "凌寒";
p.age = 18;
System.out.println("我是" + p.name + ", 今年" + p.age + "岁了!");
} } ```
1.3 成员方法
1.3.1 定义
class 类名 {
返回值类型 成员方法名(形参列表) {
成员方法体;
}
}
// 当成员方法名由多个单词组成时,要求从第二个单词起每个单词的首字母大写
1.3.2 返回值
- 主要指从方法体内返回到方法体外的数据
- 返回值的数据类型可以是基本数据类型,也可以是引用数据类型
- 在方法体内使用return关键字可以返回具体的数据内容并结束当前方法
- 如不需要返回任何数据内容时,则返回值类型写void即可
1.3.3 形参列表
- 形式参数主要用于将方法体外的数据内容带入到方法体内部
- 形参列表:由多个形式参数组成的列表,如:
- 数据类型 形参变量名1,数据类型 形参变量名2,……
- 当该方法不需要带入任何数据内容时,则形参列表位置啥也不写即可。
1.3.4 方法体
- 成员方法体主要用于编写描述该方法功能的语句块
- 成员方法可以实现代码的重用,简化代码
1.3.5 方法的调用
- 引用变量名.成员方法名(实参列表)
- 实际参数列表主要用于对形参列表进行初始化,因此参数的个数、类型以及顺序都要完全一致
- 实际参数可以传递直接量、变量、表达式、方法的调用等
1.3.6 可变长参数
- 返回值类型 方法名(参数的类型… 参数名)
- 方法参数部分指定类型的参数个数也是可变的,0~n个
- 一个方法的形参列表中最多只能声明一个可变长形参,并且需要放到参数列表的末尾
1.3.7 参数传递的注意事项
- 基本数据类型的变量作为方法的参数传递时,形参变量数值的改变通常不会影响到实参变量的数值,因为两个变量有各自独立的内存空间
- 引用数据类型的变量作为方法的参数传递时,形参变量指向内容的改变会影响到实参变量指向内容的数值,因为两个变量指向同一块内存空间
- 当引用数据类型的变量作为方法的参数传递时,若形参变量改变指向后,再改变指定的内容,则通常不会影响到实参变量指向内容的改变,因为两个变量指向不同的内存空间
- Java中都是值传递,没有地址传递
1.3.8 内存结构之栈区
- 栈用于存放程序运行过程当中所有的局部变量,一个运行的java程序从开始到结束会有多次方法的调用
- JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为该方法的栈帧。一个栈帧对应一个正在调用中的方法,栈帧中存储了该方法的参数、局部变量等数据
- 当某一个方法调用完成后,其对应的栈帧将被清除
- 引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象
- 当某个引用类型变量为null时,无法对对象实施访问,此时如果通过引用访问成员变量或调用方法,会产生NullPointException异常。
2. 方法和封装
2.1 构造方法
class 类名 {
类名(形参列表) {
构造方法体;
}
}
// 构造方法名与类名完全相同并且没有返回值类型,连void都不许有
// 当一个类中没有定义任何构造方法时,编译器会自动添加一个无参空构造方法,叫做默认/缺省构造方法,
// 如: Person(){}
// 可以定义多个构造方法,如有参,无参
// 使用new关键字创建对象时会自动调用构造方法实现成员变量初始化工作
// 不能主动调用
2.2 方法重载
若方法名称相同,参数列表不同,这样的方法之间构成重载关系(overload)
方法重载的主要形式体现在:
- 参数个数不同
- 参数类型不同
- 参数顺序不同
- 与返回值类型和形参变量名无关,但建议返回值类型最好相同
判断方法能否构成重载的核心:调用方法时能否加以区分
/*
编程实现方法重载主要形式的测试
*/
public class OverloadTest {
// 自定义成员方法
void show() {
System.out.println("show()");
}
void show(int i) {
System.out.println("show(int)"); // ok,体现在方法参数的个数不同
}
void show(int i, int j) {
System.out.println("show(int, int)"); // ok,体现在方法参数的个数不同
}
void show(int i, double j) {
System.out.println("show(int, double)"); // ok,体现在方法参数的类型不同
}
void show(double i, int j) {
System.out.println("show(double, int)"); // ok,体现在方法参数的顺序不同
}
/*void show(double a, int b) {
System.out.println("show(double, int)"); // error, 与参数变量名无关
}
*/
/*int show(double a, int b) {
System.out.println("show(double, int)"); // error, 与返回值类型无关
}
*/
public static void main(String[] args) {
OverloadTest ot = new OverloadTest();
// 调用show方法
ot.show();
ot.show(66);
ot.show(22, 33);
ot.show(22, 3.14);
ot.show(3.14, 22);
}
}
重载的实际意义
方法重载的实际意义在于调用者只需要记住一个方法名就可以调用各种不同的版本,来实现各种不同的功能。
如:java.io.PrintStream类中的println方法
2.3 this关键字
2.3.1 基本概念
- 若在构造方法中出现了this关键字,则代表当前正在构造的对象
- 若在成员方法中出现了this关键字,则代表当前正在调用的对象
- this关键字本质上就是当前类类型的引用变量。感觉像python中的self
- 在构造方法中和成员方法中访问成员变量时,编译器会加上this.的前缀,而this.相当于汉语中的”我的”,当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同,从而this.方式访问的结果也就随之不同。
2.3.2 使用方式
- 当局部变量名与成员变量名相同时,在方法体中会优先使用局部变量(就近原则),若希望使用成员变量,则需要在成员变量的前面加上this.的前缀,明确要求该变量是成员变量。
- this关键字除了可以通过this.的方式调用成员变量和成员方法外,还可以作为方法的返回值。
- 在构造方法的第一行可以使用this()的方式来调用本类中的其它构造方法。
/*
编程实现boy类的定义
*/
public class Boy {
String name;
// 自定义构造方法
Boy() {
// 调用本类中的有参构造方法
//this("无名");
System.out.println("无参构造方法!");
}
Boy(String name) {
// 调用本类中的无参构造方法
this();
System.out.println("==========有参构造方法!");
this.name = name;
}
// 自定义成员方法实现特征的打印
void show() {
System.out.println("我的名字是:" + name);
}
public static void main(String[] args) {
// 1.使用无参方式构造对象并打印
Boy b1 = new Boy();
b1.show();
// 2. 使用有参方式构造对象并打印
Boy b2 = new Boy("张飞");
b2.show();
// 3. 引用变量的数值可以为空
Boy b3 = null;
//b3.show(); // 编译ok, 运行报错NullPointerException空指针异常
}
}
2.4 递归
- 递归本质就是指在方法体的内部直接或间接调用当前方法自身的形式
- 使用递归必须有递归的规律以及退出条件
- 使用递归必须使得问题简单化而不是复杂化
- 若递归影响到程序的执行性能,则使用递推取代之
/*
实现n的阶乘
*/
public class JieCheng {
// 递推方法
int count1(int n) {
int sum = 1;
for(int i = 1; i <= n; i++) {
sum *= i;
}
return sum;
}
// 递归方法
int count2(int n) {
if(1 == n) return 1;
else {
return n*count2(n-1);
}
}
public static void main(String[] args) {
// 实列化
JieCheng jc = new JieCheng();
// 使用递推的方法计算5!
System.out.println(jc.count1(5));
// 使用递归的方法计算5!
System.out.println(jc.count2(5));
}
}
2.5 封装
2.5.1 概念
- 通常情况下可以在测试类给成员变量赋值一些合法但不合理的数值,无论是编译阶段还是运行阶段都不会报错或者给出提示,此时与现实生活不符。
- 为了避免上述错误的发生,就需要对成员变量进行密封包装处理,来隐藏成员变量的细节以及保证成员变量数值的合理性,该机制就叫做封装。
2.5.2 封装的实现流程
- 私有化成员变量,使用private关键字修饰
- 提供公有的get和set方法,并在方法体中进行合理值的判断
- 在构造方法中调用set方法进行合理值的判断
/*
学生类,姓名与学号
*/
public class Student {
// 1.私有化成员变量, 使用private关键字修饰
// private关键字修饰表示私有的含义,也就是该成员变量只能在当前类的内部使用
private String name;
private int id;
// 3. 在公有的构造方法中调用set方法进行合理值的判断
public Student() {}
public Student(String name, int id) {
setName(name);
setId(id);
// setName(name); 和形参的对应顺序并不影响
}
// 2.提供公有的set与get方法读写成员变量,并在方法体中进行合理值判断
// public关键字表示公有的含义,也就是该方法可以在任意位置使用
public int getId() {
return id;
}
public void setId(int id) {
if(id > 0) {
this.id = id;
} else {
System.out.println("学号不合理哦");
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 自定义成员方法实现特征的打印
// 什么修饰符都没有叫做默认的访问权限,级别介于private和public之间
public void show() {
System.out.println("我是" + getName() + ", 我的学号是:" + getId());
}
}
/*
Student类的测试类,输入学生人数,再依次输入学生姓名和学号,最后打印
*/
import java.util.Scanner;
public class StudentTest {
public static void main(String[] args) {
// 1. 输入学生人数
System.out.println("请输入学生人数:");
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
/*Student s1 = new Student();
s1.setId(sc.nextInt());
s1.setName(sc.next());
s1.show();*/
// 2. 生成长度为num,元素类型为Student的一维数组
Student[] arr = new Student[num];
// 3. 循环输入学生姓名和学号(姓名 学号)
for(int i=0; i < num; i++) {
System.out.println("请输入第" + (i+1) + "个学生的姓名和学号:");
// sts[i].setName(sc.next());
// sts[i].setId(sc.nextInt()); 错误,空指针异常
// 为数组中每一个元素新建对象
arr[i] = new Student(sc.next(), sc.nextInt());
}
// 4. 打印所有学生的姓名和学号
for(int i=0; i < num; i++) {
arr[i].show();
}
}
}
2.5.3 JavaBean的概念
使用Java语言编写的可重用组件,本质上就是符合以下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get,set方法
3. static关键字和继承
3.1 static关键字
3.1.1 概念
- 不使用static关键字,成员变量属于对象层级,每个对象都有自己的一份
- 使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关
- static关键字修饰的成员可以使用==引用.的方式访问,但推荐类名.==的方式
3.1.2 使用方式
- 在非静态成员方法中既能访问非静态的成员又能访问静态的成员
- 成员:成员变量+成员方法,静态成员被所有对象共享
- 在静态成员方法中只能访问静态成员不能访问非静态成员
- 因为此时可能还没有创建对象
- 在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰,不能滥用
3.2 构造块和代码块
- 构造块:在类体中直接使用{}括起来的代码块
- 每创建一次对象都会执行一次构造块
- 静态代码块:使用static关键字修饰的构造块
- 静态代码块随着类加载时执行一次
- 执行顺序
- 静态代码块
- 构造块
- 构造方法体
- 父类与子类存在的情况
- 先执行父类的静态代码块,再执行子类的静态代码块
- 执行父类的构造块,执行父类的构造方法体
- 执行子类的构造块,执行子类的构造方法体
3.3 单例设计模式
- 在某些特殊场合中,一个类对外提供且只提供一个 对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式
- 私有化构造方法,使用private关键字修饰
- 声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰
- 提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰
/*
Single,单例设计模式
*/
public class Single {
// 饿汉式 推荐
/*// 1. 私有化构造方法
private Single(){};
// 2.声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰
private static Single s = new Single(); // 好像一个成员变量
// 3.提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰
public static Single getInstance() {
return s;
}
*/
// 懒汉式,调用时再创建对象
private Single() {};
private static Single s = null;
public static Single getInstance() {
if(null == s) {
s = new Single();
}
return s;
}
}
3.4 继承
3.4.1 继承的概念
- 当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为,而在多个类型只需要编写自己独有特征和行为的机制,叫做继承
在Java语言中使用extends(扩展)关键字来表示继承关系
java public class Worker extends Person {} /* 表示Worker类继承自Person类 其中Person类叫做超类、父类、基类 其中Worker类叫做派生类、子类、孩子类
使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件
3.4.2 继承的特点
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承,只是不能直接访问
- 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码super()的效果
- 主动使用super(形参列表)可以选择调用相应的父类有参构造方法,而不调用无参构造方法
- 使用继承必须满足逻辑关系:子类 is a 父类,也就是不能滥用继承
- Java语言中只支持单继承不支持多继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类
3.4.3 方法重写的概念和原则
- 从父类中继承下来的方法不满足子类的需求时,需要在子类中重新写一个方法覆盖继承下来的方法,该方式就叫做方法的重写(override)
- 要求方法名相同,参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型
- 要求方法的访问权限不能变小,可以相同或者变大
- 要求方法不能抛出更大的异常
- 使用注解@Override 若没有构成重写则编译报错
java @Override public void show() { super.show(); // 表示调用父类的show方法 System.out.println("我的薪水是"); }
3.5 常用的访问控制符
修饰符 | 本类 | 同一个包中的类 | 子类 | 其他类 |
---|---|---|---|---|
public | ✓ | ✓ | ✓ | ✓ |
protected | ✓ | ✓ | ✓ | ✗ |
默认 | ✓ | ✓ | ✗ | ✗ |
private | ✓ | ✗ | ✗ | ✗ |
- public修饰的成员可以在任意位置使用
- private修饰的成员只能在本类内部使用
- 通常情况下,成员方法都使用public关键字修饰,成员变量都使用private关键字修饰
3.6 package语句
- 解决命名冲突的问题
- org.apache.commons.lang.StringUtil
- 公司.项目.模块.类名
- 使用import关键字导入包
- 使用import关键字导入静态成员,从Java5.0开始
3.7 final关键字
final本意为”最终的、不可改变的”,可以修饰类、成员方法以及成员变量
- final修饰类体现在该类不能被继承 防止滥用继承
- final修饰成员方法体现在该方法不能被重写但可以继承 防止不经意间造成重写
- final修饰成员变量体现在在该变量必须初始化且不能改变 防止不经意间造成改变
- 显示初始化
- 构造块里初始化
- 构造方法体内初始化
4. 多态,抽象,接口
4.1 多态
多态主要指同一种事物表现出来的多种形态
- 饮料:可乐、雪碧、红牛、……
- 宠物:猫、狗、鸟、……
4.1.1 多态的语法格式
父类类型 引用变量名 = new 子类类型()
Shape sr = new Rect()
4.1.2 多态的特点
- 当父类类型的引用指向子类类型的对象时,父类类型的引用可以直接调用父类独有的方法
- 当父类类型的引用指向子类类型的对象时,父类类型的引用不可以直接调用子类独有的方法
- 对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段调用子类重写的版本(动态绑定`)
- 对于父子类都有的静态方法来说,编译和运行阶段都调用父类版本
4.1.3 引用数据类型之间的转换
- 引用数据类型之间的转换方式:自动类型转换和强制类型转换
- 自动类型转换主要指子类转为父类,也叫做向上转型
- 强制类型转换主要指父类转为子类,也叫做向下转型或显示类型转换
- 引用数据类型之间的转换必须发生在父子类之间,否则编译报错
- 若强转的目标类型并不是该引用真正指向的数据类型时(如多态),则编译通过,运行阶段发生类型转换异常
- 为了避免上述错误发生,应该在强转之前进行判断,格式如
java if(引用变量 instanceof 数据类型) // 判断引用变量指向的对象是否为后面的数据类型
4.1.4 多态的实际意义与使用方式
屏蔽不同子类的差异性实现通用的编程带来不同的效果
- 通过参数传递的方式形成多态
- 参数要求类型为父类,则实参可以传递子类及其下位类
- 由于Object类是所有类的上位类,所以若形参为Object,则所有类都可以作为实参
- 父类类型 引用变量名 = new 子类类型()
- 通过返回值类型形成多态
4.1.5 多态使用方式
- 通过方法的参数传递形成多态;```java public static void draw(Shape s) { s.show() }
draw(new Rect(1,2,3,4)); // 形参要求是父类对象,实参可以传递父类及其下位类对象,多态
- 在方法体中直接使用多态的语法格式```java
Shape s = new Rect();
- 通过方法的返回值类型形成多态
java Calendar getInstance() { return new GregorianCalendar(zone,aLocale); } // 要求的返回值类型是父类,实际返回的是子类
4.2.抽象
抽象方法主要指不能具体实现的方法并且使用abstract关键字修饰,也就是没有方法体
// 访问权限 abstract 返回值类型 方法名(形参列表);
public abstract void cry();
抽象类主要指不能具体实例化的类并且使用abstract关键字修饰,也就是不能创建对象
抽象类与抽象方法的关系
- 抽象类中可以有成员变量、构造方法、成员方法
- 抽象类中可以没有抽象方法,也可以有抽象方法
- 拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是具有抽象方法并且使用abstract关键字修饰的类
抽象类的实际意义
- 抽象类的实际意义不在于创建对象而在于被继承
- 当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是抽象类对于子类具有强制性和规范性,因此叫做模板设计模式
开发经验
- 推荐使用多态的格式,此时父类类型引用直接调用的所有方法一定是父类中拥有的方法,若以后更换子类时,只需要将new关键字后面的子类类型修改而其它地方无需改变就可以立即生效,从而提高了代码的可维护性和可扩展性
- 缺点:父类引用不能直接调用子类独有的方法,若调用则需要强制类型转换
笔试考点
- private 和 abstract 关键字不能共同修饰一个方法
- final 和 abstract 关键字不能共同修饰一个方法和类
- static 和 abstract 关键字不能共同修饰一个方法
4.3 接口
基本概念
- 接口是一种比抽象类还要抽象的类,体现在所有方法都为抽象方法
- 定义类的关键字是class,定义接口的关键字是interface
类和接口之间的关系
名称 | 关键字 | 关系 |
---|---|---|
类&&类 | 使用extends关键字表达继承 | 支持单继承 |
类&接口 | 使用implements关键字表达实现 | 支持多实现 |
接口&接口 | 使用extends关键字表达继承 | 支持多继承 |
抽象类和接口的主要区别
抽象类 | 接口 | |
---|---|---|
定义关键字 | abstract class | interface |
继承与实现 | extends | implements |
单继承 | 多实现 | |
构造方法 | 可以有 | 不可以有 |
可以有成员变量 | 只可以有常量 | |
可以有成员方法 | 只可以有抽象方法 | |
增加方法时 | 子类可以不重写 | 实现类需要重写(Java8以前) |
接口新特性
- 从Java8开始,接口中允许出现非抽象方法和静态方法,但非抽象方法需要使用default关键字修饰
- 实现类不需要重写不需要的非抽象方法
- 从Java9开始,接口允许出现私有方法
- 方便接口内部代码复用
5. 特殊类
5.1 内部类
概念
- 当一个类的定义出现在另外一个类的类体中时,那么这个类叫做内部类(Inner),而这个内部类所在的类叫做外部类(Outer)
实际作用
- 当一个类存在的价值仅仅是为某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,这样可以隐藏该类的实现细节并且可以方便的访问外部类的私有成员而不再需要提供公有的get和set方法
分类
- 普通内部类:直接将一个类的定义放在另外一个类的类体中
- 静态内部类:使用static关键字修饰的内部类,隶属于类层级
- 局部内部类:直接将一个类的定义放在方法体的内部时
- 匿名内部类:就是指没有名字的内部类
5.1.1 普通内部类
格式
访问修饰符 class 外部类的类名 {
访问修饰符 class 内部类的类名 {
内部类的类体;
}
}
使用方式
- 普通内部类和普通类一样可以定义成员变量、成员方法以及构造方法等
- 普通内部类和普通类一样可以使用final或者abstract关键字修饰
- 普通内部类还可以使用private或protected关键字进行修饰
- 普通内部类需要使用外部类对象来创建对象
- outer.new
- 如果内部类访问外部类中与本类内部同名的成员变量或方法时,需要使用this关键字
5.1.2 静态内部类
格式
访问修饰符 class 外部类的类名 {
访问修饰符 static class 内部类的类名 {
内部类的类体;
}
}
使用方式
- 静态内部类不能直接访问外部类的非静态成员
- 静态内部类可以直接创建对象 不需要先创建外部类的对象
- 如果静态内部类访问外部类中与本类内同名的成员变量或方法时,需要使用类名.的方式访问
5.1.3 局部内部类
格式
访问修饰符 class 外部类的类名 {
访问修饰符 返回值类型 成员方法名(形参列表) {
class 内部类的类名 {
内部类的类体;
}
}
}
使用方式
- 局部内部类只能在该方法的内部使用
- 局部内部类可以在方法体内部直接创建对象
- 局部内部类不能使用访问控制符和static关键字修饰符
- 局部内部类可以使用外部方法的局部变量,但是必须是final的,这是由于局部内部类和局部变量的声明周期不同所致
5.1.4 匿名内部类
格式
接口/父类类型 引用变量名 = new 接口/父类类型() {方法的重写};
回调模式
回调模式是指:如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数兑现所实现的方法
- 当接口/类类型的引用作为方法的形参时,实参的传递方式有两种:
- 自定义类实现接口/继承类并重写方法,然后创建该类对象作为实参传递
- 使用匿名内部类的语法格式得到接口/类类型的引用即可
5.2 枚举
5.2.1 概念
一年中所有的季节:春,夏,秋,冬
当描述的事物的所有值都可以一一列举出来,这个列举出来的类型就叫做枚举类型
5.2.2 定义
- 使用public static final表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从Java5开始增加的一种引用数据类型
- 枚举值就是当前类的类型,也就是指向本来的对象,默认使用public static final关键字共同修饰,因此采用枚举类型.的方式调用
- 枚举类可以自定义构造方法,但是构造方法的修饰符必须是private,默认也是私有的
5.2.3 Enum类的概念和方法
- 所有的枚举类都继承自java.lang.Enum类,所以不能继承其他类,但可以实现接口 | 方法 | 效果 | | —- | —- | | static T[] values() | 返回当前枚举类中的所有对象 | | String toString() | 返回当前枚举类对象的名称 | | int ordinal() | 获取枚举对象在枚举类中的索引位置 | | static T valueOf(String str) | 将参数指定的字符串名转为当前枚举类的对象 | | int compareTo(E o) | 比较两个枚举对象在定义时的顺序 |
- 枚举类实现接口后需要重写抽象方法
- 重写一个
- 每个对象都重写
5.3 注解
5.3.1 概念
- 注解(Annotation)又叫标注,是从Java5开始增加的一种引用数据类型
- 注解本质上是代码中的特殊标记,通过这些标记可以在编译、类加载、以及运行时执行指定的处理
5.3.2 格式
访问修饰符 @interface 注解名称 {
public String value(); // 注解成员,只能是成员变量
}
- 自定义注解自动继承java.lang.annotation.Annotation接口
- 通过@注解名称的方式可以修饰包、类、成员方法、成员变量、构造方法、参数、局部变量的声明等
- 如果注解只有一个参数成员,建议使用参数名为value,而类型只能是八种基本数据类型,String类型、Class类型、enum类型及Annotation类型
5.3.3 元注解
- 元注解是一种基本注解,可以应用到其它的注解上面 | 元注解 | 说明 | | —- | —- | | @Retention | 说明该注解的生命周期 | | @Documented | 注解可以被javadoc工具提取成文档 | | @Target | 指定注解可以用于哪些元素的修饰 | | @Inherited | 指定子类可以继承父类的注解 | | @Repeatable | 表示注解可重复 |
5.3.4 常见的预制注解
注解 | 说明 |
---|---|
@author | 标明作者,使用,分割 |
@version | 版本 |
@see | 相关主题 |
@since | 从哪个版本开始增加 |
@param | 对方法中某参数的说明 |
@return | 对方法返回值的说明 |
@exception | 对方法可能抛出的异常进行说明 |
@Override | 限定重写父类方法 |
@Deprecated | 表示所修饰的元素已过时 |
@SuppressWarnings | 抑制编译器警告 |
6.笔试考点
- 请问构造器能否被重写
- 不可以,构造器不能被继承,当然也就不能被重写
- 重载overload和重写override的区别是什么?
- 使用final关键字修饰一个引用变量时,请问是引用不能变还是引用的对象不能变呢?
- 引用不能变,即引用变量中保存的地址不能变
- 简述复制引用和复制对象的区别
- 关于多态,父类类型的引用不可以直接调用子类独有的方法,那应该怎样间接调用呢
- 需要强制类型转换
- 在使用多态过程中,是不是应该主要使用父子类都有的方法,这样如果需要更换子类,新的子类直接重写方法,而原来的地方,使父类指向新的子类就可以了
- 使用父子类都有的非静态方法