第一章:常用的API
第一节:API概述
1.1 概述
**API:**应用程序编程接口。Java API是一本程序员的字典,是JDK中提供给我们使用的类的说明文档。这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。所以我们可以通过查阅API的方式,来学习Java提供的类,并得知如何使用它们
1.2 API使用步骤
1、打开帮助文档
2、点击显示,找到索引,看到输入框
3、你要找谁,就在输入框里输入,然后回车
4、看包,java.lang下的类不需要导包,其他需要
5、看类的解释和说明
6、学习构造方法
7、使用成员方法
第二节:Scanner类
2.1 什么是Scanner类
**Scanner类的功能:**可以实现键盘输入数据到程序中
引用类型的一般使用步骤:
1、导包
import 包路径.类名称;
在package之后写,但在public之前写
如果需要使用的目标类和当前类位于同一个包下,则可以省略导包语句不写
只有java.lang包下的内容不需要导包,其他的包都需要import语句
2、创建
类名称 对象名=new 类名称();
3、使用
对象名.成员方法名()
package cn....;
import java.util.Scanner;
public class Demo01Scanner{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);//现阶段一成不变
//System.in代表从键盘进行输入
int num=sc.nextInt();//获取键盘输入的一个int数字:
String str=sc.next();//获取键盘输入的一个字符串;
}
}
第三节:匿名对象
3.1 匿名对象的说明
创建对象的标准格式:
类名称 对象名=new 类名称();
匿名对象就是只有右边的对象,没有左边的名字和赋值运算符
new 对象名().成员变量;//定义
注意:匿名对象只能使用唯一的依次,下次使用不得不再创建一个新对象
使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象
3.2 匿名对象作为返回值的参数
public static void main(String[] args){
//普通使用Scanner方式:
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
//匿名对象的方式:
int num=new Scanner(System.in).nextInt();
System.out.println("输入的是:"+num);
//使用一般写法传入参数:
Scanner sc=new Scanner(System.in);
methodparam(sc);
//使用匿名对象来进行传参:
methodparam(new Scanner(System.in));
}
第四节:ArrayList 集合
4.1 对象数组
数组有一个缺点:一旦创建,程序运行期间长度不可以发生改变
public class Demo01Array{
public static void main(String[] args){
//首先创建一个长度为3的数组,里面用来存放Person类型的对象
Person[] array=new Person[3];
Person one =new Person("迪丽热巴",18);
Person two =new Person("古力娜扎",28);
Person three=new Person("玛尔扎哈",38);
//将one当中的地址值赋值到数组0号元素位置
array[0]=one;
array[1]=two;
array[2]=three;
System.out.println(attay[0]);//地址值
System.out.println(attay[1]);//地址值
System.out.println(attay[2]);//地址值
System.out.println(attay[1].getName);//古力娜扎
}
}
4.2 ArrayList 集合概述和基本使用
**与数组的区别:**数组的长度不可以发生改变,但是ArrayList的长度可以发生改变
对于ArrayList来说,有一个代表泛型。
泛型:也就是装在集合当中的所有元素,全部都是统一的什么类型。
注意:1、泛型只能是引用类型,不能是基本类型
2、对于ArrayList集合来说,直接打印得到的不是地址值,而是内容,如果内容是空,得到的是空的中括号,[]
3、创建的时候尖括号泛型说的是什么类型,添加进去的元素就必须是什么类型
package cn.Test2;
import java.util.ArrayList;
public class Arraytest {
public static void main(String[] args) {
//创建了一个ArrayList集合,集合的名称是list,里面装的全都是String字符串类型的数据
//备注:从JDK 1.7+开始,右侧的尖括号内部可以不写内容,但是<>本身还是要写的
ArrayList<String> list=new ArrayList<>();
System.out.println(list);
//向集合中添加一些数据,需要用到add方法
list.add("赵丽颖");
System.out.println(list);
list.add("da");
list.add("as");
System.out.println(list);
}
}
常用方法:(重点)
1、向集合中添加元素,参数的类型和泛型一致,返回值是对应的boolean值 list.add(“想加的元素”);
public boolean add(E e);
2、从集合中获取元素,参数是索引编号,返回值就是对应位置的元素 list.get(索引值);
public E get(int index);
3、从集合中删除元素,参数是索引编号,返回值就是被删除的元素 list.remove(3);
public E remove(int index);
4、获取集合的尺寸长度,返回值是集合中包含的元素个数 list.size();
public int size();
4.3 ArrayList集合存储基本数据
如果希望向集合ArrayList中存储基本类型,必须使用基本类型对应的“包装类”
基本类型 | 包装类(引用类型,包装类都位于java.lang包下) | |
---|---|---|
byte | Byte | |
short | Short | |
int | Integer | 【特殊】 |
long | Long | |
float | Float | |
double | Double | |
char | Character | 【特殊】 |
boolean | Boolean |
在这八个类名中,除了Integer和Character类以后,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。
ArrayList<Integer> list=new ArrayList<>();
list.add(100);
从JDK 1.5+开始,支持自动装箱,自动拆箱
**自动装箱:**基本类型----->包装类型
**自动拆箱:**包装类型------>基本类型
第五节: String类
5.1 字符串概括和特点
String类代表字符串,JAVA程序中的所有字符串字面值(如"abc")都作为此类的实例实现
其实就是说:程序中所有双引号字符串,都是String类的对象(就算没有new,也照样是)
字符串的特点:
1、字符串的内容永不可变【重点】
2、正是因为字符串不可改变,所以字符串是可以共享使用的
3、字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组
5.2 字符串的构造方法和创建方法
创建字符串的常见3+1种方式:
三种构造方法:
public String();//创建一个空白字符串,不含有任何内容
String str1=new String();//小括号留空,说明字符串什么内容都没有
public String(char[] array);//根据字符数组的内容,来创建对应的字符串
char[] charArray={'a','b','c'};
String str2=new String(charArray);//abc
public String(byte[] array);//根据字节数组的内容,来创建对应的字符串
byte[] byteArray={97,98,99};
String str3=new String(byteArray);//abc
一种直接创建:
String str="Hello";//右边直接用双引号
注意:直接写上双引号,就是字符串对象
5.3 字符串的常量池
字符串的常量池:程序当中直接写上的双引号字符串,就在字符串常量中,从JDK1.7开始,常量池在堆中
对于基本类型来说,==是进行数值的比较
对于引用类型来说,==是进行【地址值】的比较
常量池的工作内存图:
注意:
1、对于引用类型来说,==进行的是地址值的比较
2、双引号直接写的字符串在常量池中,new的不在池当中
5.4 字符串的比较相关方法
==是进行对象的地址值比较,如果确实需要字符串的内容比较,可以使用两个方法:
一、严格区分大小写
public boolean equals(Object obj);//参数可以是任何对象,只有参数是一个字符串并且内容相同的才会给true,否则返回flase,任何对象都能用Object进行接收
System.out.println(str1.equals(str2));
System.out.println(str1.equals("Hello"));
System.out.println("Hello".equals(str1));
注意:
1、任何对象都能用Object进行接收
2、equals方法具有对称性,也就是a.equals(b)和b.equals(a)效果一样
3、如果比较双方一个常量一个变量,推荐把常量字符串写在前面
推荐:“abc”.equals(str); 不推荐:str.equals(“abc”);
**当str=null时,不推荐的写法会报错:空指针异常(NullPorinterException)**
二、不区分大小写
public boolean equalsIgnoreCase(String str);//忽略大小写,进行内容比较
System.out.println(str1.equalsIgnoreCase(str2));
System.out.println(str1.equalsIgnoreCase("Hello"));
System.out.println("Hello".equalsIgnoreCase(str2));
注意:只有英文字母区分大小写,其他都不区分大小写
5.4 字符串的获取相关方法
String中与获取相关的常用方法:
public int length();//获取字符串中含有的字符个数,拿到字符串长度
int length="asfahfhlafhla".length();
public String concat(String str);//将当前字符串和参数字符串拼接,返回新的字符串
String str3=str1.concat(str2);
public char charAt(int index);//获取指定索引位置的单个字符(索引从0开始)
char ch="Hello".charAt(1);//e
public int indexOf(String str);//查找参数字符串在本字符串中首次出现的索引位置,如果没有,返回-1
int index=str1.indexOf(str2);
5.5 字符串的截取方法
截取方法:
public String substring(int index);//截取从参数位置一直到字符串末尾,返回新字符串
String str2=str1.substring(5);
public String substring(int begin,int end);//截取区间从begin开始,一直到end结束,中间的字符串,而且是个左闭右开,[begin,end)
String str3=str1.substring(4,7);
5.6 字符串的转换相关方法
String中与转换相关的常用方法:
public char[] toCharArray();//将当前字符串拆分成字符数组作为返回值
char[] chars="Hello".toCharArray();
public byte[] getBytes();//获得当前字符串底层的字节数组
byte[] bytes="Hello".getBytes();
public String replace(CharSequence oldString,CharSequence newString);//将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串.CharSequence意思是可以接受字符串类型
String str1="How do you do?";
String str2=str1.replace("o","*");//H*w d* y*u d*?
5.7 字符串的分割相关方法
分割字符串的方法:
public String[] split(String regex);//按照参数的规则,将字符串切分成为若干部分
String str1="aaa,bbb,ccc";
String[] array1=str1.split(",");//aaa bbb ccc
注意:
split方法的参数其实是一个“正则表达式”,如果要按照英文句点".“进行切分,必须写”\\."(两个反斜杠)
第六节 关键字Static静态
6.1 概述
一旦使用了static关键字,那么这样的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享一份
6.2 static修饰成员
static String room;
6.3 static修饰方法
public void method(){
System.out.println("这是一个普通的成员方法。");
}
public static void methodStatic(){
System.out.println("这是一个静态方法");
}
一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的
如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它
无论是成员变量还是成员方法,如果有了static,都推荐使用类名称进行调用
推荐格式:
静态变量:类名称.静态变量
静态方法:类名称.静态方法()
注意:
1、静态只能直接访问静态,不能直接访问非静态
**原因:因为在内存中是先有静态内容,后有的非静态内容**
2、静态方法中不能用this
原因:this代表当前对象,通过谁调用的方法,谁就是当前对象
6.4 静态static的内存图
在方法区中有一块静态区,专门用来存储静态static类型
注意:根据类名称访问静态成员变量的时候,全程和对象向就没关系,只和类有关系
6.5 静态代码块
格式:
public class 类名称{
static{
//静态代码块的内容
}
}
**特点:**当第一次用到本类时,静态代码块执行唯一的一次
注意:静态内容总是优先于非静态,所以静态代码块比构造方法先执行
静态代码块的典型用途:用来一次性地对静态成员变量进行赋值
第七节:Arrays工具类
7.1 数组工具类Arrays
java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见操作
常见的操作:
public static String toString(数组);//将参数数组变成字符串(按照默认格式:[元素1,元素2,...])
String intstr=Arrays.toString(intArray2);
public static String void sort(数组);//按照默认升序(从小到大)对数组的元素进行排序
Arrays.sort(array);//直接将数组排序,没有返回对应数组
注意:
1、如果是数值,sort默认按照升序从小到大排序
2、如果是字母,sort默认按照字母升序
3、如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持
第八节: Math类
java.utli.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学运算相关的操作
public static double abs(double num);//获取绝对值
System.out.println(Math.abs(3.14));//3.14
System.out.println(Math.abs(0));//0
System.out.println(Math.abs(-2.5));//2.5
public static double ceil(double num);//向上取整
System.out.println(Math.ceil(2.5));//3.0
public static double floor(double num);//向下取整
System.out.println(Math.floor(2.5));//2.0
public static long round(double num);//四舍五入
System.out.println(Math.round(2.5));//3.0
Math.PI//代表近似的圆周率常量(默认为double)
第二章:继承和多态
第一节:继承
1.1:继承的概述
面向对象的三大特征:封装性、继承性、多态性
继承是多态的前提,如果没有继承,就没有多态
继承主要解决的问题是:共性抽取
**父类:**也可以叫做基类、超类
**子类:**也可以叫做派生类
继承关系中的特点:
1、子类可以拥有父类的内容
2、子类还可以拥有自己专有的新内容
1.2:继承的格式
在继承的关系中,子类就是一个父类。(子类可以被当做父类看待)
定义父类的格式:
public class 父类名称{
//...
}
定义子类的格式:
public class 子类名称 extends 父类名称{
//...
}
1.3:继承中成员变量的访问特点
在父子类的继承关系中,如果成员名变量重名,则创建子类对象时,访问有两种方式:
1、直接通过子类对象访问成员变量:等号左边是谁,就优先用谁,没有则向上找
2、间接通过成员方法访问成员变量:该方法属于谁,就优先用谁,没有则向上找
1.4:区分子类方法中重名的三种情况
局部变量: 直接写成员变量名
本类的成员变量: this.成员变量名
父类的成员变量: super.成员变量名
1.5:继承中成员方法的访问特点
在父子类的继承关系中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有就向上找
注意:无论是成员方法还是成员变量,如果没有都是向上找父类,绝不会向下找子类
1.6:方法的覆盖重写
**重写概念:**在继承关系中,方法的名称一样,参数列表也一样
重写(Override):方法的名称一样,参数列表也一样(覆盖、覆写)
重载(Overload):方法的名称一样,参数列表不一样
**方法的覆盖重写特点:**创建的是子类对象,则优先用子类方法
注意:
1、必须保证父子类之间的方法名称相同,参数列表也相同
@Override,写在方法前面,用来检测是否是有效的方法覆盖重写
这个注释就算不写,只要满足要求,也是正确的方法覆盖重写
2、子类方法的返回值必须小于等于父类方法的返回值范围
3、子类方法的权限必须大于等于父类方法的权限修饰符
权限比较:public>protected>(default)>private
(default)不是关键字,而是什么都不写
**设计原则:**对于已经投入使用的类,尽量不要进行修改,推荐定义一个新的类,来重复利用其中共性 内容,并且添加改动新内容
1.7:继承中构造方法的访问特点
继承关系中,父子类构造方法的访问特点:
1、子类构造方法中有一个默认隐含的"super()"调用,所以一定是先调用的父类构造,后执行的子类构造
2、子类构造可以通过super关键字来调用父类重载构造
3、super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造
总结:
子类必须调用父类构造方法,不写则赠送super(),写了则用写的指定的super调用,super只能有1个,还必须是第一个
1.8:关键字super和this的用法
super关键字的用法:
1、在子类的成员方法中,访问父类的成员变量
public void methodzi(){
System.out.println(super.num);//父类中的num
}
2、在子类的成员方法中,访问父类的方法
public void methodzi(){
super.method();//访问父类中的method
}
3、在子类的构造方法中,访问父类的构造方法
public zi(){
super();//可以不写
}
this关键字的用法:
super关键字用来访问父类内容,而this关键字用来访问本类内容
this关键字的用法:
1、在本类的成员方法中,访问本类的成员变量
int num=20;
public void shownum(){
int num=10;
System.out.println(num);//局部变量
System.out.println(this.num);//本类中的成员变量
System.out.println(super.num);//父类中的成员变量
}
2、在本类的成员方法中,访问本类的另一个成员方法
public void methodA(){
System.out.println("AAA");
}
public void methodB(){
this.methodA();
System.out.println("BBB");
}
3、在本类的构造方法中,访问本类的另一个构造方法
注意:A this(…)调用也必须是构造方法的第一个语句,唯一一个
B super和this两种构造调用,不能同时使用
public zi(){
this(123);//本类的无参构造,调用本类的有参构造
}
public zi(int n){
}
1.9:Java继承的三个特点
**1、Java语言是单继承的:**一个类的直接父类只能有唯一一个
2、Java语言可以多级继承
3、一个子类的直接父类是唯一的,但是一个父类可以拥有很多个子类
第二节:抽象类
2.1:抽象的概念
如果父类当中的方法不确定如何进行{}方法体实现,那么这就应该是一个抽象方法
2.2:抽象的方法和抽象的类的格式
**抽象方法:**加上abstract关键字,然后去掉大括号,直接分号结束
**抽象类:**抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可
public abstract class Animal{
public abstract void eat();
}
2.3:抽象方法和抽象类的使用
如何使用抽象类和抽象方法:
1、不能直接创建new抽象类对象
2、必须用一个子类来继承抽象父类
3、子类必须覆盖重写抽象父类中所有的抽象方法
4、创建子类对象进行使用
**覆盖重写(实现):**去掉抽象方法的abstract关键字,然后补上方法体大括号
2.4:抽象方法和抽象类的注意事项
1、抽象类不能创建对象,只能创建其非抽象子类的对象
2、抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的
3、抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类
4、抽象类的子类,必须重写抽象父类中所有的抽象方法,除非子类是抽象类
第三节:接口
3.1 接口概念
**接口:**一种公共的规范标准
只要符合规范标准,大家就可以通用
接口是多个类的公共规范,是一种引用数据类型,最重要的内容就是其中的抽象方法
3.2 接口的定义基本格式
定义接口的格式:
public interface 接口名称{
//接口内容
}
**备注:**换成了关键字interface之后,编译生成的字节码文件依然是.java–>.class
如果是java 7,那么接口中可以包含的内容有:
1、常量
2、抽象方法
如果是java 8,还可以额外包含有:
3、默认方法
4、静态方法
如果是java 9,还可以额外包含有:
5、私有方法
3.3 接口的抽象方法定义
在任何版本的Java中,接口都能定义抽象方法
格式:
public abstract 返回值类型 方法名称(参数列表);
abstract void 方法名称(参数列表);
public void 方法名称(参数列表);
void 方法名称(参数列表);
注意:
1、接口中的抽象方法,修饰符必须是两个固定的关键字:public abstract
2、这两个关键字修饰符,可以选择性的忽略
3、方法的三要素可以随意定义
3.4 接口的使用步骤
1、接口不能直接使用,必须有一个“实现类”来“实现”该接口
格式:
public class 实现类名称 implements 接口名称{
//...
}
2、接口的实现类必须覆盖重写(实现)接口中所有的抽象方法
实现:去掉abstract关键字,加上方法体大括号
3、创建实现类的对象,进行使用
注意:如果实现类没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类
3.5 接口的默认方法
从Java 8开始,接口里允许定义默认方法
格式:
public default 返回值类型 方法名称(参数列表){
方法体
}
备注:接口中的默认方法可以解决接口升级问题
总结:
1、接口的默认方法,可以通过接口实现类对象直接调用
2、接口的默认方法,也可以被接口实现类进行覆盖重写
3.6 接口的静态方法
从Java 8开始,接口中允许定义静态方法
格式:
public static 返回值类型 方法名称(参数列表){
方法体
}
提示:就是将abstract或者default换成static即可,带上方法体
注意:不能通过接口实现类的对象来调用接口当中的静态方法
正确用法:通过接口名称,直接调用其中的静态方法
格式:
接口名称.静态方法名(参数);
3.7 接口的私有方法
需求:我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题,但是这个公共方法不应该让实现类使用,应该是私有化的
从Java9 开始,接口当中允许定义私有方法
私有方法的种类:
1、普通私有方法:解决多个默认方法之间重复代码问题
格式:
private 返回值类型 方法名称(参数列表){
方法体
}
2、静态私有方法:解决多个静态方法之间重复代码问题
格式:
private static 返回值类型 方法名称(参数列表){
方法体
}
3.8 接口的常量定义和使用
接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰
从效果上看,这其实就是接口的**【常量】**
格式:
public static final 数据类型 常量名称=数据值;
都能用 能.出来 不可变
例:public static final int num=10;//这其实就是一个常量,不可以修改
注意:
1、接口当中的常量,可以省略public static final,不写也照样是这样
2、接口当中的常量,必须进行赋值,不能不赋值
3、接口当中常量的名称,使用完全大写的字母,用下划线进行分隔(推荐命名规则)
3.9 内容小结
在Java 9+版本中,接口的内容可以有:
1、成员变量其实是常量,格式:
[public] [static] [final] 数据类型 常量名称=数据值;
注意:常量必须进行赋值,而且一旦赋值不能改变,变量名称完全大写,用下划线进行分隔
2、接口中最重要的就是抽象方法,格式:
[public] [abstract] 返回值类型 方法名称(参数列表);
注意:实现类必须覆盖重写接口中所有的抽象方法,除非实现类是抽象类
3、从Java 8开始,接口里允许定义默认方法,格式:
public default 返回值类型 方法名称(参数列表){
方法体
}
注意:默认方法也可以被覆盖重写
4、从Java 8开始,接口里允许定义静态方法,格式:
[public] static 返回值类型 方法名称(参数列表){
方法体
}
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
5、从Java 9开始,接口里允许定义私有方法,格式:
普通私有方法:
private 返回值类型 方法名称(参数列表){
方法体
}
静态私有方法:
private static 返回值类型 方法名称(参数列表){
方法体
}
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用
使用接口的时候,需要注意:
1、接口是没有静态代码块或构建方法的
2、一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
格式:
public class MyInterfaceImp implments MyInterfaceA,MyInterfaceB{
//覆盖重写所有抽象方法
}
3、如果实现类所实现的多个接口中,存在重复的抽象方法,那么只需要覆盖重写一次即可
4、如果实现类没有覆盖重写所有接口中的所有抽象方法,那么实现类就必须是抽象类
5、如果实现类所实现的多个接口中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
6、一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,会优先用父类中的方法
3.10 接口之间的多继承
1、类与类之间是单继承的,直接父类只有一个
2、类与接口之间是多实现的,一个类可以实现多个接口
3、接口与接口之间是多继承的
注意:
1、多个父接口中的抽象方法如果重复,没关系
2、多个父接口中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写,【而且带着default关键字】
第四节:多态
4.1 概述:
面向对象三大特征:封装性、继承性、多态性
extends继承或者implements实现,是多态性的前提
**对象的多态性:**一个对象拥有多种形态
4.2 多态的使用和说明
代码当中体现多态性,其实就是一句话:父类引用指向子类对象
格式:
父类名称 对象名=new 子类名称();
或者:
接口名称 对象名=new 实现类名称();
访问成员变量的两种方式:
1、直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找
2、间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找
第五节:final关键字
5.1 概述
final:最终不可改变的
常见四种用法:
1、可以用来修饰一个类
2、还以用来修饰一个方法
3、还可以用来修饰一个局部变量
4、还可以用来修饰一个成员变量
5.2 final关键字用来修饰一个类
当final关键字用来修饰一个类时,格式:
public final class 类名称{
//...
}
**含义:**当前这个类不能有任何的子类,即不能使用final类作为父类
注意:一个类如果是final类,那么其中所有的成员方法都无法进行覆盖重写
5.3 final关键字用于修饰成员方法
当final关键字用来修饰一个方法的时候,这个方法就是最终方法,也就是不能被覆盖重写
格式:
修饰符 final 返回值类型 方法名称(参数列表){
//方法体
}
注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾
5.4 final关键字用于修饰局部变量
一旦使用final用来修饰局部变量,那么这个变量就不能进行修改,一次赋值,终生不变
final int num=200;//不可再改变num的值了
final int numb;
numb=100;//正确写法,只要保证只有唯一一次赋值即可
不变:对于基本类型来说,不可改变的是变量当中的数据,对于引用类型来说,不可变的是变量中的地址值,但其中的数据可以改变
final Student stu2=new Student("aa");
stu2=new Student("bb");//错误写法,final的引用类型变量,其中的地址不可改变
5.5final关键字用于修饰成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变的
1、由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了
2、对于final的成员变量,要么进行直接赋值,要么进行构造方法赋值(二者选其一)
3、必须保证类中所有重载的构造方法,都最终会对final的成员变量进行赋值
第六节:四种权限修饰符
四种权限修饰符: public>protect>(default)>private
同一个类(我自己) YES YES YES YES
同一个包(我邻居) YES YES YES NO
不同包子类(我儿子) YES YES NO NO
不同包非子类(陌生人) YES NO NO NO
第七节:内部类
7.1 内部类的概念与分类
如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类
分类:
1、成员内部类
2、局部内部类(包含匿名内部类)
7.2 成员内部类
定义格式:
修饰符 class 外部类名称{
修饰符 class 内部类名称{
/...
}
//...
}
注意:内用外,随意访问;外用内,需要借助内部类对象
如何使用:
**1、间接方式:**在外部类的方法当中使用内部类,然后main只是调用外部类的方法
Body body=new Body();
body.methodBdy();
**2、直接方式:**公式:外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();
Body.Heart heart=new Body().new Heart();
heart.beat();
内部类的同名变量访问:
如果出现了重名现象,那么格式是:
外部类名称.this.外部类成员变量名
public class Outer{
int num=10;
public class Inner{
int num=20;
public void methodInter(){
int num=30;//内部类方法的局部变量
System.out.println(num);//局部变量,就近原则
System.out.println(this.num);//内部类的成员变量
System.out.println(Outer.this.num);//外部类的成员变量
}
}
}
7.4 局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类
**“局部”**只有当前所属方法才能使用它,出了这个方法外面就不能用了
定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//...
}
}
}
定义一个类时,权限修饰符规则:
1、外部类:public/(default)
2、成员内部类:public/protected/(default)/private
3、局部内部类:什么都不能写
注意:局部内部类如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】
备注:从Java 8+开始,只要局部变量不变,那么关键字final关键字可以省略
原因:
1、new出来的对象在堆内存当中
2、局部变量是跟着方法走的,在栈内存当中
3、方法运行结束之后立刻出栈,局部变量就会立刻消失
4、new出来的对象会在堆内存中持续存在,知道垃圾回收消失
7.5 匿名内部类
如果接口的实现类(或者父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略该类的定义,而改写为使用**【匿名内部类】**
匿名内部类的定义:
格式:
接口名称 对象名=new 接口名称(){
//覆盖重写所有抽象方法
};
**对格式进行解析:**new 接口名称(){…}
1、new代表创建对象的动作
2、接口名称就是匿名内部类需要实现哪个接口
3、{…}这才是匿名内部类的内容
注意:
1、匿名内部类,在【创建对象】时,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样,那么必须使用单独定义的实现类
2、匿名对象,在【调用方法】的时候,只能调用唯一一次
如果希望同一个对象调用多次方法,那么就必须给对象起个名字
3、匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略【对象名称】
强调:匿名内部类和匿名对象不是一回事
第三章:常用的API第二部分
第一节:Object类
Object类的equals方法
Person类默认继承了Object类,所以可以使用Object类的equals方法
boolean equals(Object obj)指示其他某个对象是否与此对象“相等”
参数:Object obj :可以传递任意的对象
obj:传递过来的参数
基本数据类型:比较的是值
引用数据类型:比较的是两个对象的地址值
哪个对象调用的方法,方法中的this就是那个对象
重写Object类的equals方法:
Object类的equals方法,默认比较的是两个对象的地址值,没有意义,所以我们要重写equals方法,比较两个对象的属性。问题:隐含着一个多态
**多态的弊端:**无法使用子类特有的内容(属性和方法)
**解决弊端的方法:**可以使用向下转型(强转),把obj类型转换为Person
//增加一个判断,传递的参数obj如果是this本身,直接返回true,提高程序的效率
if(obj==this)
return true;
//增加一个判断,传递的参数obj如果是null,直接返回false,提高程序的效率
if(obj==null)
return false;
if(obj instanceof Person){
Person p=(Person)obj;//强转
//比较两个对象的属性,一个对象是this(p1),一个对象是p(obj->p2)
this.name.equals(p.name)&&this.age==p.age;//true
}
//不是Person类型
return flase;
Objects类的equals方法:
Objects类的equals方法:对两个对象进行比较,防止空指针异常
第二节:Date类
2.1 毫秒值的概念和作用
需要导包:java.util.Date :表示日期和时间的类,精确到毫秒
**毫秒:**千分之一秒
**毫秒的作用:**可以对时间和日期进行计算
可以把日期转换为毫秒进行计算,计算完毕,再把毫秒转换为日期
**时间原点:**1970年1月1日00:00:00(英国格林威治)
System.out.println(System.currentTimeMillis());//获取当前系统时间到时间原点经历了多少毫秒(Long类型的值)
注意:中国属于东八区,会把时间增加8个小时
把毫秒转换为日期:1天=246060=86400秒=86400000毫秒
2.2 Date类的构造方法和成员方法
Date类的空参数构造方法:
Date()获取当前系统的日期和时间
Date date=new Date();
System.out.println(date);//Sun Dec 06 19:29:24 CST 2020
Date类的带参数构造方法:
Date(Long date):传递毫秒值,把毫秒值转化为Date日期
Date date1=new Date(0L);
System.out.println(date1);//Thu Jan 01 08:00:00 CST 1970
**getTime()😗*把日期转换为毫秒值(相当于System.currentTimeMills()方法),返回自1970年1月1日00:00:00 GNT 以来Date对象表示的毫秒数
Date date2=new Date();
long time=date2.getTime();
System.out.println(time);//1607261977925
2.3 DateFormat类
功能:对日期进行格式化,是日期/时间格式化子类的抽象类
作用:格式化(也就是日期–>文本)、解析(文本–>日期)
导包:java.text.DateFormat
成员方法:
String format(Date date) 按照指定的模式,把Date日期,格式化为符合模式的字符串
使用步骤:
1、创建SimpleDateFormat对象,构造方法中传递指定的模式
2、调用SimpleDateFormat对象中的方法format,按照构造方法中指定的模式,把Date日期格式化为符合模式的字符串(文本)
Date parse(String source) 把符合模式的字符串,解析为Date日期
使用步骤:
1、创建SimpleDateFormat对象,构造方法中传递指定的模式
2、调用SimpleDateFormat对象中的方法parse,把符合构造方法中模式的字符串,解析为Date日期
注意:
prase方法中声明了一个异常叫ParseException,如果字符串和构造方法的模式不一样,那么程序就会抛出异常,调用一个抛出了异常的方法,就必须处理这个异常,要么throws继续抛出这个异常要么try catch自己处理
DateFormat类是一个抽象类,无法直接创建对象使用,可以使用DateFormat类的子类
构造方法:
SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat
参数:String pattern---传递指定的模式,区分大小写
y 年 M 月 d 日 H 时 m 分 s 秒
"yyyy-MM-dd HH:mm:ss"
注:模式中的字母不能更改,连接符号可以改变
第三节:Calendar类
Canlendar类是一个抽象类,里面提供了很多操作日历字段的方法(Year、Month、Day_Of_Month、Hour),它无法直接创建对象使用,里面有一个静态方法叫getInstance(),该方法反回了Canlendar类的子类对象
java.util.Calendar类:日历类
常用方法:
public int get(int field):返回给定日历字段的值
public void set(int field,int value):将给定的日历字段设置为给定值
public abstract void add(int field,int amount):根据日历的规则,为给定的日历字段添加或减去指定的时间量
public Date getTime():返回一个表示此Calendar时间值(从历元到现在的毫秒偏移量)的Date对象
成员方法的参数:
int field:日历类的字段,可以使用Calendar类的静态成员变量获取
int value:给指定字段设置的值
第四节:System类
java.lang.System
提供了大量的静态方法,可以获取与系统相关的信息或系统级操作,在System类的API文档中,常用的方法有:
public static long currentTimeMills():返回以毫秒为单位的当前时间
格式:
long s=System.currentTimeMillis();
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length):将数组中指定的数据拷贝到另一个数组中
参数:src:原数组 srcPos:原数组中的起始位置(起始索引) dest:目标数组
destPos:目标数据中的起始位置 length:要复制的数组元素的数量
格式:int[] src={1,2,3,4,5};
int[] dest={6,7,8,9,10};
System.arraycopy(src,0,dest,0,3);
第五节:StringBuilder类
5.1 StringBuilder的原理
由于String类的对象内容不可改变,所以每当进行字符串拼接时,总是会内存中创建一个新的对象。
字符串是常量,它们的值在创建之后不可更改,它的底层是一个被final修饰的数组,不能改变
public class StringDemo{
public static void main(String[] args){
String s="Hello";
s+="World";
System.out.println(s);
}
}
进行字符串的相加,内存中就会有多个字符串,占用空间多,效率低下
**StringBuilder类:**字符串缓冲区,可以提高字符串的操作效率(看成一个长度可以变化的字符串),底层也是一个数组,但是没有被final修饰,可以改变长度
StringBuilder在内存中始终是一个数组,占用空间少,效率高,如果超出了StringBuilder的容量,会自动扩容
5.2 StringBuilder的构造方法
StringBuilder():构造一个不带任何字符的字符串生成器,其初始容量为16个字符
//空参数构造方法
StringBuilder str=new StringBuilder();
System.out.println(str);//空
//带字符串的构造方法
StringBuilder str1=new StringBuilder("abc");
System.out.println(str1);//abc
5.3 StringBuilder的成员方法
public StringBuilder append(..):添加任意类型数据的字符串形式,并返回当前对象自身
使用append方法不需要接收返回值
StringBuilder str=new StringBuilder();
StringBuilder str2=str.append("abc");
System.out.println(str);//abc
System.out.println(str2);//abc
System.out.println(str==str2);//true
str.append(1).append(true).append(8.8).append("中");
System.out.println(str);//abc1true8.8中
public String toString():将当前StringBuilder对象转换为String对象
String str="hello";
//字符串转化为StringBuilder
StringBuilder bu=new StringBuilder(str);
bu.append("world");
//StringBulider转换为字符串
String str2=bu.toString();
第六节:包装类
6.1 概述
java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果我们想要我们的基本类型像对象一样操作,就可以使用基本类型对象的包装类
**包装类:**基本数据类型,使用起来非常方便,但是没有对应的方法来操作这些基本类型的数据,可以使用一个类,把基本类型的数据装起来,这个类叫做包装类。我们可以使用类中的方法来操作这些基本类型的数据
6.2 装箱与拆箱
**装箱:**从基本类型转换为对应的包装类对象(基本类型的数据—>包装类)
**拆箱:**从包装类对象转换为对应的基本类型(包装类—>基本类型的数据)
装箱构造方法:
Integer(int value):构造一个新分配的Integer对象,它表示指定的int值
Integer in1=new Integer(1);//方法上有横线,说明方法过时了
System.out.println(in1);//1 重写了toString方法
Integer(String s):构造一个新分配的Integer对象,它表示String参数所指示的int值,传递的字符串,必须是基本类型的字符串,否则会抛出异常,"100"正确,"abc"错误
Integer in2=new Integer("1");
System.out.println(in2); //1
装箱静态方法:
static Integer valueOf(int i):返回一个表示指定int值的Integer实例
Integer in3=Integer.valueOf(1);
System.out.println(in3);//1
static Integer valueOf(String s):返回保存指定的String的值的Integer对象
Integer in3=Integer.valueOf("1");
System.out.println(in3);//1
拆箱成员方法:
int intvalue():以int类型返回该Integer的值
int i=in1.intValue();
System.out.println(i);//1