JAVA面向对象知识点—全面详解
一、方法
1.什么是方法?
方法就是具有一定功能的代码块
2.为什么用方法
- 划分功能块(利于开发和维护)
- 可以让代码块重新执行
- 方法也是一种封装( 不问细节,只管调用)
3.方法的介绍 :
**方法就是具有一定功能的代码块**
注: java中我们叫方法, 叫其它语言中叫函数, 所以注意方法和函数是一个概念
- 方法格式(语法)
修饰符 返回值类型 方法名(参数类型 参数名1 , 参数类型 参数名2){
? //方法体
? return 返回值;
}
修饰符: 目前的修饰符,就写 public static
返回值类型 : 就是功能结果的数据类型, 没有返回用void 关键字
方法名: 给代码块取一个见名知义的名称,符合规则即可,方便进行调用
参数:
形式参数: 就是在方法定义上的参数, 用于接收实际参数
实际参数: 调用(使用)方法时,实际进行参与的参数
形参与实参的关系: 拷贝(复制)
参数类型: 数据类型
参数名 : 变量名
方法体: 实现特定功能的代码块
return : 结束这个方法; 注: 没有返回值,也可以使用return ,用: return; 表示结束方法
返回值 : 返回的结果 ,由return来返回,返回给调用者
要写好一个方法:
1. 返回值的类型
1. 参数列数
经验: 减少嵌套,可以利用return 来结束方法
4.方法的调用:
方法的特别:不调用方法,方法的代码就不会执行
如何调用方法:
方法名();
//有明确返回值的方法,单独调用没有任何意义
// 1. 单独调用没有任何意义
// zhaZhiJi("苹果");
// 2. 输出调用,但是这种方式也是最好的,因为不一定进行输出
System.out.println(zhaZhiJi("苹果"));
// 3. 赋值调用(推荐)
String str = zhaZhiJi("苹果");
System.out.println(str);
案例:
public static String zhaZhiJi(String shuiguo){
// 进行一系列的工作
return shuiguo +"汁";
}
方法调用内存图
5.方法的分类
根据返回值,参数可以分四类:
无返回值无参函数
无返回值有参函数
有返回值无参函数
有返回值有参函数
写方法的一个原则: 高内聚,低耦合
二、面向对象
1.面向对象的介绍
OO: 面向对象
OOP: 面向对象编程
面向对象是一种思想. 以对象为基础
面向过程也是一种思想,以函数(方法)基础
面向过程与面向对象的区别
面向过程与面向对象都一种编程思想;
面向过程: 一步一步实现,具体功能步骤
面向对象: 创建类,根据类去new 具体的对象,然后调用对象的方法。
面向对象的特点(人 。。。懒)
- 更符合我们的思考习惯
- 把复杂问题给简单化
- 让我们从执行者变成一个指挥者
Java 是一门面向对象的语言(class)
面向过程: 每一个步骤都亲力亲为,一步一步分析然后实现,最终完成
举例:
? 吃饭
? 面向过程: 买菜, 洗菜, 切菜,炒菜, 吃
? 面向对象: 找对象(饭店, 妈妈,外卖) 点菜
? 买电脑
? 面向过程 ;
? 会有电脑相关知识 网上去找(或者去电脑城) 买配件 组装
? 面向对象
? 找对象(doubleyong ) 买电脑
? 洗衣服:
? 面向过程:
? 脱衣服 放到盆子 放洗衣粉 洗 扭水 清3次 晒衣服
? 面向对象
? 脱衣服 把衣服放到洗衣机 启动 晒衣服
? 脱衣服 给你爸爸
程序中如何去使用面向对象的思想
有对象?什么对象:万物皆对象
对象太多了,每个实现不方便? 对对象进行划分类别(分类)
面向对象去开发?
有对象? =》 通过类, 生产去对象
? 模型 创建具体对象
怎么去写类, 把相同对象的信息,行为给他抽象出来
类的内容有哪些呢? 信息和行为
? 学生类
? 信息: 姓名, 年龄, 地址, 家乡,学号,学校,专业
? 行为: 上课,写作业
面向对象思想: 写类 ( 信息和行为)
根据类如何产生对象: 类名 对象名 = new 类名();
案例:
把大象装进冰箱
? 面向过程:
? 打开冰箱 , 把大象放进冰箱 , 关闭冰箱
面向对象:
? 冰箱类
? 信息: 品牌, 大小,颜色 (项目需要的信息)
? 行为: 打开冰箱
? 关闭冰箱
? 大象类:
? 信息: 年龄,体积...
? 行为:
? 进冰箱
? 测试类:
? 冰箱类 对象1 = new 冰箱类 ();
? 大象类 对象2 = new 大象类();
?
? 对象1.打开冰箱();
? 对象2.进冰箱();
? 对象1.关闭冰箱();
java 是一门面向对象的语言. 它提供了class 关键字
面向对象 =》 有对象 =》创建类 =》
根据类生成对象 -> 通过对象,调用方法
怎么创建类,创建哪些类( 一般找名词 )
2.类和对象的关系
类: 具有相同属性和行为一组对象的集合, 类是对对象的抽象
对象:是一个具体的事物
类和对象的关系:
类是对对象的抽象 ,对象是类的实例(具体的).
类的组成:
? 信息 ( 属性) - 变量
? 行为 (方法) - 方法
3.创建类
语法:
修饰符 class 类名{
// 属性
// 方法
}
类名: 符合标识符的命名规则 , 规范: 首字母大写,后面驼峰
// 修饰符 public : 公共的
注: 一个java文件中可以写多个类
// 但是一个Java文件中,只能一个public 修饰的符, 并且 public 修饰的类名和文件名要一致
// 规范: 一个 java 文件只有一个类, 前期为了大家好理解 , 我们会一个文件里写多个类
定义类的属性
修饰符 数据类型 属性名;
// 属性名 首字面小写,后面驼峰
定义类的行为(方法)
方法名 首字面小写,后面驼峰
public static
public
修饰符 返回值类型 方法名(参数类型 参数名1, 参数类型 参数名2 .....){
// 方法体
return 返回值
}
4.创建对象
对象:是类的实例
怎么产生对象( new 一个)
类相当于一个模型,new 类名()相当于根据模型产生的一个具体的对象
?
类名 对象名 = new 类名();
// 在内存中做的操作,顺序
-
加载类,类加载方法区类内容区
-
类名 对象名 ; 在栈中申请一个空间
-
new 类名()在堆中new 一个地址空间
-
把类模板中的属性,创建一份,且赋默认值
-
将堆中对象的内存地址,赋值给对象名
// new 对象时, 会给属性给默认值
// 基本类型
// int byte short long : 默认值 0
// float double 默认值 0.0
// boolean 默认值 false
// char 默认值 ‘\u0000’
// 引用类型( 默认值 : null)
获取对象的属性
对象名.属性名;
对象的属性赋值
对象名.属性名 = 值;
获取对象的方法
对象名.方法名();
5.内存图
一个对象的内存图
二个对象的内存图
三个对象的内存图
6.成员变量与局部变量
以变量的位置进行分类:
可以分为: 成员变量和局站变量
成员变量: 类中方法外
局部变量: 在方法的内部(包括方法里,及方法的声明-形参)
7.成员变量与局部变量的区别
1. 在类中的位置不高
成员变量: 类中方法外
局部变量: 在方法的内部(包括方法里,及方法的声明-形参)
2. 作用的范围不同
成员变量: 类中都可以使用
局部变量:只有定义应该变量的方法可以使用
3. 在内存中的位置不一样
成员变量: 在堆内存中
局部变量:在栈内存中
3. 初始值不同
成员变量:有默认初始化
局部变量:没默认的初始化,必须赋值后才能使用
4. 生命周期不同
成员变量: 随着对象的创建而存在,随着对象的销毁而销毁
局部变量:随着方法的调用而存在,随着方法的执行完成而消失
三 、方法进阶
1.方法的注意事项
1.方法不调用不执行
2.方法和方法是平级关系,不能嵌套定义
3.方法定义的参数用, 隔开
4.方法调用的时候传递的参数不用在前面写数据类型,直接写变量名( 实参不用写数据类型)
5.如果一个方法有明确的返回值类型,一定要用return带回一个值。如果是void,return可以省略不写
6.当方法的返回值类型是void的时候,只能单独直接调用
7.当我在调用一个方法的时候,这两个方法的局部变量没有任何关系
2.方法参数是基本数据类型
变量的类型,如果是基本类型,值是存在栈
变量的类型是引用类型,它的值是存在堆里,然后堆的内存值,赋值给变量
3.方法参数是引用数据类型
方法的参数是引用类型时,实参会存在地址值,赋值给形式; 我们会发现,实参与形参指向的是同一个对象
如果方法的参数是基本类型, 形参的修改,不会影响实参.
如果方法的参数是引用类型, 形参的修改,会导致实参也发生变化 .
4.类作为形式参数的问题?
如果你看到一个方法参数的,参数类型是一个类名,那么记住,它指的是这个类的具体对象(通过这个类new出来的实例对象)。
public void showStudent(Student2 stu2){
stu2.show();
}
5.方法的重载(overload)
Java 允许方法名相同,但是参数类型不能个同,或者参数的个数不同. 这种就叫做方法的重载(在一个类中)
方法重载与返回值类型,没有任何关系
6.方法调用栈
方法调用栈: 方法调用时,用栈来存在方法
数据结构是计算机存储、组织数据的方式。而常用的数据结构有:数组(Array)、栈(Stack)、队列(Queue)、链表(Linked List)、树(Tree)、图(Graph)、堆(Heap)、散列表(Hash)等;
下面我们来给大家介绍 栈和队列 这两种数据结构 :
栈:
队列 :
记住: 栈: 先进后出
? 队列: 先进先出
注: 方法的调用,是用栈来存储的
7.匿名对象
平时对象再创建时,都会取一个名字
类名 对象名 = new 类名();
匿名对象概念: 就是没有名字对象
应用场景:
A: 调用方法,仅仅只调用一次的时候
? 如: new Studnet().hello()
B: 可以作为实参进行传递
? xx.show(new Student())
四、封装
面向对象三大特性: 封装,继承,多态
面向对象四大特性: 封装,继承,多态,抽象 (灵活回答)
面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。
封装可以被认为是一个保护屏障,
防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。
适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
1.封装好处:
-
提高代码的安全性
-
提高代码的易用性(复用性)
-
隐藏了内部的实现,防止外部的修改
2.封装原则(设计原则/ 如何实现封装):
把不想让外界知识的实现细节,给封装起来, 提供公共的访问方式(调用)
3.封装的体现形式:
方法,对象(类), private
4.private 关键字
-
修饰符:
public : 公开的 ( 权限最高)
private : 私有的 -
用到修饰符的地方:
- 成员变量 的定义( 类中方法外的变量)
- 成员方法的定义
- 类的定义
private 的特点
-
private 修饰符,可以修饰成员变量和成员方法, 不能修饰类
-
private 修饰的成员变量和成员方法,只能在本类中访问(使用)
-
外界只能通过公共的方法来间接的调用
使用private 可以让可以在设置属性时,添加自己的业务需求,为什么? 因为它是通过setXX方法去进行修改
5.标准的封装(JavaBean)
class 类名{
// 私有属性
// 成员方法
// setXX 和 getXX
}
6.this关键字
在方法中,如果局部变量与成员变量同名了,采用的是就近原则 ,所以当你使用这个名字,它指的是局部变量
java 提供了一个关键字this, 代表是当前类的对象
注: 哪个对象调用这个方法,该方法内部的this,就代表那个对象
this应用的场景:
- 解决了局部变量隐藏成员问题
- 调用当前类的构造方法 ,如: this(…)
7.this内存图
五、构造方法
1.构造方法
作用是创建对象(对象数据初始化)
2.构造方法的格式
1. 方法名与类名相同
1. 没有返回值 ,连void都没有
3.构造方法可以重载
思考: 构造方法中能不能写return
? 可以的,但是要用 return; 就可以了
? 我们之前一直有在创建对象,可是没有构造方法,请问方法哪里来的? 系统会给一个默认的无参构造函数
注意事项:
-
如果我们没有构造方法,系统会自动给一个无参构造方法
-
如果我们给出构造方法,系统将不会提供无参构造方法, 这个要可以写构造方法,无参与有参都要写
建议: 永远给出无参构造方法
4.类的组成
成员变量
成员方法
构造方法
给成员变量赋值的方法
- 通过setXX方法
- 带参的构造方法
Student s = new Student(“参数”); 做了哪些?
- 把 Student.class 文件加载到内存中
- 在栈中为 s 开辟一块空间
- 在堆中为学生对象申请空间
- 给学生对象的成员变量进行默认初始化: null 0 null
- 给学生对象的成员变量进行显示初始化 : 张三 18 007
- 通过构造方法给成员变量进行初始化 : doubleyong 18 008
- 对象构造完成, 把地址值赋值给s
class Student7{
private String name="张三";
private int age=18;
private String stuNO="007";
public Student7(String name, int age, String stuNO) {
this.name = name;
this.age = age;
this.stuNO = stuNO;
}
public Student7(int age, String stuNO) {
this.age = age;
this.stuNO = stuNO;
}
public Student7(String name) {
this.name = name;
}
public Student7(){
}
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;
}
public String getStuNO() {
return stuNO;
}
public void setStuNO(String stuNO) {
this.stuNO = stuNO;
}
}
public class Demo7 {
public static void main(String[] args) {
Student7 s = new Student7("doubleyong",18,"008");
}
}
什么时候应该用成员变量?
当变量是用来描述类的时候
六、static
1.static的引入
// 1.每个对象单独给国家赋值,发起一个问题,它们都赋值的是中国, 赋值操作是不是重复了?
// 解决方案: 给国家的属性定义显示的默认值, 默认为中国
//2. 画对象的内存图时,发现了问题, 每个对象都国家进行了存储,但是它们值是一样的
// 我们就想,能不能在一个地址存储,其它地方来用就可以了
// 针对多个对象有共同的成员变量的值的时候 , java提供了关键字 static
// 四种修改符: public private default protected
class Person{
private String name; // 姓名
private int age; //年龄
private static String country="中国"; //国家
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;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String country) {
this.name = name;
this.age = age;
this.country = country;
}
public void show(){
System.out.println(name+"---"+age+"---"+country);
}
}
public class Demo10 {
public static void main(String[] args) {
Person p1 = new Person("周星驰",28);
p1.show();
Person p2 = new Person("刘德华",20);
p2.show();
Person p3 = new Person();
p3.setName("张学友");
p3.setAge(60);
p3.show();
}
}
2.static 内存图
哪些属性定义成静态的? 共享的
3.静态变量与静态方法
static 是一个修饰符,修饰成员属性时,称为静态变量, 修饰成员方法,称为静态方法
4.static 的特点
- 随着类的加载而加载
- 优先于对象
- 被类的所有对象共享
- 可以通过类名调用,也可以通过对象名调用,但是推荐使用类名调用
5.static 关键字的注意事项
-
静态方法里没有this关键字(就是不能用this)
如何理解 ?
静态随着类的加载而加载,this是随着对象的创建而存在
-
静态方法只能访问静态变量和静态方法
成员方法:即可以调用成员属性,也可以调用静态属性
记住点:静态的只能访问静态的
6.静态变量与成员变量的区别
所属不同
静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
内存中位置不同
静态变量存储于方法区的静态区
? 成员变量存储于堆内存
内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
? 成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同
静态变量可以通过类名调用,也可以通过对象调用
? 成员变量只能通过对象名调用
7.main方法
public static void main(String[] args){
}
public : 公共的/公开的 访问权限最大, main 方法由jvm调用 ,所以权限足够大
static : 静态的 不需要创建对象,通过类名可以直接调用。方便jvm调用
void : 方法返回值类型给调用者 由jvm调用的 返回值给jvm是没有意义的
main: 是一个常见的方法入口
String[] args : 字符 中数组 ,用户输入的
这个东西是早期的键盘录入,已经被Scanner淘汰了
七、继承
1. 继承的概念
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
-
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名{ }
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
继承中类之间体现的是:"is a"的关系
2.继承的语法
class Fu{
? //相同的属性和行为(公共财产)
}
class Zi extends Fu{
//自己的新的行为和属性
}
public class Demo{
}
3.继承案例
class Person{ //人类
String name;
int age;
public void eat(){
System.out.println("吃饭");
}
}
//学生类
class Student2 extends Person{
}
//老师
class Teacher2 extends Person{
}
public class Demo2 {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.name);
System.out.println(stu.age);
stu.eat();
Teacher teacher = new Teacher();
teacher.name ="doubleyong";
teacher.age = 18;
teacher.eat();
System.out.println(teacher.name);
System.out.println(teacher.age);
}
}
4.继承的优点和缺点
- 继承的优点:
- 提高了代码的复用性
- 提高了代码的维护性
- 让类与类产生了关系,是多态的前提
- 继承的缺点(弊端):
- 让类与类产生了关系 (让耦合增强了)
原则 : 高内聚,低耦合
5.继承的特点
java中继承只能单继承,不能多继承
java中继承支持多层继承
6.继承的注意事项
A. 子类只能继承父类所有的非私有的成员(成员属性和成员方法)
B. 子类不能继承父类的构造方法, 但是可以通过 super关键字去访问父类的构造方法
C:不要为了部分功能而继承
class A{
public void show1(){ }
public void show2() {}
}
class B {
public void show2(){ }
public void show3(){}
}
class B extends A{
public void show3(){}
}
//这样其实不好,为什么呢? 因为不光继承了show2, 还继承了show1
我们什么时候才去使用继承呢?
继承中类之间体现的是:"is a"的关系
Person
? Student
? Teacher
动物
? 狗
? 猫
通过假设法,判断是否满足is-a的关系
如果有两个类A,B , 只要符合A是B的一种,或者B是A的一种,这个时候就可以考虑使用继承
7.继承中成员变量的关系
类的组成:
成员属性
构造方法
成员方法
我们应该考虑一下,继承后类的各部分之间的关系
继承中成员变量的关系
A:子类成员变量与父类成员变量名称不一样 很简单,直接使用名称调用
B:子类成员变量与父类成员变量名称一样
? 子类使用变量,查找的顺序
1. 找子类的局部变量
1. 找子类的成员变量
1. 找父类的成员变量
1. 如果还找不到, 就报错
8.super关键字
- this 与 super 的区别?分别是什么?
? this 代表当前类的对象
? super 代表父类的对象(super 代表父类存储空间的标识 ), 可以通过super去操作父类的属性和方法
- 怎么用?
1.调用成员
this.成员变量;
super.成员变量; super.成员方法();
2.调用构造函数
this(…) 调用本类的构造方法
super(…) 调用父类名的构造方法
9.继承中构造方法的关系
-
子类中所有的构造方法默认都会访问父类的无参构造方法
为什么?
因为子类会继承父类中的数据,可以还会使用父类的数据
所以,子类初始化之前,一定要先完成父类的数据初始化
注: 子类每个构造方法的第一句默认都是:super()
子类初始化之前,一定要先完成父类的数据初始化
一个类的初始化:
- 默认值初始化
- 显示初始化
- 构造方法初始
继承中构造方法的注意事项
如果父类中没有无参构造方法,会怎么
(报错)
? 怎么办?
- 给父类加一个无参构造方法
- 子类通过super(…)去调用有参的父类构造方法
- 子类通过this去调用本类的其他构造方法, 其它的构造方法,必须先访问父类构造方法
注意:
? this(…), super(…) 都必须放到第一个句中, 不放到可能会父类多初始化
10.继承中成员方法的关系
继承中成员方法的关系
-
子类方法和父类方法,声明不一样, 这个很简单
-
子类方法与父类方法,声明一样, 调用哪一个
通过子类调用方法:
a. 先找子类中有没有这个方法,有就使用
b. 再看父类中有没有这个方法,有就使用
c. 如果都没有就报错
class X {
Y b = new Y();
X() {
System.out.print("X");
}
}
class Y {
Y() {
System.out.print ("Y");
}
}
// Y X Y Z
public class Demo9 extends X {
Y y = new Y();
Demo9() {
//super();
System.out.print("Z");
}
public static void main(String[] args) {
new Demo9();
}
}
11.重写
子类与父类方法相同是,我们应用的是子类,所以可以称 子类 重写 父类的方法, java中这种情况为: 重写
重载( overload ) : 在同一个类中, 方法名相同,参数类型不同,或参数的个数,称为重载 (注: 和返回值没有关系)
重写( override ) : 继承关系中, 子类去重写(复写/覆盖)父类已经有的方法,方法的声明要一致(包括方法名,返回值,参数都要一致)
重写的注意事项
-
父类的私有方法不能重写,因为父类的私有方法根本没有办法进行继承
-
子类在重写父类时 权限不能更低 (最好保持一致)
-
父类静态方法,子类必须是静态方法,通过静态方法重写
权限修饰符:
public
private
default
protected
@Override // 通过它检查是否去重写了父类的方法,可以写也可以不写,如果写了,必须是重写的方法,也就是说它的方法名必须和父类中可以重写的方法名中有一个相同
public void call(){
System.out.println("给张三打电话");
}
一句话: 继承可以多层继承
12.final 关键字
final:最终的意思。常见的是它可以修饰类,方法,变量
final修饰的类: 此类就不能被继承了
final修饰的方法: 方法不能被重写(覆盖/复写)
final修饰的变量: 此就是不能被重新赋值,因为被它修饰变量其实就是常量
常量:
1. 字面量常量
“hello”,6,true
2. 自定义常量(符号常量)
final int 常量名= 值; //常量 ,全大写
final修饰局部变量
局部变量:
? 基本类型:值不能变
? 引用类型: 地址值不能变,但地址值指向的堆中存储的数据值可以改变
final只初始化1次;
八、多态
1.多态概述
某一个事物,在不同时刻表现出来的不同状态。
举例:
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。
动物 d= new 猫();
? 猫,即可以叫猫,也可以叫动物
注:new xx赋值时,永远从右边向左边说就错不了
在举一个例子:水在不同时刻的状态 . 水 ( 液体, 固体, 气态)
多态: 同一个对象,在不同时刻体现出来的不同状态
2.多态的前提
A. 要有继承关系
B. 要有方法重写
? 如果没有方法重写,使用意义就不大了
? 动物 d1 = new 狗();
? d1.show()
? 动物 d2 = new 猫();
? d2.show();
? 如上面的案例,如果没有重写,调用的方法一样,就没有了意义
C. 要有父类的引用指向子类
? 父 f = new 子(); //这就是多态
3.多态的案例
class Father{
public void show(){
System.out.println("fu");
}
}
class Son extends Father{
public void show(){
System.out.println("zi");
}
public void method(){
System.out.println("zi mothod");
}
}
public class Demo1 {
public static void main(String[] args) {
// 父类引用指向子类
Father father = new Son();
}
}
4.多态中的成员访问特点
类的成员: 成员变量,成员方法,构造方法
多态中的成员访问特点:
? A: 成员变量(重点)
? 编译看左边, 运行看左边
? B: 构造方法
? 子类的构造都会默认访问父类构造,对父类的数据进行初始化
? C: 成员方法(重点)
? 编译看左边, 运行看右边;
? 为什么呢?
? 因为成员方法有重写(覆盖)
? 结论: 由于成员方法存在方法重写,所以它运行看右边
D: 静态方法(静态与类相关的,其实算不上重写,所以访问的还是左边的)
? 编译看左边,运行也看左边.
5.多态的优缺点
1.多态的缺点
父类不能用子类的特有方法
可是,我就想用子类的特有方法,行不行
? 行
? 怎么用?
A: 创建子类对象调用方法即可. (可以但是很多时候不合理.而且太点内存了) Son son = new Son();
? B: 把父类的用强制转换为子类的引用.....(向下转型)
对象间的转型问题:
向上转型:
? Father f = new Son();
向下转型
? Son son = (Son) f; // 注意: 类型必须要兼容
2.多态的优点
A. 提高了代码的维护性(继承保证)
B. 提高了代码的扩展性(多态来保证的)
6.多态的理解
class 张三爹{
int age = 46;
public void teach(){
System.out.println("法律");
}
}
class 张三 extends 张三爹{
int age = 22;
public void teach(){
System.out.println("音乐");
}
public void paly(){
System.out.println("玩王者");
}
}
public class Demo2 {
public static void main(String[] args) {
// 张三爹 名气很高 很多人请他讲课
// 有一天 张三爹出去讲课了 来了一个人,想邀请张三爹, 给的费用很高
// 但是不在,怎么办? 张三心动
// 伪装成爹 穿上他爹的衣服,带上眼镜, 贴上胡子 外表看已经是他爹的样子
张三爹 fu = new 张三();
System.out.println(fu.age);
fu.teach();
// 下课了,做你自己,脱下你爹装备
张三 son = (张三)fu;
son.paly();
}
}
内存图来理解多态
向下转型的内存图
九、抽象
1.抽象的概述
回想前面我们的猫狗案例提取出了一个动物类。并且我们在前面也创建过了动物对象,其实这是不对的。
为什么呢?
因为,我说动物,你知道我说的是什么动物吗?只有看到了具体的动物,你才知道,这是什么动物。
所以说,
动物本身并不是一个具体的事物,而是一个抽象的事物。
只有真正的猫,狗才是具体的动物。
同理,我们也可以推想,不同的动物吃的东西应该是不一样的,
所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法;该类必须定义为抽象类。
2.抽象类的特点
-
抽象类与抽象 方法用abstract 关键字
-
抽象类中不一定有抽象方法,但是有抽象方法的类,一定要定义为抽象类
-
抽象类不能实例化
因为它不是具体的类,所以不能实例化
抽象类有没有构造方法呢? 有
构造方法方法的作用是什么? 用于子类访问父类的时候进行数据初始化
-
抽象类的子类
- 抽象类的子类也是一个抽象类, 它可以不用去实现抽象方法
- 如果它的子类不是抽象类(具体类),必须重写所有的抽象方法
有了具体的类以后,抽象类可以能过多态来实现实例化
? 抽象类 fu = new 具体类()
3.抽象类的成员特点
成员变量: 即可以变量,也可以是常量
构造方法: 有
? 作用是: 用于子类访问父类的时候进行数据初始化
成员方法:可以是抽象方法, 也可以是非抽象方法( 也可以称为具体方法,或普通方法)
抽象类中的成员方法的特点:
- 是抽象方法 强制要求子类必须做的事情
- 非抽象方法 子类继承父类的事情( 提高代码复用性 )
4.抽象类案例
猫狗案例
分析: 从具体到抽象
? 猫类:
? 成员变量: 姓名,年龄
? 成员方法: 吃饭( 吃鱼),睡觉(趴着)
? 狗类:
? 成员变量: 姓名,年龄
? 成员方法: 吃饭( 吃肉),睡觉(站着)
因为发现上面的多个类中,有共同属性和方法,所以我们提取了一个单独的类,放共同属性和方法,这个类称为 动物 => (继承)
但是,它们吃饭,和睡觉的方法是不一样的, 所以,把吃饭,睡觉写成抽象方法
因为方法是抽象 的,所以类必须是抽象 类
实现: 从抽象到具体
动物类
成员变量 姓名,年龄
构造方法: 有参构造,无参
抽象 方法: 吃饭,睡觉
狗类
继承动物类
构造方法: 有参构造,无参
重写抽象方法
猫
继承动物类
构造方法: 有参构造,无参
重写抽象方法
5.抽象类中的问题
一个类中如果没有抽象方法,可以不定义为抽象类?
? 可以, 为了不让它被实例化
abstract 不能和哪些关键字共存
? private 冲突 错误信息: 非法的修饰符组合: abstract和private
? final 冲突 错误信息: 非法的修饰符组合: abstract和final
? static 冲突 错误信息:非法的修饰符组合: abstract和static
接口
Object类
包装类
StringBuilder , StringBuffer类
十、接口
狗它能钻火圈,可以握手
为了某一个事物,实现额外的功能,就可以使用接口来定义, 然后谁实现了这个接口,谁就可以使用这个功能
1.接口特点
-
用Interface 关键字表示(定义)
interface 接口名{ }
-
类去实现接口用 implements
class 类名 implements 接口名{ }
-
接口不能实例化
接口不能直接实例化,但是可以通过多态来进行实例化
-
接口的的子类
a: 可以是抽象类,但是意义不大
b: 可以用具体的类,要重写接口中的所有方法(推荐)
由些可见:
多类的分类:
1. 具体类的多态( 比较少 ) 1. 抽象类的多态( 常用) 1. 接口的多态(最常用)
2.接口成员特点
- 成员变量: 只能是常量 默认修饰符: public static final
? 建议: 自己手动给出
构造方法: 没有构造方法,因为接口主要是功能的扩展,没有具体的存在
- 成员方法: 只能是抽象方法,默认修饰符: public abstract
? 建议: 自己手动给出
注: 接口实现类: 一般用 接口名+ Impl 命名
3.类与类,类与接口,接口与接口
-
类与类:
继承关系,只能单继承,不能多继承,但是可以多层继承
-
类与接口
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口
-
接口与接口
继承关系,可以单继承,也可以多继承
4.抽象类与接口的区别
-
成员区别:
抽象类: 成员变量: 可以变量,也可以是常量
构造方法 有
成员方法 抽象 方法, 也可以是非抽象 方法
接口 : 成员变量:常量
构造方法 无
成员方法 抽象方法 (jdk8 支持 default 方法 和 static 方法,jkd9 支持 private 方法,供 default 方法调用 ) -
关系区别:
类与类:
继承关系,只能单继承,不能多继承,但是可以多层继承
类与接口:
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时,实现多个接口
接口与接口:
继承关系,可以单继承,也可以多继承
设计理念区别
抽象类: is a 关系 (共性功能)
接口: like a 关系 (扩展功能)
5.接口支持的方法
jdk8之前,接口中的方法,只能定义抽象方法
jdk8 支持方法,default 方法和static方法 . 为什么?
- 默认方法的使用场景包括:
- 为接口添加新的方法,而不会破坏已有代码的兼容性。
- 允许接口提供默认实现,从而减少实现类的工作量。
-
静态方法的使用场景包括:
提供与接口相关的工具方法,这些方法可以在接口中定义为静态方法。
jdk9 支持private 方法,主要是给default 方法
作用
默认方法和静态方法的作用是为了提供更加灵活和方便的接口设计。
十一、方法的参数和返回值
写一个方法时,思考:它的返回值类型
1.参数类型
-
类名作为参数(需要传递的是类的实例对象)
-
抽象类作为参数(需要传递的是, 它的具体要类的实例对象)
-
口作为参数(需要传递的是, 它的实现类的实例对象)
2.返回值
-
类名作为返回值类型: 返回对应类的对象
-
抽象类作为返回值类型: 返回抽象类的具体类的对象
-
接口作为返回值类型: 接口实现类的对象
3.权限修饰符
权限修饰符 本类 同一个包下(子类和无关类) 不同包子类 不同包的无关类
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
4.常见的修饰特点
修饰符:
权限修饰符 private 默认的 protected public
状态修饰符 static final
抽象修饰符 abstract
类
权限修饰符 默认的 public
状态修饰符 final
抽象修饰符 abstract
(以上public用的最多)
成员变量
权限修饰符 private 默认的 protected public
状态修饰符 static final
(用的最多的是private)
成员方法
权限修饰符 private 默认的 protected public
状态修饰符 static final
抽象修饰符 abstract
(用的最多的public)
构造方法
权限修饰符 private 默认的 protected public
(用的最多的public)
组成规则
组成变量 public static final
成员方法 public static
public abstarct
public final
十二、包
1.代码块
代码块: {} 括起来的代码被称为代码块
分类:
局部代码块: 方法中定义的代码块,它的作用主要是限制变量的作用范围
构造代码块:类中的方法外(类的成员位置),每次在构造方法执行之前会先执行构造代码块
作用: 如果多个构造方法中有相同的代码,可以放在构造代码块中
**每个构造方法执行之前,都会先执行构造代码块**
静态代码块:类中的方法外(类的成员位置),用{}括起来,且在前面加上static关键字
作用: 对类进行初始化,仅仅执行1次
代码块的执行顺序 : 静态代码块 > 构造代码块 > 局部代码块
java中包的本质 : 就是文件夹
注:在一个文件夹下面同名的同类型的文件只能出现一个
当有多级目录的时候,java中
包名1.包名2.包名3
直接右键选择创建包, 如:com.gxa.student idea中看到的一个目录文件夹,但是实现上是创建了3个文件夹
创建包: 选择src 右键 new -> package
2.包名的命名规则
包名用小写字母,不要驼峰,不要中文
举例:
学生 增加 删除 修改 查询
老师 增加 删除 修改 查询
方案一:按照功能划分
公司网址的倒序
com.gxa.add
? AddStudent.java
? AddTeacher.java
com.gxa.del
? delStudent.java
? delTeacher.java
方案二:按照模块划分
com.gxa.student
? AddStudent.java
? DelStudent.java
? UpdateStudent.java
? SearchStudent.java
3.怎么在包中放类
使用package 声明这个类在哪一个包下
4.不同包下面的类的访问
使用import 关键字,导入包
导入包的两种方法
-
单类型导入(导一个)
import com.gxa.student.Student;
import com.gxa.student.Person;
-
按需导入
? import com.gxa.student.*;
按需类型导人 (type-import-on-demand), 例如import java. util.*
单类型导入比较好理解,编程所使用的各种工具默认都是按照单类型导入的,
需要什么类便导人什么类,这种方式是导入指定的public类或者接口;
按需类型导入,比如 import java. util. * 可能看到后面的* 程序员会以为是导
入java. util 包下的所有类, 其实并不是这样,Java会根据名字知道是按照需
求导入,并不是导入整个包下的所有类。
按需类型导入是绝对不会降低Java 代码的执行效率的,但会影响到Java代码的编译速度。
所以在编码时最好是使用单类型导入,这样不仅能提高编译速度,也能避免命名冲突。
6.全局导入和局部导入
全局导入 在当前整个类上面都可以使用导入的类
? import com.gxa.find.Teacher;
局部导入 用的非常少 如果要使用的类和全局导入的类名相同,可以使用局部导入 一次性
com.gxa.update.Student s2=new com.gxa.update.Student();
十三、工具类,常用类
封装一些常用的公共的静态方法
工具类一般都静态方法
自己写工具类
1.java 提供的API
API(回顾)
API(Application Programming Interface),应用程序编程接口。Java API是一本程序员的 字典 ,是JDK中提供给我们使用的类的说明文档。这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。所以我们可以通过查询API的方式,来学习Java提供的类,并得知如何使用它们。
API使用步骤
1.打开帮助文档。
1. 点击显示,找到索引,看到输入框。
2. 你要找谁?在输入框里输入,然后回车。(如果输入类名称只有一个直接打开,如果多个则需要选择)
3. **看包。**java.lang下的类不需要导包,其他需要。
4. **看类的解释和说明**。
5. 学习**构造方法**。
6. 使用**成员方法**。
注:java.util.* java中工具类
java.lang.* 该包下的所有的java类 在使用时不需要导入包
2.常用类
Object类/ Scanner类
String类/ StringBuffer类 / StringBuilder类
Arrays类
基本类型包装类(Integer,Character)
正则表达式(Pattern,Matcher)
Math类/Random类/System类
Biglnteger类 / BigDecimal 类
Date类/ DateFormat类 / Calendar类
已经学过: Scanner类, Random类
在java.lang下面的类,可以不用导入.请问为什么? 不需要手导入,它已经自动导入了
java.lang 包是java语言的核心, 它提供了java中的基础类。包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。
String 类 / Math类 / Arrays类
3.String 类
概述
java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如 “abc” )都可以被看作是实现此类的实例。
? 类 String 中包括用于检查各个字符串的方法,比如用于比较字符串,搜索字符串,提取子字符串以及创建具有翻译为大写或小写的所有字符的字符串的副本.
-
特点:
-
字符串不变:字符串的值在创建后不能被更改。
-
因为String对象是不可变的,所以它们可以被共享。
-
“abc” 等效于 char[] data={ ‘a’ , ‘b’ , ‘c’ } 。
-
-
字符串的构造方法
new String(字符串)
new String(char[]);
new String(byte[]);
-
字符串判断方法
public boolean equals (Object anObject) :将此字符串与指定对象进行比较。
public boolean equalsIgnoreCase (String anotherString) :
将此字符串与指定对象进行比较,忽略大小写。
Object 是” 对象”的意思,也是一种引用类型。作为参数类型,表示任意对象都可以传递到方法中。
问题 : equals 与 == 的区别
获取功能的方法
public int length () :返回此字符串的长度。
public String concat (String str) :将指定的字符串连接到该字符串的末尾。
public char charAt (int index) :返回指定索引处的 char值。
public int indexOf (String str) :返回指定子字符串第一次出现在该字符串内的索引。
public String substring (int beginIndex) :返回一个子字符串,从beginIndex开始截取字符串到字符
串结尾。
public String substring (int beginIndex, int endIndex) :返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex。
转换功能的方法
public char[] toCharArray () :将此字符串转换为新的字符数组。
public byte[] getBytes () :使用平台的默认字符集将该 String编码转换为新的字节数组。
public String replace (CharSequence target, CharSequence replacement) :将与target匹配的字符串使用replacement字符串替换。
CharSequence 是一个接口,也是一种引用类型。作为参数类型,可以把String对象传递到方法中。
分割功能的方法
public String[] split(String regex) :将此字符串按照给定的regex(规则)拆分为字符串数组。
? // 该方法的工作原理是通过使用给定表达式和限制参数为零调用双参数[`split`](../../java/lang/String.html#split-java.lang.String-int-)方法。因此,尾随的空字符串不会包含在结果数组中。
4.Math类
Java Math 类的作用
Java Math 类是 Java 标准库中的一个类,它提供了很多数学函数和常量。Java Math 类是一个 final 类,因此不能被继承。它包含了以下常量和方法:
常量:
? E:自然对数的底数
? PI:圆周率
方法:
? abs():返回一个数的绝对值
? max():返回两个数中较大的那个数
? min():返回两个数中较小的那个数
? pow():返回一个数的某个次幂
? sqrt():返回一个数的平方根
? sin():返回一个数的正弦值
? cos():返回一个数的余弦值
? tan():返回一个数的正切值
? log():返回一个数的自然对数
? exp():返回一个数的指数值
? **ceil():返回一个数的上限整数**
? **floor():返回一个数的下限整数**
? **round():返回一个数的四舍五入整数**
? **random()方法可以生成一个范围在0到1之间的随机浮点数。**
5.Arrays类
Arrays.toString()方法
方法作用:快速输出数组内容,可以偷偷懒
int[] a = {1,2,3,4,5};
System.out.println(Arrays.toString(a));
// 输出格式:[1,2,3,4,5]
Arrays.sort()方法
方法运用:给数组排序,默认升序
int[] a = new int[]{5,4,3,2,1};
Arrays.sort(a); // 1 2 3 4 5
System.out.println(Arrays.toString(a));
// [1,2,3,4,5]
https://blog.csdn.net/qq_62939743/article/details/123435767
Arrays.equals()方法
方法作用:比较两个数组内容是否相等
int[] a = {1,2,3};
int[] b = {1,2,3};
boolean isSame = Arrays.equals(a,b);
//true
注意:Arrays.equals()是比较数组内容,而a.equals(b) 这样的方法是比较地址值
以后使用java提供的引用数据内容(数组、字符串、各种集合…)时,一定要用equals()方法比较内容是否相等,而不是傻傻的用 ==了!因为官方已经把equals()给重写了。如果你要比较你自己写的类,例如学生按成绩排序,就要自己重写equals()方法
Arrays.binarySearch()
方法作用:在数组中查找元素
int Arrays.binarySearch( Datatype[], Datatype key)
再数组中查找指定值,若找到,则返回此值的下标,
若没找到,返回 -插入点-1;
如:
int[] a = {1,5,6,7};
Arrays.binarySearch(a,2) //没找到,插入点为1,则返回 -2
Arrays.binarySearch(a,4) //没找到,插入点为1,则返回 -2
Arrays,binarySearch(a,8) //没找到,插入点为4,则返回 -5
Arrays.binarySearch(a,5) //找到了!返回下标 1
只要返回值 ≥ 0 ,就代表找到了。
Arrays.copyOf()
方法作用:拷贝数组
源码如下:第一个参数是原数组,第二个参数是拷贝长度,返回值是将原数组拷贝一份返回
(它的底层其实是调用了System.arrayCopy()方法)
Arrays.copyOf()的拷贝是从下标0开始的,如果你想从其他下表开始,可以使用Arrays.copyOfRange()方法
6.System类
java.lang.System类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作
public static long currentTimeMillis():返回以毫秒为单位的当前时间
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):
将数组中指定的数据拷贝至另一个数组中
参数说明:
src:源数组
srcPos:源数组中的起始位置
dest:目标数组
destPos:目标数组中的起始位置
length:要复制的元素个数
System.arraycopy()方法的性能非常高,因为它是由底层代码实现的,并且能够利用硬件的特性来进行快速的数据复制。它通常比使用循环逐个复制数组元素要快得多。
System.arraycopy() 可以用于向上或向下转型,但在使用时要谨慎,确保数据类型兼容性和运行时类型检查。如果数据类型不匹配,虽然可通过编译,但运行时会跑出运行时异常java.lang.ArrayStoreException。最好的做法是尽量避免不必要的类型转换,以保持代码的清晰性和可维护性。
7.Object 类
Object 是类层次结构的根类.
所有类都直接或间接继承自Object类
构造方法
Object 只有一个构造方法,且是无参构造.
hashCode
int hashCode() 返回哈希码值
不同的对象,返回不同的整数,相同的对象返回相同的整数
getClass();
public final 类<?> getClass(): 返回此Object
的运行时类。
getClass().getName() 返回当前类的名字
toString()
public String toString() : 返回对象的字符串表示形式。
直接输出对象,相当于调用这个对象的toString方法
equals()
equals 与 == 的区别
== :
? 基本类型: 比较的是值是否相等
? 引用类型:比较的是地址值是否相等
equals
? 只能比较引用类型,默认情况也是比较的是地址值是否相等
? 如果,要比较值是否相等,需要重写equals方法
finalize()
protected void finalize() 垃圾回收器回收对象的时候会调用此方法
finalize和final的区别
System.gc(); //运行垃圾加收器
clone()
protected Object clone()
throws CloneNotSupportedException
创建并返回此对象的副本。 “复制”的精确含义可能取决于对象的类。
使用clone ,
- 返回的Object 类型,需要强制向下转型
- 重写clone方法
- 需要处理异常
- 需要实现 Cloneable 接口, 不能实现 CloneNotSupportException
链式调用
stu.getClass().getName(); //一个方法的返回值,必须是一个对象,这样才可以再调用方法
8.String 类
String 类不能被继承,因为被final修饰
String的底层是一个字符数组,因为它被final修饰不能被修改
String str = "abc";
String str2 = "abc";
System.out.println(str==str2);
System.out.println(str.equals(str2));
String str3="hello";
str3+="world";
System.out.println(str3);
构造方法
成员方法
1.字符串常量池
2.StringBuffer类
线程安全,可变的字符序列。 字符串缓冲区就像一个String ,但可以修改。
3.StringBuilder类
一个可变的字符序列。 此类提供与StringBuffer的API,但不保证同步
StringBuilder不能安全使用多线程。 如果需要同步, 那么建议使用StringBuffer
4.构造方法
StringBuilder()
构造一个没有字符的字符串构建器,初始容量为16个字符。
StringBuilder(CharSequence seq)
构造一个包含与指定的相同字符的字符串构建器 CharSequence 。
StringBuilder(int capacity)
构造一个没有字符的字符串构建器,由 capacity参数指定的初始容量。
StringBuilder(String str)
构造一个初始化为指定字符串内容的字符串构建器。
5.成员方法
底层是一个char[] 如果长度不够,创建一个更大长度的数组 自动扩容
int capacity(): 返回容量
int length() : 返回长度
append() ; 追加字符串(加在最后)
insert(int offset , String str):
delete:
deleteCharAt()
replace
String 与 StringBuilder的转换
String - StringBuilder
方法1:
String s = “hello”;
StringBuilder sb = new StringBuilder(s);
方法2:
StringBuilder sb = new StringBuilder();
sb.append(s);
StringBuilder - String
sb.toString();
String str = new String(sb);
java 提供常用类
需求1: 把100 , 转成对应2,8,16进制
需求2:判断一个数据是否在int范围内.
9.Character类
可判断 字符是否为数字,大写字母,小写字母等方法
10.BigInteger类
BigInteger bi = new BigInteger("8");
BigInteger bi2 = new BigInteger("3");
BigInteger biResult = bi.add(bi2);
BigInteger biResult2 = bi.subtract(bi2);
// multiply() :相相乘
// divide(): 相除
System.out.println(biResult);
System.out.println(biResult2);
11.BigDecimal类
注意: 精度不想丢失,使用BigDecimal, 实始化的时,用字符串
BigDecimal bd = new BigDecimal("1");
BigDecimal bd2 = new BigDecimal("3");
BigDecimal addResult = bd.add(bd2);
BigDecimal subResult = bd.subtract(bd2);
BigDecimal mulResult = bd.multiply(bd2);
BigDecimal deResult = bd.divide(bd2,2, RoundingMode.HALF_UP);
12.日期类
1.Date类
Date : 表示特定的瞬间,精确到毫秒
-
构造方法
Date d = new Date(); //返回当前的日期
Date d2 = new Date(毫秒数); // 1970年1月1 0:0:0 + 加上给定的毫秒数,计算出来的日期(考虑时区)
-
方法:
getTime(); //获取日期对应的毫秒数
setTime(); //设置日期到1970-1-1 0:0:0的毫秒数
2.DateFormat类
DateFormat 是日期/时间格式化子类的抽象类。
是抽象类,不能实例化,所以用它的子类SimpleDateFormate
模式:
年 y
月 M
日 d
时 H
分 m
秒 s
Date - > String (格式化)
String -> Date (解析)
// Date - String (格式化)
Date d = new Date();
// xxxx年xxx月xx日 xx:xx:xx
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf.format(d));
// String - Date (解析)
String str2 = "2023-11-20 16:06:55";
// 字符串日期格式,要与SimpleDateFormat给日期模式一致
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d2 = sdf2.parse(str2);
3.Calendar 类
add()
set()
Calendar calendar = Calendar.getInstance(); //获取 Calendar 类的实例对象
//获取年
int year = calendar.get(Calendar.YEAR);
System.out.println(year);
//获取月
int month = calendar.get(Calendar.MONTH);
System.out.println(month);
//获取月
int day = calendar.get(Calendar.DATE);
System.out.println(day);
System.out.println(year+"年"+(month+1)+"月"+day+"日");
十六、包装类
将基本数据类型封装成对象, 让我们可以在对象中定义更多的功能方法来操作数据
- 常用于: 基本类型与字符串之间的转换
? int -> String
? String -> int
1.基本类型与包装类的对应
int -> Integer 类
byte -> Byte 类
short -> Short 类
long -> Long 类
float -> Float 类
double -> Double类
char -> Character 类
boolean -> Boolean
2.int 转 String
// int - String
//方法1:
int num2 = 666;
String s1 = num2 +"";
// 方法2 : 可以用String类里的方法
// static String valueOf(int i)
String s2 = String.valueOf(num2);
System.out.println(s2);
// 方法3 : Integer 类
// new Integer().toString的方法
String s3 = new Integer(num2).toString();
System.out.println(s3);
//方法4: Integer.toString()
String s4 = Integer.toString(num2);
System.out.println(s4);
3.String 转 int
// String - int
// 方法1 :
// 结构调用Integer构造方法
String ss = "666";
Integer integer1 = new Integer(ss);
int i1 = integer1.intValue();
System.out.println(i1);
//方法2 : Integer.parseInt();
int i2 = Integer.parseInt(ss);
System.out.println(i2);
4.自动拆箱与装箱
把int 变成 Integer 的对象,称为装箱
// 666 变成了一个Integer对象, 称为装箱
Integer i = Integer.valueOf(666);
//自动先拆箱,再进行计算,然后,再把计算结果装箱
// i = Integer.valueOf(i.intValue() + 100);
i+=100;
System.out.println(i);
// Integer 的对象 变成 int 基本类型, 称为拆箱
5.Integer缓冲池
Integer 初始化时会创建一个数组, 这个数组会把 -128 到 127 提前放到数组里面
Integer.valueOf()获取Integer类的对象时, 如果这个基本类型的值在-128-127这里范围内,直接返回对应数组存的Integer对象
如果,直接new 就不用缓冲池里的对象了
注: 自动装箱相当于调用的是Integer.valueOf() 方法
Integer integer = Integer.valueOf(666);
Integer integer1 = 666;
Integer i = 128;
Integer i2 = 128;
System.out.println(i==i2);
System.out.println(i.equals(i2));
System.out.println("-------------");
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3==i4);
System.out.println(i3.equals(i4));
System.out.println("-------------");
Integer i5 = new Integer(127);
Integer i6 = new Integer(127);
System.out.println(i5==i6);
System.out.println(i5.equals(i6));
System.out.println("-------------");
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7==i8);
System.out.println(i7.equals(i8));
System.out.println("-------------");
Integer i9 = Integer.valueOf(128);
Integer i10 = Integer.valueOf(128);
System.out.println(i9==i10);
System.out.println(i9.equals(i10));
正则表达式
含义: 是指一个用来描述或者匹配一系列符合某句语法规则的字符串的一个字符串( 就是一种规则 )
举例: 校验qq (5-15位,必须是数字 ,首字符不能是0)
? 手机号码的格式
? email的格式
? 身份证号码的格式
A: 字符
具体字符 x . 如 'a' 表示字符 a
\\ 表示一个反斜线
\n 换行符
\r 回车符
B:字符类 []表示一位字符
[abc] : , 要么a , b 或c
[^abc]: 除a,b,c之外
[a-zA-Z]:a-z或A-Z这个范围内
[0-9]: 0-9字符都包括
C:预定义字符类
. 任何字符。 如果就想让表示 .本身,怎么表示 : \.
\d 相当于 [0-9] 表示数字
\w 相当于 [a-zA-Z_0-9]
\D 相当于 [^0-9] 表示数字
\W 相当于 [^a-zA-Z_0-9]
D: 边界匹配器
^: 以什么开头
$:以什么结尾
F: 数量词
X? X-次或一次也没有
X* X 0次或多次也没有
X+ X 1次或多次也没有
X{n} X恰好n次
X{n,} X至少n次
X{n,m} X, n-m次,不能超过m
lambda表达式
lambda表达式https://blog.csdn.net/weixin_53679823/article/details/132587543
校验qq (5-15位,必须是数字 ,首字符不能是0)
String checkQQ="[1-9][0-9]{4,14}";
// 用到表达式的方法有
// 判断 ,分割,替换,获取
判断
十七、内部类
1.内部类是什么?
在类的内部定义的类。称为这个类的内部类
如: A类中定义了B类, B类就是内部类
2.内部类的访问特点:
1.内部类可以直接访问外部类的成员,包括私有的
2.外部类要访问内部类的成员,必须创建对象
3.内部的划分(根据位置分类)
成员位置(成员内部类)
局部位置(局部内部类)
public class Example02 {
//成员变量
//定义内部类,这就是成员内部类
class Inner{
}
//成员方法
public void show(){
//局部内部类
class Inner2{
}
}
}
4.成员内部类的使用
直接访问成员内部类
A: 在外部内部提供一个方法,返回内部对象
B: 外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
// Outer outer = new Outer();
// outer.method();
Outer.Inner inner = new Outer().new Inner();
inner.show();
5.成员内部类的修饰符
private 为了保证数据的安全性
static 为了让数据访问更方便(内部类用static修饰后,可以把内部类看成外部类的成员);
注意: 被静态修饰的内部类,只能访问外部类的静态成员;
? 静态内部类访问外部类数据 ,必须是用静态修饰
内部类被静态修饰后,方法即可以是静态的,也可以是非静态的;
案例:
有一个人(人有身体,身体内有心脏)
class Body{
? class Heart{
? public void operator(){
? System.out.println(“心脏搭桥”);
? }
? }
}
Body.Heart bh = new Body().new Heart();
bh.operator();
6.局部内部类
局部内部类,可以直接访问外部类的成员
外部内部类,要访问局部内部类,可以创建内部类的对象,通过对象名.方法,去调用内部类的功能
注: 局部内部类内,要使用局部变量, 要求是常量。默认会加final ;所以建议大家,把final修饰加上
为什么?要求局部内部类直的局部变量是常量
因为:局部变量是方法调用完就消失,而内部类上调用方法时,是通过对象去调用,对象调用后,不会立即消失,所以要求局部变量是一常量;
7.匿名内部类
是一个对象
是一个继承了该类或者实现了该接口的子类 的匿名对象
格式:匿名内部类
new 类名或接口名(){
//重写的方法
}
// 传统写法
interface inter1{
void show();
}
class inter1Impl implements inter1{
void show(){
}
}
inter1Impl impl = new inter1Impl();
注: 匿名内部类,只能使用1次。如果需要多次使用类,就单独去写一个类
十八、异常
1.异常概述
异常: 不正常的情况
举例: 周末天气很好,我们出去骑车。骑自行车去成都绿道
? 问题1: 去骑自行车,租车,租车后发现,没有气了
? 问题2: 换一辆,开始骑了, 感觉绿道 ,happy 的不得了, 突然有个小石头,小小摔倒了
? 问题3: 骑着骑着,发现,路段了
概念: 异常指的是在程序的运行过程中发生的不正常的事件
异常体系(异常分类)
? Throwable (超类)
error (严重) Exception
? RuntimeException (运行时异常) 其它(编译时异常)
严重问题: Error 我们不处理。 这种错误太严重了, OutOfMemoryError 计算中觉见的错误,内存溢出
? 问题: Exception
? 编译期问题: 不是RuntimeException 类及它子类的异常,
? 运行期问题: 是RuntimeException 类强它的子类的异步
3.异常体系
4.jvm 默认如何处理异常
如果程序出现异常,我们没有处理,它会打印异常信息到控制台, 并且终止程序
5.Throwable类的常见方法
-
e.printStackTrace() 打印异常信息到控制台( 出现类什么类型的异常+信息+位置)
-
e.getMessage() 异常信息,如果想打印需要自己打印
-
e.toString() 出现类什么类型的异常+信息
注: System.exit(0); 退出程序
6.异常处理
自己处理
? 注:
-
在使用catch 对异常进行处理时,catch声明的异常类型应该和实际抛出的异常类型,相同,或者是继承关系,才能捕获。
-
方法中的异常,可以在方法里进行处理,也可以在调用方法时,进行处理
单个异常处理
? 语法:
try{
可能出现异常的代码块
}catch(异常类型 异常名){
针对这个异常进行处理
}finilly{
都会执行,释放资源相关代码
}
注: try里面的代码越少越好
多个异常处理
try{
可能出现异常的代码块
}catch(异常类型 异常名){
针对这个异常进行处理
}catch(异常类型 异常名){
针对这个异常进行处理
}catch(异常类型 异常名){
针对这个异常进行处理
}
finilly{
都会执行,释放资源相关代码
}
7.抛出异常
throws
通过throws关键字将异常交给调用者来处理, 可以抛出多个异常,多个异常之间用逗号
throws作用:
在定义一个方法的时候可以使用throws关键字声明,使用throws关键字声明的方法表示此方法不处理异常,而交给方法的调用者进行处理
注:
- 调用的方法如果 throws 抛出了异常,调用方法时,要进行处理(1. try … catch … 2. 用throws 向外抛出)
- 重写一个方法时,throws 抛出的异常,父类不能小于子类的范围(子不能比坏)
throw
抛出异常, 可以确定出现异常
语法:
throw new 异常类型("异常信息");
if(num2 == 0){
throw new ArithmeticException("除数不能为0");
}
System.out.println(num/num2);
8.throw 与 throws的区别
-
throws用在方法名后面,跟的是异常类名,throw是用在方法体中,跟的异常对象
-
throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象
-
throws表示抛出异常,由该方法的调用者来处理, throw表示抛出异常,由方法体内的语句处理
-
throws表示出现异常的一种可能性,并不一定发生这些异常,throw则是抛出了具体的异常,真是的产生了一个Exception对象
9.finally
放在finally中的代码,不管程序是否发生异常都会执行
只有程序执行了try块中的代码,finally就都会执行前提是没有执行System.exit ()
try块中写return 也没有用, finally 中的代码还是要执行
组合形式:
try{} catch(){}
try{} catch(){} catch(){} catch(){} ...
try{} finally{}
try{} catch(){} finally{}
try{} catch(){} catch(){} catch(){} ...finally{}
10.return 与 finally 相关的面试题
在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。
在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,
执行完finally之后,在从中取出返回结果,
因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。
public class Example07 {
public static void main(String[] args) {
System.out.println(test());
}
public static int test(){
int x = 1;
try{
x++; // 2
return x; // return 2
}finally {
++x; //3
System.out.println(x); //3
}
}
}
自定义异常
-
用户名不能为空
-
用户名的年龄需要在0-150之间
class MyException extends Exception{
private String message;
public MyException(){
}
public MyException(String message){
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
class Student2{
private int age;
public void setAge(int age) throws MyException{
if(age>=0 && age <= 150){
this.age = age;
}
else{
throw new MyException("年龄必须在0-150之间");
}
}
}
public class Example08 {
public static void main(String[] args) throws MyException {
// String username = "";
// if(username.length() ==0){
// throw new MyException("用户名不能为空");
// }
int age =-1;
Student2 stu = new Student2();
stu.setAge(age);
}
}
ClassCastException: 类不兼容
NullpointException:空指针
ArrayIndexOutofboundException: 数组下标超界
ArithmeticException: 计算出错
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!