注释分类(注释不参与程序运行,仅起到说明作用)
单行注释 格式://注释信息 多行注释 /*注释信息*/ 文档注释 格式/**注释信息*/
数据类型
var关键字
有些时候,类型的名字太长,写起来比较麻烦。例如:
StringBuilder sb = new StringBuilder();
这个时候,如果想省略变量类型,可以使用var
关键字:
var sb = new StringBuilder();
编译器会根据赋值语句自动推断出变量sb
的类型是StringBuilder
。对编译器来说,语句:
var sb = new StringBuilder();
实际上会自动变成:
StringBuilder sb = new StringBuilder();
因此,使用var
定义变量,仅仅是少写了变量类型而已。
变量使用的注意事项
long类型的变量定义的时候,为了防止整数过大,后面要加L
float类型的变量定义的时候,为了防止类型不兼容,后面要加F
类型转换
自动类型转换(把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量)
强制类型转换(倒过来)
例如 int k=88.88 并不能编译 因为88.88属于double类型
但是int k=(int)88.88可以编译 这就是强制类型转换
字符的“+”操作
‘A’=65 A-Z是连续的
'a'=97 a-z是连续的
'0'=48 0-9是连续的
算术表达式中包含多个基本数据类型的值的时候,整个算术表达式的类型会自动进行提升
提升规则:
byte类型,short类型和char类型将被提升到int类型
整个表达式的类型自动提升到表达式中最高等级操作数同样的类型
等级顺序byte,short,char ——int——long——flot——double
举例int k =12.66 编译不可取 int换成double可取
赋值运算符
符号 | 作用 | 说明 |
---|---|---|
= | 赋值 | a=10 将10赋值给变量a |
+= | 加后赋值 | a+=b 将a+b的值给a |
-= | 减后赋值 | a-=b 将a-b的值给a |
*= | 乘后赋值 | a*=b 将a*b的值给a |
/= | 除后赋值 | a/=b 将a/b的商给a |
%= | 取余后赋值 | a%b 将a/b的余数给a |
自增自减运算符
符号 | 作用 | 说明 |
++ | 自增 | 变量的值加1 |
-- | 自减 | 变量的值减1 |
单独使用
例: int i=10;
i++;或者++i;
System.out.println("i:"+i); 结果为i:11
参与操作使用
int i=10
int j=i++ 输出之后 i=11 j=10
int j=++i 输出之后 i=11 j=11
最常见的用法(单独使用)
关系运算符
符号 | 说明 |
== | a==b,判断a和b的值是否相等,成立为true,不成立为false |
!= | a!=b,判断a和b的值是否不相等,成立为true,不成立为false |
> | a>b,判断a是否大于b,成立为true,不成立为false |
>= | a>=b,判断a是否大于等于b,成立为true,不成立为false |
< | a<b,判断a是否小于b,成立为true,不成立为false |
<= | a<=b,判断a是否小于等于b,成立为true,不成立为false |
例:int i= 10 int j=20 int k=10
System.out.println(i==j); 结果为false
System.out.println(i==k); 结果为true
System.out.println(i=j); 结果为20
逻辑运算符
符号 | 作用 | 说明 |
& | 逻辑与 | a&b,a和b都是true,结果为true,否则为false |
| | 逻辑或 | a|b,a和b都是false,结果为false,否则为true |
^ | 逻辑异或 | a^b,a和b结果不同为true,相同为false |
! | 逻辑非 | !a,结果和a的结果正好相反 |
短路逻辑运算符
符号 | 作用 | 说明 |
&& | 短路与 | 作用和&相同,但有短路效果 |
|| | 短路或 | 作用和|相同,但有短路效果 |
注意事项
短路与&&,如果左边为真,右边执行,如果左边为假,右边不执行。
短路或||,如果左边为假,右边执行,如果左边为真,右边不执行。
三元运算符
格式:
关系表达式?表达式1:表达式2;
范例:
a>b?a:b;
执行流程:
首先计算关系表达式的值,如果结果为true,表达式1的值就是运算结果。如果结果为false,表达式2的值就是运算结果。
数据输入
导包:导包的动作必须出现在类定义的上边
import java.util.Scanner;
创建对象:下面这个格式里面,只有sc是变量名,可以变,其他都不可以变。
Scanner sc=new Scanner(System.in);
接受数据:下面这个格式里面,只有i是变量名,可以变,其他都不可以变。
int i =sc.nextInt();
流程控制
分支结构(if,switch)
循环结构(for,while,do...while)
if语句执行流程①首先计算关系表达式的值 ②如果关系表达式的值为true就执行语句体,如果为false就继续执行后面的语句内容。
if...else语句执行流程2①首先计算关系表达式的值 ②如果关系表达式的值为true就执行语句体1,如果为false就执行语句体2,继续执行后面的语句内容
if...else if...else语句执行流程3①首先计算关系表达式的值 ②如果没有任何关系表达式为true,就执行语句体n+1 最后一个不用写条件语句
switch语句格式
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个星期数(1-7)")
int week = sc.nextInt();
swtich(week){
case “1”:
System.out.ptintln(“星期一”);
brake;
case “2”:
System.out.ptintln(“星期二”);
brake;
default:
System.out.ptintln(“你输入的星期数有误”)
brake;
}
(在switch语句中,如果case控制的语句后面不写break,将出现穿透现象,在不判断下一个case的情况下,向下运行,知道遇到break,或者整体switch语句结束。)
for循环语句格式①执行初始化语句②执行条件判断语句,看其结果是true还是false,如果是false循环结束,如果是true,执行循环体语句③执行条件控制语句④回到②继续
for(int i =1; i<=5; i++){
System.out.ptintln("HelloWorld");
}
while循环结构可以把i++放到最后
求偶数和案例
do...while循环语句格式
初始化语句;
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
案例
int j =1;
do{
System.out.ptintln("HelloWorld");
j++;
}while (j<=5);
三种循环的区别
for和while是先判断后执行,do...while是先执行后判断
for和while的区别,在for循环结束后就不能再次被访问到了,在while循环结束后,该变量还可以继续使用。
死循环
for(;;){}
while(true){ }
do{}while(true);
while的死循环格式是最常用的
Ctrl+C可以结束死循环
跳转控制语句
continue;用在循环中,基于条件控制,跳过某次循环体的执行,继续下一次的执行
break;用在循环中,基于条件控制,终止循环体内容的执行,也就是说结束当前整个循环
Random(用于产生一个随机数)
1、导包
import java.util.Random;
2、创建对象
Random r=new Random();
3、获取随机数
int unmber=r.nextInt(10);
获取数值的范围;包括0,但不包括10
IDEA创建HelloWorld
①创建一个空项目
②创建一个新模块(idea_test)
③在idea_test模块下的src下创建一个包(com.itiheima)
④在com.itiheima包下新建一个类(HelloWorld)
⑤在HelloWorld类中编写代码
⑥在idea中执行程序
IDEA中内容辅助键和快捷键
快速生成语句:快速生成main方法:psvm 回车
快速生成输出语句:sout 回车
快捷键:
注释:单行,选中代码,Ctrl+/ 再来一次就是取消
多行,选中代码,Ctrl+Shift+/ 再来一次就是取消
格式化 : Ctrl+Alt+L
内容辅助键
Ctrl+Alt+space(内容提示,代码补全等)
数组定义格式
格式一:数据类型【】变量名
范例: int【】 arr
定义了一个int类型的数组,数组名是arr
格式二:数据类型 变量名【】
范例: int arr【】
定义了一个int类型的变量,变量名是arr的数组
实参是真实存在的参数,形参是表达中的参数。
方法的定义和调用
方法定义
public static void 方法名(){
方法体
}
例:定义一个方法,在方法中定义一个变量,判断该数据是否是偶数
public static void isEvenNumber(){
int number=10;
if(number%2=0){
System.out.println(ture);
}else{
System.out.println(false);
}
方法调用
isEvenNumber ();
带参数的方法和调用
带返回值方法的定义和调用
方法的通用格式
格式:public static返回值类型 方法名(参数){
方法体;
return数据;
}
定义方法时要做到两个明确
①:明确返回类型,主要是明确方法操作完毕之后是否有数据返回,如果没有,写void,如果有,写对应的数据类型.
②:明确参数,主要是明确参数的类型和数量
调用方法时
void类型的方法,直接调用即可
非void类型的方法,推荐用变量接受调
用
方法重载
多个方法在同一个类中
多个方法具有相同的方法名
多个方法的参数不相同,类型不同或者数量不同
System.out.println("内容");输出内容不换行
System.out.print("内容");输出内容并换行
System.out.println();起到换行作用
名词解释
temp:临时变量
start:第一个
end:最后一个
printArray:输入数组
reverse:反转
类的定义
类的组成:属性和行为
定义类public class 类名{ ...}
属性:在类中通过成员变量来提现 (类中方法外的变量)
行为:在类中通过成员方法来提现 (和前面的方法相比去掉static关键字即可)
创建对象
格式:类名 对象名=new 类名();
范例: Phone p =new Phone();
使用对象
1、使用成员变量
格式:对象名 . 变量名
范例:p.brand
2、使用成员方法
格式:对象名.方法名()
范例:p.call();
成员变量和局部变量
区别 | 成员变量 | 局部变量 |
类中位置不同 | 类中方法外 | 方法内或者方法声明上 |
内存中位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的存在而存在 随着对象的消失而消失 | 随着方法的调用而存在 随着方法的调用完毕而消失 |
初始化值不同 | 有默认的初始化值 | 没有默认的初始化值,必须先定义 赋值,才能使用 |
private
作用是保护成员不被别的类使用,被private修饰的成员只在本类中才能访问
针对private修饰的成员变量,如果需要被其他类使用,方法用public修饰
提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
对象名.setage(10); 是赋值
构造方法
作用:创建对象(不声明对象调用就用static,声明对象调用就不用static)
public class类名{
修饰符 类名(参数){
}
}
功能:完成对象数据的初始化
构造方法的注意事项
1、构造方法的创建
如果没有定义构造方法,系统将给出一个默认的无参数构造方法
如果定义了构造方法,系统将不再提供默认的构造方法
2、如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
标准类制作
① 成员变量
使用private修饰
②构造方法
提供一个无参构造方法
提供一个带多个参数的构造方法
③成员方法
提供每一个成员变量对应的setXxx()/getXxx()
提供一个显示对象信息的show()
④创建对象并为其成员变量赋值的两种方式
无参构造方法创建对象后使用setXxx()赋值
使用带参构造方法直接创建带有属性值的对象
字符串的比较
使用==做比较
基本类型:比较的是数据值是否相同
引用类型:比较的是地址值是否相同
字符串是对象,它比较内容是否相同是通过一个方法来实现的,这个方法叫
equals()或A.equals()
public boolean equals(Object an Object):将此字符串与指定对象进行比较,由于我们比较的是字符串对象,所以参数直接传递一个字符串
遍历字符串
数组的长度:数组名.length
字符串的长度:字符串对象.length()
遍历数组的通用格式
for{int i =0;i<s.length();i++} {
s.charAt(i); //就是制定索引处的字符值
}
字符数组:char【】chs = {‘a’,‘b’};
字节数组:byte【】bys={97,,98};
String构造方法
方法名 | 说明 |
public String() | 创建一个空白字符串对象,不包含任何内容 |
public String(char【】chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte【】bys) | 根据字节数组内容,来创建字符串对象 |
String s =“abc” | 直接赋值的方式创建字符串对象,内容就是abc |
String和StringBuilder区别
String:内容是不可变的
StringBuilder:内容是可变的
String和StringBuilder相互转换
StringBuilder 转换为String
public String toString():通过toString()就可以实现把StringBuilder 转换为String
String转换为StringBuilder
public StringBuilder(Strings):通过构造方法就可以实现把String转换为StringBuilder
例:(String转化为StingBuilder)
String s =“hello”;
StingBuilder sb = new StingBuilder(s);
System.out.println(sb);
集合概述
ArrayList<E>
①可调整大小的数组实现
②<E>是一种特殊的数据类型,泛型
例:ArrayList<String>,ArrayList<Student>
ArrayList构造方法和添加方法
方法名 | 说明 |
public ArrayList() | 创建一个空的集合对象 |
public boolean add(Ee) | 将指定的元素添加到此集合的末尾 |
public void add (int index,E element) | 在此集合中的指定位置插入指定的元素 |
ArrayList常用方法
方法名 | 说明 |
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
public E remove (int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,Element) | 删除指定索引处的元素,返回被修改的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
学生管理系统
①快捷键Alt+Insert 可以帮我们构造方法 和get set方法
②System.exit(0); 退出系统0
继承
格式:
public class ZI extends FU { }
FU:是父类,也被称为基类,超类
ZI:是子类,也被称为派生类
子类可以有父类的内容
子类也可以有自己特有的内容
什么时候使用继承?
继承体现的关系 is a
我有两个类A和B,如果他们满足A是B的一种或者B是A的一种,就说明他们存在继承关系
举例:苹果和水果
继承中变量的访问特点(Java中可以继承再继承)
在子类方法中访问一个变量
子类局部范围找
子类成员范围找
父类成员范围找
如果都没有就报错(不考虑父亲的父亲)
super和this
关键字 | 访问成员变量 | 访问构造变量 | 访问成员变量 |
this | this成员变量 访问本类成员变量 | this() 访问本类构造方法 | this成员方法() 访问本类成员方法 |
super | super成员变量 访问父类成员变量 | super() 访问父类构造方法 | super成员方法() 访问父类成员方法 |
继承中构造方法的访问特点
每一个子类构造方法的第一条语句默认都是 super()
如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢
①通过使用super关键字去显示的调用父类的带参构造方法
②在父类中自己提供一个无参构造方法 推荐:自己给出无参构造方法
访问成员方法时子类没有就去父类找 父类没有就报错
方法重写(子类中出现了和父类中一模一样的方法声明)
当子类需要父类的功能,而功能主体子类有自己特定内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。
@override
是一个注解
可以帮助我们检查重写方法的方法声明的正确性
方法重写注意事项
①私有方法不能被重写(父类私有成员子类是不能继承的)
②子类方法访问权限不能更低(public>默认>私有)
包
手动建包:
按照以前的格式编译java文件 javac HelloWorld.java
手动创建包 在E盘建立文件夹com,然后在com下建立文件夹itheima
把class文件放到包的最里面 把HelloWorld.class文件放到这个itheima下
带包执行 java com.itheima.HelloWorld
自动建包:
javac -d.HelloWorld.java java com.itheima.HelloWorld
导包
使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了
为了简化带包的操作,Java就提供了带包的功能
导包的格式:import 包名.类名
范例:import itcast.Teacher
权限修饰符
修饰符 | 同一个类中 | 同一个包中 子类无关类 | 不同包的子类 | 不同包的无关类 |
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
final
修饰方法:表明该方法是最终方法,不能被重写
修饰变量:表明该变量是最终变量,不能再次被赋值
修饰类:表明该类是最终类,不能被继承
final修饰局部变量
当final修饰成员方法里边的变量的时候,如果创建对象再次被调用,还是可以改变的。
static(静态修饰符)
static修饰成员变量的特点
被类的所有对象共享,这也是我们是否使用静态关键字的条件
可以通过类名调用,当然也可以使用对象名调用,推荐使用类名调用
static访问特点
非静态的成员方法可以访问静态和非静态的成员方法和成员变量
静态的成员方法只能访问静态的成员方法和成员变量
多态(多态的前提和体现)
①有继承关系②有方法重写③有父类引用指向子类对象
多态中成员访问特点
成员变量:编译看父类,执行看父类
成员方法:编译看父类,执行看子类
为什么成员方法和成员变量的访问不一样呢?
因为成员方法有重写,而成员变量没有
多态的好处和弊端
多态的好处:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作
多态的弊端:不能使用子类的特有功能
多态中的转型
Animal a = new cat();
Cat c = (Cat) a;
a.playgame();
抽象类
一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,
那么这个类必须定义为抽象类
抽象类的特点
①抽象类不能创建对象
抽象类如何创建对象呢?参照多态的方式,通过子类创建对象,这叫抽象类多态
②抽象类的子类
要么重写抽象类中所有抽象方法
要么是抽象类
接口
①接口用关键字interface修饰
public interface 接口名{ }
②类继承接口用implement表示
public class 类名 implement 接口名{ }
③接口不能被创建对象
接口如何实例化?参照多态的方式,通过实现类对象实例化,这叫接口多态
多态的形式:具体类多态,抽象类多态,接口多态
多态的前提:有继承或者实现关系,有方法重写,有夫(类/接口)引用指向(子/实现)类对象
④接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类
接口的成员特点
成员变量:只能是常量,默认修饰符:public static final
构造方法:接口没有构造方法,因为接口主要是对行为进行抽象类的,没有具体存在一个类如果没有父类,默认继承object类
成员方法:只能是抽象方法 默认修饰符:public abstract
类和接口的关系
类和类的关系
继承关系,只能单继承,但是可以多层继承
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
接口和接口的关系
继承关系,可以单继承,也可以多继承
类名作为形参和返回值
方法的形参是类名,其实需要的是该类的对象
方法的返回值是类名,其实返回的是该类的对象
抽象类名作为形参和返回值
方法的形参是抽象类名,其实需要的是该抽象类的子类对象
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
接口名作为形参和返回值
方法的形参是接口名,其实需要的是该接口的实现类对象
方法的返回值是接口名,其实返回的是该接口的实现类对象
内部类
内部类可以直接访问外部类的成员变量,包括私有
外部类如果访问内部类的成员方法,必须创建该类的对象
成员内部类如何创建对象呢(前提是内部类不是私有的,如果要用内部类的方法,可以先在外部类的方法里边创建一个对象调用方法,然后在测试类里边创建外部类的对象 调用这个外部类的方法)
格式:外部类名.内部类名 对象名=外部类对象.内部类对象;
范例:Outer.Inner oi = new Outer().new Inner();
局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
匿名内部类(其实它是一个对象,可以直接调用抽象类或接口方法)
格式: new类名或者接口名(){
重写方法;
}
Arrays
方法名 | 说明 |
public static String to String(interesting【】a) | 返回指定数组的内容的字符串表示形式 |
public static void sort (int【】a) | 按照数字顺序排列指定的数组 |
Math
方法名 | 说明 |
public static int abs(int a) | 返回参数的绝对值 |
public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
public static double floor(double a) | 返回小于或等于参数的最小double值,等于一个整数 |
public static int round(float a) | 按照四舍五入返回最接近参数的int |
public static int max (int a,int b) | 返回两个int值中较大的值 |
public static int min (int a, intb) | 返回两个int值中较小的值 |
public static double pow(double a,double b) | 返回a的b次幂 |
public static double random() | 返回值为double的正值【0.0,1.0) |
System
方法名 | 说明 |
public static void exit (int status) | 终止当前运行的Java虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
看方法的源码,按住方法按Ctrl+B;
数组和字符串的区别:
对于字符数组,其长度是固定的,其中任何一个数组元素都可以为 null 字符。 因此,字符数组不一定是字符串。 对于字符串,它必须以 null 结尾,其后的字符不属于该字符串。 字符串一定是字符数组,它是最后一个字符为 null 字符的字符数组。
基本类型包装类
将基本数据类型封装对象的好处在于可以在对象中定义更多的功能方法操作改数据
常用的操作之一;用于基本数据类型与字符串之间的转化
基本数据类型 | 包装类 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Char |
boolean | Boolean |
Integar
静态方法获取对象:
public static Integer valueof (int a) 或(string b)
案例:
Integer i1 = Integer.valueOf(100); System.out.println(i1); Integer i2 = Integer.valueOf("gh2hu"); System.out.println(i2);
Int和String相互转换
案例:int number = 100;
String s2 = string.valueof(number);
string s = “100”;
int x = Interget.parseInt(s);
自动装箱和拆箱
装箱:把基本数据类型转换为对应的包装类类型
拆箱:把包装类类型转换为对应的基本数据类型
自动装箱:Integer i = 100;
i += 200; i = i+200; i+200自动拆箱 i = i+200自动装箱
注意:在使用包装类类型的时候,如果做操作,最好先判断是否为null
Date(代表了一个特定的时间,精确到毫秒)
方法名 | 说明 |
public Date() | 分配一个Date对象,并初始化,以便它代表它分配的时间,精确到毫秒 |
public Date(long date) | 分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
public long get Time() | 获取的是日期对象从1970年1月1日00:00:00到现在的毫秒值 |
public void setTime(long time) | 设置时间,给的是毫秒值 |
SimpleDateFormat
方法名 | 说明 |
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat,使用给定的模式和默认的日期格式 |
Date转String和String转Date
报错可以按Alt+enter键去解决
工具类:构造方法私有,成员方法静态
Calendar
异常
Error:严重问题不需要处理
Exception:称为异常类,它表示程序本身可以处理的问题
RuntimeException:在编译期是不检查的(可以编译),出现问题后,需要我们回来修改代码
非RuntimeException:编译器就必须处理的(不可以编译),否则程序不能通过编译,就更不能正常运行了
异常处理之try...catch
Throwable的成员方法
方法名 | 说明 |
public String getMessage() | 返回此throwable的详细信息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
异常处理之throws
编译时异常有两种处理方法:tyr...catch...或者throws,如果采取throws这种方案,调用的方法也需要处理
运行时异常可以不处理:出现问题后,需要我们回来修改代码。
自定义异常
Collection集合概述和使用
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
JDK不提供此接口的任何直接实现,它提供更具体的子接口(如set和list)实现
创建Collection集合的对象
多态的方式
具体的实现类ArrayList
Collection集合常用方法
方法名 | 说明 |
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
Collection 集合的遍历
Iterator:迭代器,集合的专用遍历方式
Iterator<E> Iterator():返回此集合中元素的迭代器,通过集合的 Iterator()方法得到
迭代器是通过集合的 Iterator()方法得到的,所以我们说它是依赖于集合而存在的
Iterator中的常用方法
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回true
List集合概述和特点
List集合概述
有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素并搜索列表中的元素
与Set集合不同,列表通常允许重复的元素
List集合的特点
有序:存储和取出的元素顺序一致
可重复:存储的元素可以重复
List集合特有方法
方法名 | 说明 |
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
并发修改异常
ConcurrentModificationException
产生原因
迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案
用for循环遍历,然后用集合对象做对应的操作即可
ListInterator:列表迭代器
通过List集合的ListInterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListInterator中的常用方法
E next():返回迭代中的下一个元素
boolean hasNext():如果迭代具有更多元素,则返回true
E previous():返回列表中的上一个元素
boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e):将指定的元素插入列表
增强for循环
增强for:目的是简化数组和Collection集合的遍历
实现Iterable接口的类允许其对象成为增强型for语句的目标
增强for的格式
for(元素数据类型,变量名:数组或者Clooection集合){
//在此处使用变量即可,该变量就是元素
}
数据结构之栈和队列
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
栈是一种数据先进后出的模型
相反队列是一种先进先出的模型
List集合子类的特点
List集合常用子类:ArrayList,LinkedList
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
LinkedList集合的特有功能
方法名 | 说明 |
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
Set集合概述和特点
Set集合特点:
①不包含重复元素的集合
②没有带索引的方法,所以不能使用for循环遍历
哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
对象的哈希值特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的,但是如果重写hashCode()方法的话,可以让不同的对象哈希值相同
HashSet集合概述和特点
底层数据结构是哈希表
对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用for循环遍历
由于是Set集合,所以是不包含重复元素的集合
HashSet集合储存学生对象并遍历
①定义学生类
②创建HashSet集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合(增强for)
⑥在学生类中重写两个方法(目的是不让有重复的元素)
hashCode()和equals()
LinkHasSet集合概述和特点
哈希表和链表实现的Set接口,具有可预测的迭代顺序
由链表保证元素有序,也就是说元素的储存和取出顺序是一致的
由哈希表保证元素唯一,也就是说没有重复的元素
TreeSet集合概述和特点
元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet();根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for循环
由于是set集合,所以不包含重复元素的集合
自然排序Comparable的使用
用TreeSet集合储存自定义对象,无参构造方法使用的是自然排序对元素进行排序的
自然排序,就是让元素所属的类实现Comparable接口,重写ComparableTo(To)方法
重写方法时,一定要注意排序规则必须要按照要求的主要条件和次要条件来写
比较器排序Comparator的使用
用TreeSet集合储存自定义对象,无参构造方法使用的是自然排序对元素进行排序的
比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写compare(TO1,TO2)方法
重写方法时,一定要注意排序规则必须要按照要求的主要条件和次要条件来写
泛型的定义和好处
<类型>:指定一种类型的格式,这里的类型可以看做是形参
<类型1,类型2>:指定多种类型的格式,多种类型之间用逗号隔开,这里的类型可以看做是形参
将来具体调用时候给定的类型可以看做是实参,并且实参的类型只能是引用数据类型
泛型的好处
把运行期间的问题提前到了编译期间
避免了强制类型转换
泛型类
格式:修饰符class类名<类型>{ }
范例:public class sadsa <T>{ }
此处T可以随便写为任意标识,常见的如T,E,K,V等形式的参数用于表示泛型
泛型方法
格式:修饰符 <类型>返回值类型 方法名(类型 变量名){ }
范例:public <T> void show (T y) { }
泛型接口
格式:修饰符interface接口名<类型>{ }
范例:public interface asdda <T> { }
类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
类型通配符<?>
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
类型通配符的上限:<?extends 类型>
List<?extends Number>:它表示的类型是Number或者其子类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
类型通配符的下限:<?super类型>
List<?super Number>:它表示的类型是Number或者其父类型
可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
格式:修饰符 返回值类型 方法名(数据类型...变量名){ }
范例:public static int sum (int...a){ }
可变参数注意事项
①这里的变量其实是一个数组
②如果一个方法有多个参数,包含可变参数,可变参数要放到最后
可变参数的使用
Array工具类中有一个静态方法
public static<T>List<T> asList(T...a):返回由指定数组支持的固定大小的列表
返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法
public static<E>List<E> of(E...element):返回包含任意数量元素的不可变列表
返回的集合不能做增删操作
Set接口中有一个静态方法
public static<E>Set<E> of(E...element):返回一个包含任意数量元素的不可变集合
在给元素的时候,不能给重复的元素
返回的集合不能做增删操作,没有修改的方法
Map集合概述和使用
①Intreface Map<K ,V> K:键的类型;V:值的类型
②将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
③举例:学生的学号和姓名
itheima001 林青霞
itheima002 张曼玉
创建 Map集合的对象
①多态的方式
②具体的实现类HashMap
Map集合的基本功能
方法名 | 说明 |
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的键 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
Map集合的获取功能
方法名 | 说明 |
V get(Object key) | 根据键获取值 |
Set<K>keyset() | 获取所有键的集合 |
Collection<V>values() | 获取所有值的集合 |
Set<Map.Entry<K,V>>entrySet() | 获取所有键值对对象的集合 |
Collections概述和使用
Collections类的常用方法
public static <T extends Comparable<?superT >>void sort(List<T>list):将指定的列表按升序排序
public static void reverse (List<T>list):反转指定列表中的顺序
public staticvoid shuffle(List<T>list):使用默认的随机源随机排列指定的列表
File类概述和构造方法
File:它是文件和目录路径名的抽象表示
文件和目录是可以通过File封装成对象的
对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。他可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
方法名 | 说明 |
File(String pathname) | 通过将指定的路径名字符串转换为抽象路径名来创建新的File实例 |
File(String parent,String child) | 从父路径名字符串给子路径名字符串创建新的File实例 |
File(File parent,String child) | 从父抽象路径名和子路径名字符串创建新的File实例 |
File类创建功能
方法名 | 说明 |
public boolean createNewFile() | 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 |
public boolean mkdir() | 创建由此抽象路径名命名的目录 |
public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
File类判断和获取功能
方法名 | 说明 |
public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
public boolean isFile() | 测试此抽象路径名表示的FIle是否为文件 |
public boolean exists() | 测试此抽象路径名表示的File是否存在 |
publicString getAbsolutaPath() | 返回此抽象路径名的绝对路径名字符串 |
public String getPath() | 将此抽象路径名转换为路径名字符串 |
public String getName() | 返回由此抽象路径名表示的文件或目录名称 |
public String[] list() | 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组 |
public File[] listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
File类删除功能
方法名 | 说明 |
public boolean delete() | 删除由此抽象路径名表示的文件或目录 |
绝对路径和相对路径
①绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:E\\itcast\\java.txt
②相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\\java.txt
删除目录时的注意事项
如果一个目录中有内容,(目录,文件)不能直接删除,应该先删除目录中的内容,最后才能删除目录
递归
递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象
递归解决问题的思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
递归解决问题要找到两个内容
递归出口:否则会出现内存溢出
递归规则:与原问题相似的规模较小的问题
IO流概述和分类
IO流分类:
按照数据的流向
输入流:读数据
输出流:写数据
按照数据类型来分
字节流:字节输入流,字节输出流
字符流:字符输入流,字符输出流
那么这两种流都在什么情况下使用呢
如果数据通过Window自带的笔记本软件打开,我们还可以读懂里面的内容,就使用字符流
否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流。
字节流写数据
字节流抽象基类
InputStream:这个抽象是表示字节输入流的所有类的超类
OutputStream:这个抽象类是表示字节输出流的所有类的超类
子类名特点:子类名称都是以其父类名作为子类名的后缀
FileOutputStream:文件输出流用于将数据写入File
FileOutputStream(String name):创建文件输出流以指定的名称写入文件
ObjectOutputStream可以帮助FileOutputStream将字符转为字节
前提是这个类要实现serializable这个接口
案例:
//将person对象写入文件person.obj中
person p = new person
FileOutputStream fos = new FileOutputStream("person.obj")
ObjectOutputStream oos = new ObjectOutputStream(fos)
oos.writeObject(p)
使用字节输出流写数据的步骤
创建字节输出流的对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
调用字节输出流对象的写数据方法
释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
字节流写数据的三种方式
方法名 | 说明 |
void write(int b) | 将指定的字节写入此文件输出流 |
void write(byte【】b) | 将数组b写入到此文件输出流 |
void write(byte【】b int a int c) | 将数组b 从索引a 写到索引c |
字节流写数据的两个小问题
①字节流写数据如何实现换行呢?
写完数据后,加换行符
Windows:\r\n
linux:\n
mac:\r
②字节流写数据如何实现追加写入呢
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件,如果第二个参数为true,则字节将写入文件的末尾而不是开头
字节流写数据加数据异常
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源
特点:被finally控制的语句一定会执行,除非JVM退出
try{
可能出现异常的代码
}catch(异常类名,变量名){
异常的处理代码
}finally{
执行所有清除操作
}
字节流复制文本文件案例
字节流复制图片案例
字节缓冲流(运行速度更快)
BufferOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节而不必为写入的每个字节导致底层系统的调用
BufferInputStream:创建BufferInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所含的输入流中重新填充,一次很多字节
构造方法:
字节缓冲输出流:BufferOutStream a = new BufferOutStream(new FileOutputStream(“E:\\ASUS”))
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
为什么会出现字符流
由于字节流操作中文不是特别的方便,所以Java就提供字符流
字符流=字节流+编码表
用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢
汉字在储存的时候,无论选择哪种编码储存,第一个字节都是负数
字符串中的编码解码问题(用什么编码就用什么解码)
字符流中的编码解码问题
字符流中和编码解码问题相关的两个类
InputStreamReader(File Reader)
OutputStreamWriter(File Writer)
字符流写数据的5种方式
方法名 | 说明 |
void write(int c ) | 写一个字符 |
void write(char[] c) | 写入一个字符数组 |
void write(char【】c ,int a,int b) | 写入字符数组的一部分 |
void write(String s) | 写一个字符串 |
void write(String s,int a,int b) | 写一个字符串的一部分 |
flush() | 刷新流,还可以继续写数据 |
字符流读数据的两种方式
方法名 | 说明 |
int read() | 一次读一个字符数据 |
int read(char【】 c) | 一次读一个字符数组数据 |
字符缓冲流
BufferedWriter:(Writer out)
BufferedReader:(Reader in)
字符缓冲流特有功能
BufferedWriter:
void newLine( ):写一行行分隔符,行分隔符字符由系统属性定义
BufferedReader:
public String readLine( ):读一行文字。结果包含行的内容,不包括任何终止字符,如果流的结尾已经到达,则为null
(复制多级文件夹)自己去练习
复制文件的异常处理
JDK7改进方案:
try(定义输入流对象,定义输出流对象){
可能出现异常的代码
}catch(异常类名 变量名){
异常的处理代码
}
JDK9改进方案:
定义输入流对象;
定义输出流对象;
try(输入流对象,输出流对象){
可能出现异常的代码
}catch(异常类名,变量名){
异常的处理代码
}
标准输入流
BufferedReader br = new BufferedReader( new InputStreamReader(System.in))
写起来太麻烦,Java就提供了一个类实现键盘录入
Scanner sc = new Scanner(System.in);
标准输出流
输出语句的本质:是一个标准的输出流
PrintStream ps = System.out;
PrintStream类有的方法,System.out类可以调用
字节打印流
PrintStream(String filename):使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的时候会原样输出
例如:ps.write 和 ps.print
字符打印流
方法名 | 说明 |
PrintWriter(String filename) | 使用指定的文件名创建一个新的PrintWriter,不带自动刷新 |
PrintWriter(Writer out,boolean autoflush) | 创建一个新的PrintWriter ①out:字符输出流 ②autoflush:一个布尔值,如果为真则刷新 |
PrintWriter提供了直接对文件进行写操作的构造器: PrintWriter(String filename) PrintWriter(File file) 上述两个构造器内部都进行了4层流连接 PrintWriter->BufferedWriter->OutputStreamWriter->FileOutputStream PW:负责按行写出字符串 BW:块写文本数据加速(内部有一个默认8192长度的字符数组) OSW:将写出的字符转字节 FOS:将字节写入到文件中
对象序列化流
对象序列化流:ObjectOutputStream
将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectOutputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久储存。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream序列化对象的方法
序列化对象的方法:
void writeObject(Object obj):将指定的对象写入ObjectOutputStream
注意:
一个对象要想被序列化,该对象所属的类必须实现Serializable接口
Serializable是一个标记接口,实现该接口,不需要重写任何方法
对象反序列化流:ObjectInputStream
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法:
ObjectInputStream(InputStream in):创建从指定InputStream读取的ObjectInputStream
反序列化对象的方法:
Object readObject():从ObjectInputStream读取一个对象
Properties
Properties概述:
是一个Map体系的集合类
Properties可以保存到流中或从流中加载
方法名 | 说明 |
Object setProperty(String key,String value) | 设置集合的键和值,都是String类型,底层调用Hashtable方法put |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性 |
Set<String>stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 |
Properties和IO流结合的方法:
方法名 | 说明 |
void load (InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStream out,String comments) | 将此属性列表(键和元素对)写入Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流 |
void store(Writer writer,String comments) | 将此属性列表(键和元素对)写入Properties表中,以适合于使用load(Reader)方法的格式写入输出字符流 |
进程和线程
进程:是正在运行的程序
是系统进行资源分配和调用的独立单位
每一个进程都有它自己的内存空间和系统资源
线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序
多线程:一个进程如果有多条执行路径,则称为多线程程序
案例:记事本和扫雷
多线程的实现方式
①定义一个类MyThread继承Thread类
②在MyThread类中重写run方法
③创建MyThread类的对象
④启动线程
两个小问题:
①为什么要重写run方法?因为run()是用来封装被线程执行的代码
②run()和start()方法的区别?
run():封装线程执行的代码,直接调用,相当于普通方法的调用
start():启动线程;然后由JVM调用此线程的run()方法
设置和获取线程名称
Thread类中设置和获取线程名称的方法
①void setName(String name):将此线程的名称更改为参数name
②String getName():返回此线程的名称
③通过构造方法也可以设置线程名称
如何获取main()方法所在的线程名称?
public static Thread currentThread():返回对当前正在执行的线程对象的的引用
Thread类中设置和获取线程优先级的方法
public final ine getPriority():返回此线程的优先级
public final void setPriority(int newPriority):更改此线程的优先级
线程默认优先级是5;线程优先级的范围是1-10
线程优先级高仅仅表示线程获取CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果
线程控制
方法名 | 说明 |
static void sleep(long millis) | 使当前正在执行的线程停留(暂停执行)指定的毫秒数 |
void join() | 等待这个线程结束 |
void setDaemon(boolean on) | 将此线程标记为守护线程,当运行的线程都是守护线程时,java虚拟机将退出 |
多线程的实现方式②
①定义一个类MyRunnable实现Runnable接口
②在MyRunnable类中重写run()方法
③创建MyRunnable类的对象
④创建Thread类的对象,把MyRunnable对象作为构造方法的参数
⑤启动线程
多线程的实现方案有两种
①继承Thread类
②实现Runnable接口
相比继承Thread类,实现Runnable接口的好处
①避免了java单继承的局限性
②适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思维
同步代码块
锁多条语句操作共享数据,可以使用同步代码块实现
格式:
synchronized(任意对象){
多条语句操作共享数据的代码
}
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
同步的好处和弊端
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,所以是很耗资源的,无形中会降低程序的运行功率
同步方法
同步方法:就是把synchronized关键字加到方法上
格式:
修饰符synchronized返回值类型 方法名(方法参数){ }
同步方法的锁对象是什么呢?
this
同步静态方法:就是把synchronized关键字加到静态方法上
格式:
修饰符 static synchronized返回值类型 方法名(方法参数){ }
同步静态方法的锁对象是什么呢?
类名.class
线程安全的类
StringBuffer Vector Hashtable
Lock锁
Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock中提供了获得锁和释放锁的方法
void lock( ):获得锁
void unlock( ):释放锁
Lock是接口所以不能直接实例化,这里采用它的实现类ReentranLock来实例化
ReentranLock的构造方法
ReentranLock( ):创建一个ReentranLock的实例
生产者消费者模式概述
为了体现生产和消费过程中的等待和唤醒,Java就提供了几个方法供我们使用,这几个方法在Object类中Object类的等待和唤醒方法
方法名 | 说明 |
wait( ) | 导致当前线程等待,直到另一个线程调用该对象的notify( )方法或notifyAll( )方法 |
void notify( ) | 唤醒正在等待对象监视器的单个线程 |
void notifyAll( ) | 唤醒正在等待对象监视器的所有线程 |
InetAddress的使用
为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用
InetAddress:此类表示Inetnet协议(IP)地址
方法名 | 说明 |
static InetAddress getByName(String host) | 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址 |
String getHostName( ) | 获取此IP地址的主机名 |
String getHostAddress( ) | 返回文本现实中的IP地址字符串 |
UDP发送数据
发送数据的步骤:
①创建发送端的Socket对象(DategramSocker)
DategramSocker()
②创建数据,并把数据打包
DategramPacket(byte[] buf , int length, InetAddress address, int port)
③调用DategramSocker对象的方法发送数据
void send(DategramPacket p)
④关闭发送端
void close
UDP接受数据
接收数据的步骤:
①创建接收端的Socker对象(DategramSocker)
DategramSocker(int port)
②创建一个数据包,用于接受数据
DategramPacket(byte[] buf , int length)
③调用DategramSocker对象的方法接收数据
void receive(DategramPacket p)
④解析数据包,并把数据在控制台显示
byte【】getDate()
int getLength()
⑤关闭接收端
void close()
TCP发送数据
发送数据的步骤
①创建客户端的Socket对象(Socket)
Socket(String host,int port)
②获取输出流,写数据
OutputStream os = s.getOutputStream();
os.write(“asdsad”)
③释放资源
void close
TCP接收数据
接收数据的步骤
①创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port)
②监听客户端连接,返回一个Socket对象
Socket accept()
③获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
④释放资源
void close
Lambda
Lambda表达式的格式:
格式:(形式参数)->{代码块}
形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
->:由英文中画线和大于符号组成,固定写法。代表指向动作
代码块:使我们具体要做的事情,也就是以前我们写的方法体内容
Lambda表达式的使用前提
①有一个接口
②接口中有且仅有一个抽象方法
Lambda表达式的省略模式
①参数类型可以省略,但是有多个参数的情况下,不能只省略一个
②如果参数有且仅有一个,那么小括号可以省略
③如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
Lambda表达式的注意事项
①使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
②必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口:Runnable r = ()->System.out.println("asdsad");
根据调用方法的参数得知Lambda对应的接口:
new Thread(()->System.out.println("asdsad")).start;
Lambda表达式和匿名内部类的区别
所需类型不同
①匿名内部类,可以是接口,也可以是抽象类,还可以是具体类
②Lambda表达式只能是接口
使用限制不同
①如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
②如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
①匿名内部类:编译之后产生一个单独的.class字节码文件
②Lambda表达式:编译之后没有.class字节码文件。对应的字节码会在运行的时候动态生成
接口中的默认方法
格式:public default 返回值类型 方法名 (参数列表){ }
接口中默认方法的注意事项
①默认方法不是抽象方法,所以不强制被重写。但可以被重写,重写的时候去掉default关键字
②public可以省略,default不能省略
接口中的静态方法
格式:public static 返回值类型 方法名 (参数列表){ }
接口中静态方法的注意事项
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略
接口中的私有方法
格式1:private 返回值类型 方法名 (参数列表){ }
格式2:private static 返回值类型 方法名 (参数列表){ }
接口中私有方法的注意事项
默认方法可以调用私有的静态方法和非静态方法
静态方法只能调用私有的静态方法
引用类方法
引用类方法,其实就是引用类的静态方法
格式:类名::静态方法
范例:Integer::parselnt
引用对象的实例方法
引用对象的实例方法,其实就引用类中的成员方法
格式:对象::成员方法
范例::(a ::asd)
Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
引用类的实例方法
引用类的实例方法,其实就是引用类中的成员方法
格式:类名::成员方法
范例:String::subString
Lambda表达式中有多个参数的时候,第一个参数作为调用者。后面的参数传递给它的方法。
引用构造器
引用构造器,其实就是引用构造方法
格式:类名::new
范例:Student::new
Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
函数式接口
函数式接口:有且仅有一个抽象方法的接口
如何检测一个接口是不是函数式接口呢?
@Functionallnterface
放在接口定义的上方:如果是函数式接口,编译通过
函数式接口作为方法的参数
如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数
函数式接口作为方法的返回值
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为结果返回
常用的函数式接口
Supplier<T> ,Consumer<T>, predicate<T>,Function<T>
Stream流
Stream流的生成方式
①生成流:对象.stream
②中间操作:filter()
③终结操作:forEach()
Stream流常见的生成方式
①Collections体系的集合(Set和List)可以使用默认方法stream()生成流
②Map体系的集合间接生成流
③数组可以通过Stream接口的静态方法of(T...values)生成流
stream流中间操作之filter&limit&skip
stream流中间操作之concat&distinct
stream流中间操作之sorted
stream流中间操作之map&mapToInt
stream流终结操作之forEach&count
stream流的收集操作
反射
Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译器就完成确定,在运行期仍然可以扩展。
获取Class类对象的三种方法
反射获取构造方法并使用
反射获取构造方法并使用练习
反射获取成员变量并赋值
反射获取成员方法并赋值
反射获取成员方法练习
反射越过泛型检查
类加载器
:是负责加载类的对象
Java运行时有以下内置类加载器
①Bootstrap class loader:它是虚拟机的内置类加载器,通常表示为null,并且没有父null
② class loader:平台类加载器可以看到所有平台类,平台类包括由平台类加载器或其祖先定义的JavaSE平台API,其实现类和JDK特定的运行时类
③System class loader:它也被称为应用程序类加载器,与平台类加载器不同,系统类加载器通常用于定义应用程序内路径,模块路径和JDK特定工具上的类
④类加载器的继承关系:System的父加载器为Platform,Platform的父加载器为Bootstrap
ClassLoader中的两个方法
①static ClassLoader getSystemLoader():返回用于委派的系统类加载器
②ClassLoader getParent():返回父类加载器进行委派
反射练习之运行配置文件指定内容
XML
1、XML是什么?
XML是一种可扩展的标记语言。
它是一种数据表示格式,可以用于自定义数据格式
2、XML的作用是什么
用于进行存储数据和传输数据
作为软件的配置文件
数组扩容
allout = Arrays.copyof(allout,allout.length+1)
最牛遍历
集合c.foreach(s ->System.out.println(s))
如果想操作这个遍历的集合那么就是
c.foreach(s ->{
if(){}
System.out.println(s)})