Java基础知识(二)
1. 类和对象
1.1 面向对象编程的概念
- 面向对象指以属性和行为的观点去分析生活中的事物
- 面向对象编程指先以面向对象的思想进行分析,然后使用面向对象的编程语言进行表达的过程。
- 面向对象是软件产业化发展的需求
- 面向对象的三大特性:封装、继承、多态
1.2 类和对象及引用
1.2.1 类和对象的概念
- 对象主要是指现实生活中客观存在的实体,在Java语言中体现为内存空间中的一块存储区域。
- 类是对具有多个相同特征和行为的多个对象共性的抽象描述,在Java语言中体现为一种引用数据类型,里面包含了描述特征/属性的成员变量以及描述行为的成员方法。
- 类是用于 构建对象的模板,对象的数据结构由定义它的类来决定。
1.2.2 类与成员变量的定义
/*class 类名{
数据类型 成员变量名 = 初始值;
}*/
class Person{
String name;//成员变量
}
注:
类名,成员变量遵循驼峰原则,即类名每个单词的首字母大写;
成员变量名,要求从第二个单词的首字母开始大写
成员变量的类型 | 默认初始值 |
---|---|
数值类型byte,short,int,long,float,double,char | 0 |
boolean型 | false |
引用类型 | null |
1.2.3 对象的创建
new 类名;
- 当一个类定义完毕后,可以使用new关键字来创建该类的对象,这个过程叫做类的实例化。
- 创建对象的本质就是在内存空间的堆区申请一块存储空间,用于存放改对象独有特征信息。
1.2.4 引用的定义
基本概念:
- 使用引用数据类型定义的变量叫做引用型变量,简称为“引用”。
- 引用变量主要用于记录对象在堆区中的内存地址信息,便于下次访问。
语法格式:
/*
类名 引用变量名;
引用变量名.成员变量名;
*/
Person p = new Person();
p.name = "张飞";
System.out.println(p.name);
1.3 成员方法
1.3.1成员方法的定义
/*
class 类名{
返回值类型 成员方法名(形参列表){
方法体
}
}
*/
class Person{
void show(){
System.out.println("Person类");
}
}
注:
成员方法名由多个单词组成时,要求从第二个单词起每个单词的首字母大写。
1.3.2 返回值、形参列表、方法体的相关详解
返回值:
- 返回值只要指从方法体内返回到方法体外的数据内容。
- 返回值类型只要值返回值的数据类型,可以是基本数据类型,也可以是引用数据类型。
- 在方法体中使用return关键字可以返回具体的数据内容并结束当前方法。
- 当方法不需要返回任何数据内容时,则返回值类型写void即可。
形参列表:
- 形式参数主要用于将方法体外部的数据内容带入到方法体内部。
- 形式参数列表主要指多个形式参数组成的列表,
语法格式为:数据类型 形参变量名1,数据类型 形参变量名2,…… - 若方法不需要带入任何数据内容时,则形参列表位置空着不写即可。
方法体:
- 成员方法主要用于编写描述该方法功能的语句块。
- 成员方法可以实现方法的复用,简化代码。
1.3.3方法的调用
- 引用变量名.成员方法名(实参列表); p.show();
- 实际参数列表主要用于对行书参数列表进行初始化操作,因此参数的个数、类型以及顺序必须完全一致。
- 实际参数列表可以传递直接量、变量、表达式、方法的调用等。
1.3.4 可变长参数
- 格式:返回值类型 方法名(参数的类型…参数名)
- 方法参数部分指定类型的参数个数时可以改变的,也就是0~n个。
- 一个方法的形参列表中最多只能声明一个可变长形参,并且需要放到参数列表的末尾。
1.3.5 方法的传参过程
方法的传参过程:
int max(int ia,int ib){……}
int a = 5; int b = 6;
int res = m.max(a,b);
- 为main方法中的变量a、b、res分配空间并初始化。
- 调用max方法,为max方法中的形参变量ia、ib分配空间。
- 将实参变量的数值赋值到形参变量的内存空间中。
- max方法运行完毕后返回,形参变量空间释放。
- main方法中的res变量得到max方法的返回值。
- main方法结束后释放相关变量的内存空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PfuFvCde-1590224756755)(C:\Users\tangxu\AppData\Roaming\Typora\typora-user-images\1588391464146.png)]
注意:
- 基本数据类型的变量作为方法的参数传递时,形参变量数值的改变通常不会影响到实参变量的数值,因为两个变量有各自独立的内存空间
- 引用数据类型的变量作为方法的参数传递时,形参变量指向内容的改变会影响到实参变量指向内容的数值,因为两个变量指向同一块内存空间
- 当引用数据类型的变量作为方法的参数传递时,若形参变量改变指向后在改变指定的内容,则通常不会影响到实参变量指向内容的改变,因为两个变量指向不同的内存空间。
1.4 内存结构之栈区
- 栈用于存放程序运行过程当中所有的局部变量。一个运行的Java程序从开始到结束会有多次方法的调用。
- JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为该方法的栈帧。一个栈帧对应一个正在调用中的方法,栈帧中存储了该方法的参数、局部变量等数据。
- 当某一个方法调用完成后,七对应的栈帧将被清除。
2. 方法和封装
2.1构造方法
2.1.1基本概念
/*
class 类名{
类名(形参列表){
构造方法体;
}
}
*/
class Person{
Person(){}
}
构造方法名与类名完全相同并且没有返回值类型,连void都不许有。
2.1.2默认构造方法
- 当一个类中没有定义任何构造方法时,编译器会自动添加一个无参的空鼓噪方法,叫做默认/缺省构造方法。
- 若类中出现了构造方法,则编译器不会再提供任何形式的构造方法。
2.1.3作用
使用new关键字创建对象时会自动调用构造方法实现成员变量初始化工作。
不能对一个已经存在的对象调用构造方法来达到重新初始化的母的。
2.2方法重载
2.2.1概念
若方法名称相同,参数列表不同,这样的方法之间构成重载关系(Overload)。
2.2.2 体现形式
- 方法重载的主要形式体现再:参数的个数不同、参数的类型不同、参数的顺序不同,与返回值类型和形参变量名无关,但建议返回值类型最好相同。
- 判断方法能否构成重载的核心:调用方法时能否加以区分。
2.2.3实际意义
方法重载的实际意义在于调用者只需要记住一个方法名就可以调用各种不同的版本,来实现各种不同的功能。
2.3 this关键字
2.3.1基本概念
- 若在构造方法中出现了this关键字,则代表当前正在构造的对象
- 若在成员方法中出现了this关键字,则代表当前正在调用的对象
- this关键字本质上就是当前类类型的引用变量
2.3.2工作原理
在构造方法中和成员方法中访问成员变量时,编译器会加上this.的前缀,而this.相当于汉语中“我的”,当不同的对象调用同一个方法时,由于调用方法的对象不同导致this关键字不同,从而this.方式的访问结果也就随之不同。
2.3.3使用方法
- 当局部变量名与成员变量名相同时,在方法中会有限使用局部变量(就近原则),若希望使用成员变量,则需要在成员变量的前面加上this.的前缀,明确要求该变量时成原变量。
- this关键字除了可以通过this.的方式调用成员变量和成员方法外,还可以作为方法的返回值。
- (了解)在构造方法的第一行可以使用this()的方式来调用本类中的其他构造方法。
注意:
- 引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象。
- 当某个引用类型变量为null时无法对对象实施访问。此时,如果通过引用访问成员变量或调用方法,就会产生空指针异常。
2.4 方法的递归调用
2.4.1 概念
递归本质就是指在方法体的内部直接或间接调用当前方法自身的形式。
注意:
- 使用递归必须有递归的规律以及退出条件
- 使用递归必须使得问题简单化而不是复杂化
- 若递归影响到程序的执行性能,则使用递推取代。
2.5 封装
2.5.2概念
- 通常情况下可以在测试类给成员变量赋值一些合法但不合理的数值,无论在编译阶段还是运行阶段都不会报错或者给出提示,此时与现实生活不符。
- 为了避免上述错误的发生,就需要对成员变量进行密封包装处理,来隐藏成员变量的细节以及保证成员变量数值的合理性,该机制就叫封装。
2.5.3实现流程
- 私有化成员变量,使用private关键字修饰。
- 提供公有的get和set方法,并在方法体中进行合理值的判断。
- 在构造方法中调用set方法进行合理值的判断。
JavaBean的概念:
- JavaBean是一种Java语言写成的可重要组件,其他Java类可以通过反射机制发现和操作这些JavaBean的属性
- JavaBean本质上就是符合一下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
3. static关键字和继承
3.1 static关键字
3.1.1 static关键字概念
- 使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关。
- static关键字修饰的成员可以使用**引用.的方式访问,但推荐类名.**的方式。
3.1.2使用方式
- 在非静态成员方法中既能访问非静态的成员又能访问静态的成员。(成员:成员变量+成员方法,静态成员被所有对象共享)
- 在静态成员方法中只能访问静态成员,不能访问非静态成员。(成员:成员变量+成员方法,因为此时可能还没有创建对象)
- 在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰。(不能滥用static关键字)
3.1.3 构造块和静态代码块
- 构造块:在类体中直接使用{}括起来的代码块
- 每创建一个对象都会执行一次构造块。
- 静态代码块:使用static关键字修饰的构造块。
- 静态代码块随着类加载是执行一次。
笔试考点:
- 先执行父类的静态代码块,在执行子类的静态代码块。
- 执行父类的构造块,执行父类的构造方法体。
- 执行子类的构造块,执行子类的构造方法体。
3.2 继承
3.2.1 继承的概念
- 当多个类之间由相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为,而在多个类型只需要编写自己独有特征和行为的机制,叫做继承。
- 在Java语言中使用extends关键字来表示继承关系。
- 使用继承提高了代码的复用性,可维护性及拓展性,时多态的前提条件。
3.2.2 继承的特点
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承,只是不能直接访问。
- 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码super()的效果。
- 使用继承必须满足逻辑关系:子类 is a 父类,也就是不能滥用继承。
- Java语言中只支持单继承不支持多继承,也就是说一个子类只能由一个父类,但一个父类可以由多个子类。
3.2.3方法重写的概念
从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方式就叫做方法的重写(Override)。
3.2.4 方法重写的原则
- 方法名相同、参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型。
- 方法的访问权限不能变小,可以相同或者变大。
- 方法不能抛出更大的异常。
3.3 访问控制
修饰符 | 本类 | 同一个包中的类 | 子类 | 其他类 |
---|---|---|---|---|
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
protected | 可以访问 | 可以访问 | 可以访问 | 不能访问 |
默认(default) | 可以访问 | 可以访问 | 不能访问 | 不能访问 |
private | 可以访问 | 不能访问 | 不能访问 | 不能访问 |
注意:
- public修饰的成员可以在任意位置使用。
- private修饰的成员只能在本类内部使用。
- 通常情况下,成员方法都是用public关键字修饰,成员变量都使用private关键字修饰。
3.4 final关键字
3.4.1基本概念
final本意为“最终的、不可改变的”,可以修饰类、成员方法以及成员变量。
3.4.2使用方式
- final关键字修饰类体现在该类不能被继承。——主要用于防止滥用继承。
- final关键字修饰成员方法体现在该方法不能被重写但可以被继承。——主要用于防止不经意间造成重写。
- final关键字修饰成员变量体现在该变量必须初始化且不能改变。——主要用于防止不经意间造成改变。
3.4.3常量的概念
- 在以后的开发中很少单独使用final关键字来修饰成员变量,通常使用public static final关键字共同修饰成员变量来表达常量的含义。
- 常量的命名规范要求是所有字母都要大写,不同的单词之间采用下划线连接。
public static final double PI = 3,14;
4. 多态和特殊类
4.1多态
4.1.1 语法格式
//父类类型 引用变量名 = new 子类类型();
Shape sr = new Rect();
sr.show();
4.1.2多态的特点
- 当父类类型的引用指向子类类型的对象是,父类类型的引用可以直接调用父类独有的方法。
- 当父类类型的引用指向子类类型的对象是,父类类型的引用不可以直接调用子类独有的方法。
- 对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段调用子类重写的版本**(动态绑定)**。
- 对于父子类都有的静态方法来说,编译和运行阶段都调用父类版本。
4.1.3引用数据类型之间的转换
-
引用数据类型之间的转换方式有两种:自动类型转化 和 强制类型转换。
-
自动类型转换主要指小类型向大类型的转换,也就是子类转换为父类,也叫做向上转型。
-
强制类型转换主要指大类型想小类型的转换,也就是父类转为子类,也叫做向下转型或显示类型转换。
-
引用数据类型之间的转换必须发生在父子类之间,否则编译报错。
-
若强转的目标类型并不是该引用真正指向的数据类型时则编译通过,运行阶段发生类型转换异常。
-
为了避免上条错误的发生,应该在强转之前进行判断,格式为:
if(引用变量 instanceof 数据类型)//判断引用变量指向的对象是否为后面的数据类型
4.1.4多态的实际意义
多态的实际意义在于屏蔽不同子类的差异性实现通用的编程歹来不同的效果。
4.2抽象类
4.2.1概念
- 抽象方法主要指不能具体的方法并且使用abstract关键字修饰,也就是没有方法体。
- 具体格式为:
//访问权限 abstract 返回值类型 方法名(形参列表);
public abstract void cry();
- 抽象类主要指不能具体实例化的类并且使用abstract关键字修饰,也就是不能创建对象。
4.2.2 抽象类与抽象方法的关系
- 抽象类中可以有成员方法、构造方法、成员方法;
- 抽象类中可以没有抽象方法,也可以有抽象方法;
- 拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是具有抽象方法并且使用abstract关键字修饰的类。
4.2.3抽象类的实际意义
- 抽象类的实际意义不在于创建对象而在于被继承。
- 当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是抽象类对子类具有强制性和规范性,因此叫做模板设计模式。
4.3接口
4.3.1基本概念
接口就是一种比抽象类还抽象的类,体现在所有方法都为抽象方法。
定义类的关键字是class,定义接口的关键字是interface。
4.3.2类与接口之间的关系
名称 | 关键字 | 关系 |
---|---|---|
类与类之间的关系 | 使用extends关键字表达继承关系 | 支持单继承 |
类与接口之间的关系 | 使用implements关键字表达实现关系 | 支持多实现 |
接口和接口之间的关系 | 使用extends关键字表达继承关系 | 支持多继承 |
4.3.3 抽象类和接口的主要区别
-
抽象类中可以有成员方法,而接口中只可以有抽象方法。
-
抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写。(Java8以前的版本)
-
从Java8开始增加新特性,接口中允许出现非抽象方法和静态方法,单费抽象方法需要使用default关键字修饰。
-
从Java9开始增加新特性,接口中允许出现私有方法。
-
定义抽象类的关键字时abstract class,而定义接口的关键字是interface。
-
继承抽象类的关键字是extends,而实现接口的关键字是implements。
-
继承抽象类支持单继承,而实现接口支持多实现。
-
抽象类中可以有构造方法,而接口中不可以有构造方法。
-
抽象类中可以有成员变量,而接口中只可以有常量。
5. 特殊类
5.1 内部类
5.1.1基本概念
当一个类的定义出现在另外一个类的类体中是,那么这个类叫做内部类(Inner),而这个内部类所在的类叫做外部类(Outer)。
类中的内容:成员变量、成员方法、构造方法、静态成员、构造块和静态代码块、内部类。
5.1.2 实际作用
当一个类存在的价值仅仅是为某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,这样就可以隐藏该类的实现细节并且可以方便的访问外部类的私有成员而不需要提供共有的get和set方法。
5.1.3 内部类的分类
- 普通内部类:直接将一个类的定义放在另外一个类的类体中。
- 静态内部类:使用static关键字修饰的内部类,隶属于类层级。
- 局部内部类:直接将一个类的定义放在方法体的内部时。
- 匿名内部类:没有名字的内部类。
5.2 枚举
5.2.1枚举的定义
- 使用public static final 表示的常量猫叔较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从Java5开始增加的一种引用数据类型。
- 枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final关键字共同修饰,因此采用**枚举类型.**的方式调用。
- 枚举类可以自定义构造方法,但是构造方法的修饰符必须是private,默认也是私有的。
5.2.2Enum类的概念和常用方法
所有的枚举类都继承自java.lang.Enum类
static T[] values() | 返回当前枚举类中的所有对象 |
---|---|
String toString() | 放回当前枚举类对象的名称 |
int ordinal() | 获取枚举对象在枚举类中的索引位置 |
static T valueOf(String str) | 将参数指定的字符串名转为当前枚举类的对象 |
int compareTo(E o) | 比较两个枚举对象在定义时的顺序 |
5.2.3枚举类实现接口的方式
枚举类实现接口后需要重写抽象方法。
- 重写一个
- 每个对象都重写
5.3 注解
5.3.1基本概念
注解(Annotation)又叫标注,是从Java5开始增加的一种引用数据类型。
注解本质就是代码中的特殊标记,通过这些标记可以在编译、类加载、以及运行时执行指定的处理。
访问修饰符 @interface 注解名称{
注解成员;
}
- 自定义注解自动继承java.lang.annotation.Annotation接口
- 通过**@注解名称**的方式可以修饰包、类、成员变量、构造方法、参数、局部变量的声明。
5.3.2 注解的使用方式
- 注解体中只有成员变量没有成员方法,而注解的成员变量以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
- 如果注解只有一个参数成员,建议使用参数名为value,而类型只能时八种基本数据类型、String类型、Class类型、enum类型及Annotation类型。
5.3.3元注解
- 可以注解到注解上的注解。元注解是一种基本注解,但是它能够应用到其他的注解上。
类型 | 作用 |
---|---|
@Retention | 用于说明该注解的生命周期 |
@Documented | 使用javadoc工具可以从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档,而该工具抽取时不包括注解内容。 |
@Target | |
@Inherited | |
@Repeatable |