一丶JAVA的概述与环境搭建
Java的历史
Java之父:James Gosling,高司令
Java的各种版本
1995年推出JDK1.0
JDK8.0
Java的三大体系
A:JavaSE,Java Platform Standard Edition(Java平台标准版)
B:JavaEE,Java Platform Enterprise Edition(Java平台企业版),企业级开发
C:JavaME,Java Platform Micro Edition(Java平台微小版)
Java的特点
1、纯面向对象
2、简单性
3、跨平台:靠JVM
Java的运行机制
1、解释执行:
将源文件一行一行解释,一行一行执行。不同的操作系统具备不同的解释器。
执行效率低。跨平台。
2、编译执行:
将源文件编译成机器码文件,一次编译。多次执行。
执行效率高。不可跨平台。
Java环境搭建
安装JDK–>版本是8.0版本 配置环境变量
二丶JAVA语言基础
注释:
1、单行注释
2、多行注释
3、文档注释
编码规则:
语法要求:
1、组成:数字,字母,_,$,组成
2、数字不能开头
3、区分大小写
4、长度
5、不能是java中的关键字和保留字。
约定俗成:
见名知意
1丶变量:
变量的三要素:
- 变量的数据类型
- 变量的名字
- 变量的值
定义变量的语法形式:
1.先声明,再赋值
2.声明和赋值写一起
3.多个变量统一声明,就是写在一起声明:同种类型
变量的注意点:
1、变量必须先定义,才能使用
2、变量名不能冲突,同一个作用域内。
3、目前所学的变量:先初始化,再使用。
2丶数据类型
整数型:
byte,字节,1个字节,8bit,-128~127
short,短整形,2个字节,16bit
int,默认类型,4个字节,32bit
long,长整形,8个字节,64bit
在声明long类型的时候,数值后加L或l。建议L。
浮点型:
float类型:4个字节,32bit,定义变量的时候,数值后加f,或F
double类型:8个字节,64bit,默认类型
布尔类型:
boolean类型:取值只有两个,true(对,真),false(错,假),
字符型:
char,表示单个的字符,使用单引号引起来的,但本质上是个数值,因为对应的字符编码值。
转义字符:
1、将有特殊作用的字符,转为普通的字符,不再起作用
2、还可以将一些普通的字符,转为有特殊含义的作用
\n,\t
引用类型:
String,用于表示一个字符序列。使用双引号引起来的都是字符串的内容
3丶数据类型的转换:
自动转换:
A:两种类型兼容
B:目标类型的取值范围 大于 源类型取值范围
强制转换:
A:两种类型兼容
B:目标类型的取值范围 小于 源类型的取值范围
取值范围:
byte–>short–>int–>long–>float–>double
char-int
4丶运算符:
算术运算符:+,-,*,/,%,++,–
赋值运算符:=,+=,-=,*=,/=,%=
关系运算符:也叫比较运算符,比较两个数值的关系的。计算结果是boolean类型
逻辑运算符:操作数是boolean类型,计算结果也是boolean类型。
三元运算符:根据条件获取一个结果。 语法:X ? Y:Z
5丶自动类型提升
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mk1EYTV0-1597135689170)(C:\Users\Administrator\Desktop\javaSE\day4\课堂笔记\img\自动类型提升.png)]
6丶控制台输入
//step1:导入Scanenr这个扫描器
imprt java.util.Scanner;
//step2:创建Scanner扫描器
Scanner sc = new Scanner(System.in);
//step3:使用sc调用对应的方法,来读取键盘的输入
int num1 = sc.nextInt();//读取一个int类型的数据
double num2 = sc.nextDouble();//读取一个double类型的数据
String str = sc.next();//读取一个String类型的数据
char c = sc.next().charAt(0);//读取一个char类型的字符串
三丶选择结构与分支语句
程序的流程结构
程序的流程结构:
A:顺序结构:默认的,从上向下,逐行的执行。
B:选择结构:条件满足,某些代码才会执行。
C:循环结构:条件满足,某些代码会反复多次的执行。直到条件不满足。
1.1丶if语句
if(条件:boolean){
//条件成立,执行此处的代码
}
1.2丶if…else语句
if(条件:boolean){
//条件成立,执行此处的代码
}else{
//条件不成立,执行此处的代码
}
1.3丶多个条件:
if(条件1){
条件1满足,执行此处的代码
}else if(条件2){
条件1不满足,条件2满足,执行此处的代码
}else if(条件3){
条件1、2都不满足,条件3满足,执行此处的代码。
}。。。
else{
}
1.4丶if语句的嵌套:
if(外层条件){
if(内层条件){
}else{
}
}else{
}
2丶switch语句:
switch也是实现分支语句
switch(变量/表达式){
case 数值1:分支1;break;
case 数值2:分支2;break;
case 数值3:分支3;break;
default:最后一个分支;
}
注意点:
1、case后的数值,不能重复。
2、case是无序的,先写后写都可以,关键是是否能够匹配上switch作用的变量。
3、switch作用的变量类型:short,byte,char,int,String。
4、default语句是可选的。
5、某个case匹配上后,如果该分支中没有break,那么后续的case都不再匹配,直接执行。一直到遇到break位置。
3丶局部变量
局部变量:定义在函数里面的变量。
在一个变量的作用范围内,任何的地方都可以直接使用该变量。不能定义相同名字的其他变量。局部变量必须要赋值才能直接使用
四丶循环结构
1丶概念
条件满足,某些代码会被反复多次的执行。条件不成立了,循环结束。0-n次。
循环的组成部分
1、初始化部分:对循环变量进行初始赋值。
2、循环条件部分:判断循环变量是否满足循环条件。
3、循环体部分:要循环执行的具体的代码。
4、更新循环变量部分:修改循环变量的值。
2丶 while循环
while( 循环条件判断 ){
//循环体
//(循环中变量的变化)
}
//执行流程:while循环的特点:先判断条件,再执行代码。
//CTRl+c终止循环死循环
3丶do-while循环
do{
//循环体
//(循环变量的变化)
}while( 循环条件 );
//执行流程:先执行一次再判断
4丶for循环
for(表达式1:循环变量的初始化 ; 表达式2:循环的条件 ; 表达式3:循环变量的变化 ){
//循环体;
}
//执行流程:表达式一次判断
5丶流程控制关键字
break关键字
break:词义:打破,打碎,破坏
用法一:switch-case语句中,break用于防止switch穿透。
用法二:循环语句:while,do-while,for。强制结束了循环语句,无论循环条件是否满足。
continue:
continue:词义:继续
用法:结束当前这次循环,循环下次会继续执行。
6丶循环嵌套
多种循环,指的就是循环的嵌套。
特点:外层循环执行1次。内存循环要完整的执行一遍。
7丶占位符:
printf(" 占位符 \n",类型的变量);//格式化打印:print+format
%d,整数占位符
%s,字符串占位符
%f,浮点占位符
%.2f,%.3f
%c,字符占位符
五丶函数/方法
1丶函数/方法的概念
Java中的方法,类似于其他语言的函数,一段用来完成特定功能的代码。这段代码可以被多次调用并执行。
函数:function
方法:method
2丶方法的使用
step1:方法声明,只是做一个方法声明,里面写清楚方法的代码。但是这些代码并不执行。
step2:方法的调用,调用几次,方法中的代码就执行几次。
3丶方法的语法
1.声明一个方法的语法:
2.声明方法的语法格式:
[修饰符1,修饰符2…] 返回值类型 方法名(形式参数){
方法体;//方法中的代码
}
4丶函数的定义
public static void 函数名称(){
//函数主体
}
//定义函数的位置:与main函数并列
//函数调用,通过函数名称进行调用
5丶函数的参数
- 形式参数:简称叫形参。声明方法的时候,用于接收外部传入的数据。
- 实际参数:简称叫实参。调用方法的时候,给形参所赋值,实际的数据。
返回值:
返回值只能返回一个
return语句:
return语句有两个作用
1、将一个方法的结果返回给调用处。
2、结束该方法的执行。
方法:方法分为无参和有参
6丶递归函数
递归:英文单词:Recursion
递归算法:
- 方法自己调用自己
- 要有出口,逐渐的向出口靠近
六丶数组
1丶数组的概念
就是一组相同数据类型的数据。内存上是开辟的连续的内存空间。
2丶数组的声明与赋值
方式一:数据类型[] 数组名 = new 数据类型[长度];
A:先声明,再创建(分配内存空间)
B:声明并创建
C:声明,创建,并赋值
数据类型[] 数组名 = {数值1,数值2,数值3,数值4.。。。};
D:声明,创建,并赋值
数据类型[] 数组名 = new 数据类型[]{数值1,数值2,数值3,数值4.。。。}
3丶数组的遍历
遍历:依次访问,从第一个元素,访问到最后一个元素。
1、使用循环来遍历数组
for(int i = 0;i < arr.length; i++){
arr[i] = i;//赋值
System.out.println(arr[i]);//获取数值
}
4丶for-each循环
for(数据类型 变量名 : 数组名){
System.out.println(变量名);
}
工作原理:
for(int e :arr){
System.out.println(e);
}
5丶数组中的默认值
数组的默认值,就是数组创建后,里面存储的默认的数据。
数组中是有默认值的
整数:0
小数:0.0
字符:\u0000
布尔:false
其他:null
6丶数组作为参数
数组是引用类型:传递的是地址。就是参数也会指向这块内存。当方法结束的时候,参数就销毁了。
class Test5ArrayMethod
{
//设计一个方法,用于打印数组
public static void printArray(int[] arr){//int[] arr = a;a的地址给了arr,那么arr和
// a指向同一块内存的数组
for(int e : arr){
System.out.print(e +"\t");
}
System.out.println();
}
public static void main(String[] args)
{
int[] a = {1,2,3,4,5};
//设计一个方法,用于打印数组
printArray(a);//将a的地址,传递给arr
System.out.println("Hello World!");
}
}
7丶数组作为返回值
//设计一个方法,用于创建一个数组, 并赋值。数组要返回给调用处
public static int[] createArray(int len){
int[] arr = new int[len];
for(int i = 0;i <arr.length;i++){
arr[i] = i * 2;
}
return arr;
}
8丶数组的排序
1、冒泡排序:
Bubble Sort 原理:比较相邻的两个数,将较大的数,向后移动。
class Test7BubbleSort
{
public static void main(String[] args)
{
int[] arr = {15,23,8,10,7};
for(int i= 1; i<arr.length;i++){//控制轮数:
//i=1,2,3,4
/*
i=1, j<4
i=2, j<3
i=3, j<2
*/
for(int j = 0;j < arr.length - i;j++){
if(arr[j] > arr[j+1]){
//交换
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int i = 0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
2丶选择排序
思路(升序):每次找个基准值,定一个变量k表示比较小的值的下标。每轮比较完,都在基准值上放一个比较小数。
int[] a = {15,23,8,10,7};
for(int i= 0;i <a.length - 1;i++){//控制轮数,趟数
int k = i;
for(int j = k + 1;j<a.length;j++){
if(arr[k] > arr[j]){
k = j;
}
}
//交换
if(k != i){
int temp = arr[k];
arr[k] = arr[i];
arr[i] = temp;
}
}
3丶工具类:Arrays
JDK提供好的类:
A:Scanner,读取键盘
B:String,字符串
C:Math,数学的
D:Arrays,提供数组的常规操作的
E:System,
9丶数组的复制
就是将一个数组的数据,复制到另一个数值中。
方法一:通过循环,依次复制,将原数组的数据,一个一个,复制到目标数组中
方法二:Arrays类里方法:copyOf(原数组,新数组的长度)–>返回值是新数组
方法三:System类里的方法:arraycopy(原数组,原数组位置,新数组,新数组位置,拷贝的个数)
10丶二维数组
int[][]i={{}{}{}};
七丶面向对向
1丶Java中定义类的格式
/*
class ClassName{//类名首字母大写
//属性描述:外部特征
//行为描述:能够干啥
}
*/
2丶内存分析
package com.qf.demo01;
public class Test1Person {
public static void main(String[] args) {
//step1:创建Person类的对象
//语法:类名 对象名 = new 类名();
Person p1 = new Person();
System.out.println(p1);//打印p1的值,p1是引用类型,打印都是p1指向的对象的地址。
System.out.println(p1.name);
System.out.println(p1.age);
System.out.println(p1.sex);
/*
* com.qf.demo01.Person@15db9742
* 包名.类名@编码值 ---->理解为p1的内存地址。
*
* java中的数据类型:
* 基本类型:byte,short,char,int,long,bolean,float,double
* 引用类型:
* 数组,类类类型
*
*/
//step2:通过对象访问属性,语法是.
//给对象的属性,进行赋值
p1.name = "王二狗";//给p1这个对象的name属性进行赋值
p1.age = 18;
p1.sex = '男';
//获取对象的属性值
System.out.println("姓名:"+p1.name);
System.out.println("年龄:"+p1.age);
System.out.println("性别:"+p1.sex);
//step3:通过对象,访问成员方法--->理解为就是对象调用成员方法
p1.eat();
p1.sleep();
p1.daDouDou();
}
}
3丶方法的重载:overload
如何判定多个方法是否是重载的?衡量标准,要同时满足以下三条:
A:必须同一个类中。
B:方法名称必须一致。
C:参数列表必须不同。(顺序,个数,类型)
4丶构造方法
构造方法:是一个很特殊的方法。
- 声明的语法:public 类名(){}
- 修饰符:只能有访问权限的修饰符,public。不能加static。
- 返回值:没有返回值,也不能写void。
- 方法名:必须和类名相同
- 调用的方式:new 关键字调用
- new关键字后面跟着构造方法即可。
- 作用:专门用于创建对象。
普通方法:一段具有特殊功能的代码。而且可以被多次调用执行。
自定义的构造方法
语法规则:
public 类名(){
}
public 类名(参数列表){
将参数的数值,赋值给属性即可。
}
//分为有参和无参够构造
对比一下构造方法和普通方法:
序号 | 对比点 | 构造方法 | 普通方法 |
---|---|---|---|
1 | 返回值 | 没有,也不能写void | 必须写返回值类型,没有就写void |
2 | 方法名 | 必须和类名一致 | 见名知意 |
3 | 参数列表 | —— | —— |
4 | 修饰符 | 最多只能访问权限:public | 访问权限public,还有其他,比如static |
5 | 调用 | 必须使用new关键字 | 没有static,类中的成员方法。对象.方法 有static,直接方法名。 |
6 | 作用 | 专门用于创建对象,并且可以初始化属性的值。 | 实现特定的功能 |
7 | 执行 | 每当创建一个对象,就会调用一次,执行1次 | 通过方法名,调用几次就执行几次。 |
5丶this关键字
this的用法一:表示当前对象。
this的用法二:this()指代当前类的构造方法。
六丶匿名对象
匿名对象,就是只有=右侧,没有=左侧。
new 构造方法(必要的参数);
八丶三大特性
1丶封装性
1.private关键字
修饰符:public,private,static,final,abstract。。。
2 getter和setter方法
使用了private访问权限修饰符,限制了只能在类中使用。那么对于外部的对象,如何给属性进行操作?赋值,取值。
使用setter方法,给属性进行赋值。
使用getter方法,获取属性值
2丶继承性
Java中的继承的概念
继承指的是两个类的关系。如果一个类(子类),继承了另外一个类(父类)。那么子类就可以直接使用父类的非私有化的成员(属性,和方法)。
继承的好处
1、实现代码的重用和扩展。
2、模拟现实世界的关系。
类的继承:
关键字:extends,词义:扩展的。描述两个类的关系:子类,父类。
继承的注意点
1、两个类存在了继承关系。
子类可以使用父类的属性和方法
但是父类不能使用子类的属性和方法。
2、Java语言的继承是局限性:单继承。
一个子类,只能有一个父类。
Java语言,不允许多继承,但是可以多层继承。
一个父类,爷爷类,太爷爷,祖爷爷。。祖宗。。
一个父类是可以有多个子类的。
子类对象的创建过程
调用子类的构造方法中,先调用父类的构造方法。默认父类的无参构造方法。
super关键字
用法一:表示父类的构造方法。super(),表示父类的构造方法。同this()相类似。
3丶方法的重写
1、继承结构中。
2、方法的声明,必须和父类的一致。
方法名必须和父类一致
参数列表必须和父类一致
返回值必须和父类一致
3、访问权限,不能比父类更加严格。
4、子类重写的方法,不能抛出比父类更大更多的异常。
4丶访问权限修饰符
private:私有的。本类中。
protected:受保护的。本类,同包下,不同包(子类使用)
public,没有限制的。
默认的:(default):注意,啥修饰符都不写,就是默认的。本类。同包下可以访问。
5丶对象的多态性
一个父类两个儿子 2个子类都可以重写父类的方法
6丶向上转型和向下转型
向上转型:一个子类对象看成了父类类型。那么就失去了子类新增。
Animal a2 = new Cat();//
九丶三个修饰符
1丶abstract关键字
表示抽象的意思。
abstract class Animal{
public abstract void run();//只有声明, 没有实现,那么就是抽象方法。
}
public static void main(String[] args){
//对于抽象类,不能创建对象
//Animal a = new Animal();
//a.run();
}
//最大目的强制子类重写方法
//抽象类不能有对象
2丶final关键字
词义:“最终的,最后的”。可不可以把final理解成最后的,谁都不能更改。
1、final修饰变量(成员变量和局部变量),则为常量,只能赋值这一次
2、final修饰方法,则该方法不能被子类重写
3、final修饰类,则类不能被继承
3丶static关键字
1、修饰属性【重点】
静态的属性:属于类,仅一份。所有的对象共享。
2、修饰方法【重点】
静态的方法:属于类,由类直接调用,方法里不能访问对象的内容(属性,方法),以及this和super关键字。
继承中,子类可以继承父类的静态方法,但是不能重写。
3、修饰代码块
4、修饰内部类
4丶代码块
局部代码块
构造代码块
静态代码块 加static
同步代码块 多线程
{
}
十丶接口
1丶什么是接口
接口就是一种能力和约定。一种协议,一种规则。
2丶接口的内容
A:接口中,包含静态常量,默认的(缺省)修饰符:public static final
B:接口中,包含抽象方法,默认的(缺省)修饰符:public abstract
3丶接口的语法
//1.定义一个接口
interface 接口名{
//静态常量
//抽象方法
}
//2.需要实现类来实现接口:类比子类继承抽象类。
class 实现类 implements 接口名{
//重写接口中的抽象方法
}
//3.创建实现类的对象
4丶接口引用
接口类型的引用 = new 实现类的对象
5丶接口注意点
1、接口可以多实现:一个实现类可以同时实现多个接口
2丶接口可以多继承
3、一个类如果实现接口了,还能继承其他的父类吗?可以的
4、如果一个类没有实现接口中的所有的方法,那么它是抽象的
5丶接口的好处
A:降低了程序的耦合性。代码的关联程度。
接口中只做功能的声明,没有具体的实现。
面向接口编程:关心功能有哪些
B:定义的都是规则,对外暴露的功能是一致。
C:接口可以多继承,以及多实现,使用更灵活。
6丶接口回调
首有个接口A,和它 实现类。然后在另一个类B中,持有A的引用,那么在B类中可以调用接口A的方法。这就是一种回调。
十一丶常用类
1丶类和类的关系
1、继承关系
2、实现关系
3、依赖关系
public class Pet{}
public class Girl{
public void play(Pet pet){
}
}
4、关联关系
public class Book{}
public class Person{
Book book;
}
特殊的关联关系:聚合,组合。。。
2丶匿名内部类
匿名内部类:没有名字的内部的类。
interface A{
public void test();
}
//A a = new 实现类对象;
A a = new A(){//从此处开始,就是匿名的呢不累
public void test();
};//到此处结束
a.test();
一般匿名内部类适合:使用一次,创建一次对象。
3丶Object类
Object类是所有类的基类。所以只要是Java中的类的对象,默认都可以执行Object类中的方法。
A:getClass()–>Class,未完待续—>反射
B:hashCode()—>int,获取对象的哈希码
C:toString()—>String,返回一个对象的字符串表示形式
D:equals()–>boolean,用于比较两个对象是否相等。
Object类中,equals()方法的源代码:
//在方法中this,就指代了c1对象
public boolean equals(Object obj) {//Object obj = c2;
return (this == obj);
}
c1.equals(c2);//false
子类重写:重写的规则
应该比较对象的各个属性值即可,如果都相同,那么认为是相同的对象,最终返回true,否则返回false。
c1.equals(c2);
/*
分析:
this-->c1
obj-->c2,向上转型
Cat c2 = new Cat();
c1.equals(c2);//Object obj = c2;
*/
//step1:先比较地址:c1和c2 的地址:this == obj,如果地址相等,直接返回true。
//step2:判断,obj == null? obj--->Cat
//step3:比较对应的属性是否相等
this.各种属性和
obj--->向下转型:c2.各种属性
4丶8种包装类
序号 | 基本数据类型 | 对应的包装类 |
---|---|---|
1 | byte | java.lang.Byte |
2 | short | java.lang.Short |
3 | int | java.lang.Integer |
4 | long | java.lang.Long |
5 | float | java.lang.Float |
6 | double | java.lang.Double |
7 | char | java.lang.Character |
8 | boolean | java.lang.Boolean |
5丶String类
1丶StringBuffer类
new StringBuffer();//默认的缓冲区大小16个字符
new StringBuffer(int capacity);//也可以自己指定容量大小
new StringBuffer(String s);//StringBuffer对象创建好,并且里面还存储了字符串
//在String基础上增加的add添加 delete删除 reverse修改
2丶StringBuilder类
StringBuilder类提供的方法,和StringBuffer功能相同。
它们的区别:
StringBuffer是线程安全的,效率比StringBuilder低一些。JDK1.0
StringBuilder线程不安全。效率比StringBuffer高一些。JDK1.5
3丶math类
Math类:和数学相关:PI,abs(),ceil(),floor(),round(),random()。。
4丶Random类:
随机数
5丶BigDecimal类
大小数。精准的计算。double,float
6丶Date类
Date类中的很多获取日期,时间等等的方法, 都被Calendar类所提供替代。
7丶 SimpleDateFormat类
/*
* SimpleDateFormat类:
* Date-->String:日期格式化?就是将一个日期Date对象,按照指定的字符串格式去显示。
* format(),根据模板,将date日期,转为String字符串类型
* 1.创建SimpleDateFormat对象。可以通过构造方法指定模板(格式):"yyyy-MM-dd"
* 如果没有指定模板,使用系统默认:20-4-16 上午11:09
* 2.sdf.format(date)-->String
*
*
* String-->Date:解析?就是将一个文本字符串,解析成一个Date对象。
* parse(),根据模板,将字符串解析为对应的日期对象,异常。
* 1.同上
* 2.sdf.parse(String)-->date
*/
8丶Calendar类
Calendar类是抽象的。GregorianCalendar子类。
获取日期时间,也可以设置日期时间。
//step1:创建Calendar类的对象。
Calendar calendar = new GregorianCalendar();//方式一
Calendar rightNow = Calendar.getInstance();//方式二
//step2:
//获取类
calender.get(YEAR,MONTH,DAY_OF_MONTH,DAY_OF_WEEK,HOUE,MINUTE....);
//设置
calendar.set();
十二丶集合
1丶集合的概念
动态存储多个对象。
对象:集合中所存储的数据,仅限于对象。
- 引用类型,能够存储
- 基本类型,装箱----->包装类类型,可以存储。
2丶Collection接口
集合框架的最大的父接口:规定的都是集合容器最基本的功能。
3丶list接口与实现类
1丶List接口
为Collection接口的子接口,也是一种容器。但是有自己的独特的存储特点。
遍历一个List接口中的所有元素:
- for-each,增强for循环
- Iterator,迭代器
- 普通的for循环,结合get()方法。
2丶ArrayList实现类
作为List接口的实现类,将接口中的方法全部实现。
底层:数组的结构来实现的。也会有人叫动态数组。
理解为ArrayList相当于一个可变长度的数组,访问遍历效率较高。增加,删除元素,效率较低。
3丶LinkedList实现类
作为List接口的实现类,将接口中的方法全部实现。同时还实现了Deque双端队列中的方法。
queue:队列。排队,队列
deque:双端队列,全名:double-ended queue
栈:
模拟栈的结构:后进先出(LIFO),栈顶元素,
push(),压栈,入栈,pop(),弹栈,出栈
队列:
模拟队列的结构:先进先出(FIFO),队头元素
offer(),poll()
4丶set接口和实现类
1丶set接口
Set词义:数学中集合的概念。也是Collection的子接口。
2丶hashset实现类
底层是由哈希表实现。它不保证迭代的顺序。特别是不保证顺序一直不变。
真正判断元素是否是重复,是否是相同的:看equals()。
-
Object类:equals()–>boolean,判断对象是否相等。
-
子类是否重写:
String,Integer,Date,。。。。
HashSet集合去重的流程**:
step1:先获取对象的hashCode,对象的哈希值不同,直接存储到HashSet容器中。
step2:如果哈希值相同,调用equals()比较。
true:认为是相同的元素,不存储
false:不同的元素,存储
原则:hashCode()和equals()的原则:
重写的规则:
重写的规则:
hashCode()
对象相同,属性值相同。哈希码必须相同。
对象不同,属性值不同。哈希码尽量不同。
equals()
对象相同:属性值相同。必须true。
对象不同:属性值不同。必须false。
3丶TreeSet实现类
也要去除重复的元素。可以给存储的元素进行整理排序。
默认的规则:Comparable接口,定义排序的规则。
interface Comparable{
int compareTo(T obj);//排序的规则
}
4丶LinkedHashSet集合
回忆:HashSet存储特点?1、无序。2、去重
HashSet存储数据,记录存储的顺序。
存储原理同HashSet相同,但是外层套了一个链表结构。用于记录存储的顺序。
5丶Comparable接口
- 正数:o1 > o2,将o1排在o2的后面。
- 负数:o1 < o2,将o1排在o2的前面。
- 零:认为o1和o2相同,不存储了。
仅有唯一的一个方法:compareTo()–>此方法用于排序,返回值int类型类型
默认的TreeSet集合,使用的是Comparable接口,来给对象进行排序。以及去重。
6丶Comparator接口
int compare(T o1, T o2)
比较其两个参数的顺序。
比较的两个对象:o1和o2
- 无参构造:new TreeSet();–>使用默认的比较器:Comparable
- 有参构造:new TreeSet(Comparator)–>使用自定义的比较器:Comparator
7丶Map接口与实现类
1丶map接口
map每次操作的元素是成对的。两个:key(键),value(值)。
map中存储的元素,键值对。其中键不能重复。值可以重复。键和值,必须是一一对应的。
put(key,value);向map中添加键值对,键不能重复。如果键重复了,那么value会被覆盖的。
2丶HashMap实现类
HashMap集合——>key如何去重?原理同HashSet相同。
HashSet集合——>如何去重?step1:hashCode(),step2:equals()
3丶TreeMap实现类
对比TreeSet和TreeMap
1、都要求对象具有可比性。
TreeSet来讲:里面所存储的元素,能够进行比较大小。
TreeMap来讲,所存储 key,能够进行比较大小。
2、区别于HashSet和HashMap,要给排序。从小到大排序。
Comparable接口:默认的
Comparator接口:自定义
4丶Map.Entry map没有迭代器就要用Entry
Entry可以认为是一个键值对对象。理解为:将键值对看成一个整体的对象。包含了Key,Value。
Map中操作的是一对对象。key和value。存在一个映射关系。对应的。
对于map集合,无法直接迭代获取里面的元素。
5丶LinkedHashMap实现类
记录了存储的顺序。去重的原理和HashMap相同。
6丶HashTable是map的实现类
HashTable的父类是:Dictionary
HashMap的父类是:AbstractMap
HashTable是旧的类,线程安全,效率低
对于null的处理:
- HashMap对null,看成了普通的对象。可以key为null,也可以value为null
- HashTable对null没有进行处理。抛出异常:NullPointerException
1丶Properties是HashTable子类
集合存储对象的,Properties存储属性信息。
将属性集合Properties中的数据——>file文件中
8丶泛型限定 -泛型Generics<>
1、泛型应用在集合上。
List<String> list = new ArrayList();
list.add(String);//存储String类型
2、泛型应用在类上。
class 类名<T>{
//T这个类型,当创建对象的时候决定好。
}
3、泛型作用在静态方法上
//3.<M>,静态方法上自己独立声明泛型,不能使用类的。
public static <M> M test(M m){
System.out.println(m);
return m;
}
4、泛型的限定:集合中
List<?>,List
5、不允许使用泛型的地方
-
静态属性:private static T member;//错误的
-
创建T的实例:T t = new T();//错误
-
自定义异常,不能使用泛型
class MyException extends Exception
9丶Collections工具类
Collections:集合的工具类,包含了集合的常用方法。
10丶迭代器Iterator
Iterator i1=new Iterator();
while(i1.hasNext()){
System.out.println(i1.next())
}
十三丶异常 Exception
1丶异常的概念:
概念:在程序执行的时候,代码中产生的不正常事件,导致程序无法正常的执行。
2丶异常的分类
Throwable类:可抛出的。
Exception:异常
1.受检异常----必须处理,程序才能运行。
2.非受检异常,又叫运行时异常-----代码中的逻辑问题导致的异常。
3丶捕获异常 try必须存在 catch可以不用存在
子类异常不能大于父类异常
try{
//try语句块中,有可能产生异常的代码,尝试着执行
}catch(异常类型1 e){
//对异常处理
}catch(异常类型2 e){
//
}...
finally{
//此处的操作是可选的,
这里的代码,一定会被执行的。。
}
4丶抛出异常
public void test()throws 异常类型1,异常类型2...{
}
5丶throws关键字和throw关键字
throws:用于一个方法的对外声明:用于表示该方法不处理异常,交由调用处进行处理。
throw:用于代码中主动抛出一个异常对象:设计一个方法的功能的时候,根据逻辑分析,可以主动抛出一个异常对象。
代码级别上,主动抛出一个异常对象,提示调用者:产生问题啦。。
以下是String这个类的源代码:
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
6丶自定义异常
自己定义一个类,用于表示某种异常。需要继承Exception或其子类即可。
class MyException extends Exception{
//提供有参构造方法。。
public MyException(String msg){
super(msg);//调用父类的有参构造:提供异常的信息
}
public MyException(){
super();//父类的无参构造,没有提供异常的信息
}
}
程序中主动抛出一个异常对象:
/*
* 设计一个方法,用于检验年龄,年龄不合法,抛出一个异常
*/
public static void checkAge(int age) throws MyException{
if(age < 0){
// return;
throw new MyException("年龄不能为负数。。");
}
System.out.println("年龄输入正确,请继续。。。");
}