javase基础大全
java的语言特点
-
面向对象(贴近人类思维模式,模拟现实世界,解决现实问题)
-
简单性(自动内存管理机制、不易造成内存溢出;简化流程处理、语义清晰)
-
跨平台(操作系统、服务器)
Java运行机制
-
JDK :开发工具和类库、包含了jre
-
JRE:运行环境,包含了jvm虚拟机
-
JVM:虚拟机,不同操作系统模拟相同的环境 源文件.java通过虚拟机编译为.class文件
环境变量
变量:系统属性; 变量名----变量值
JAVA_HOME---jdk的根目录, E:\jdk\Java\jdk1.8.0_51
path ----jdk安装目录里的bin;可以任意的路径访问命令; %JAVA_HOME%\bin E:\jdk\Java\jdk1.8.0_51\bin classpath: 类路径;----自从jdk1.5版本后可以不用配;
.;%JAVA_HOME%\lib;
JDK目录;JDK的bin目录:存放的是exe文件,可称为执行文件;
标识符命名规则
语法规则: 由数字、字母、下划线、$组成; 不能以数字开头;
约定: 见名知义; 类名:一个或多个单词首字母大写;例:Hello、HelloWord 方法/变量:一个或多个单词,第一个字母小写,其它单词字母大写;例: getName name pass 包名:全小写,用点分隔,反向域名;例:com.qf.test 常量:全部大写并且用_分隔多个单词;例:HELLO_WORLD
变量
声明变量 给变量赋值
初始化变量
-
第一种定义方式:
类型 变量名=值;
-
第二种定义方式: 类型 变量名; 变量名=值;
-
全局变量
定义在类内,方法外
类内所有的方法里都能用
static 类型 变量名;
public class Demo{
static int age;//全局变量
}
第一个java程序
创建源文件
Demo1.java-----文件名
public class Demo1{ ----类名
}
class Demo2{
}
class Demo3{
}
注:在源文件中,只有被public修饰的类必须与文件名相同;
类名是不可重复的;
通过命令编译生成class文件
javac命令:编译生成字节码文件; javac Demo1.java-->执行-->生成 Demo1.class
执行class文件
java命令:执行字节码文件 java Demo1
数据类型(8种)
基本数据类型
整型
默认整型为int
-
byte 1个字节 范围:-128--127
-
short 2个字节
-
int 4个字节
-
long 8个字节
浮点型
默认浮点型为double,在float类型变量赋值时,常量后必须添加f和F
-
float 4个字节
-
double 8个字节
布尔类型
-
boolean 1个字节 真true/假false
字符型
-
char 2个字节 使用单引号定义 '',引号中只能写一个字符(数字、中文、英文、其它符号)
引用数据类型
字符串
数组
对象
类型转换
自动类型转换
目标类型 = 原类型
-
小转大,整数转浮点数,字符转整数
byte b=100;
int c=b; //类型兼容 byte short int long
double f=c;//类型兼容 整型和浮点型
c='a';//类型兼容 97
强制类型转换
目标类型 = (目标类型)原类型
-
大转小,浮点转整数,整数转字符
byte b=100;
int c=b; //类型兼容 byte short int long
double f=c;//类型兼容 整型和浮点型
c='a';//类型兼容 97
b=(byte)c;//
c=(int)f;
char cc=(char)c;
注:将源类型转为目标类型后,如果数值超出目标类型的范围,则会造成数据的不准确存放;
转义字符
在字符串中表达一些特殊符号时,使用转义字符
| 换行 | \n |
|---|---|
| 制表符 | \t |
| 双引 | \ " |
| 单引 | \ ' |
| 斜线 | \ \ |
运算符
算数运算符
+ 加法/拼接(当+两侧任意一侧出现String字符串时为拼接)
-
*
/
%---求余数
比较运算符
> 大于
< 小于
<= 小于或等于
>= 大于或等于
== 等于
!= 不等于
注:比较结果一定是boolean类型
例:boolean flag=yushu==1;
赋值运算符
= :将符号右边的值赋给左边的变量,例:int x=10; int y=x+100;
逻辑运算符
-
&& 与 两个都真 ,条件为真
-
|| 或 两个有一个为真,条件为真
-
!非 真变假,假变真
三元运算符
-
表达式?结果1:结果2(一真二假)
条件判断语句
语法
if(表达式){
//执行语句1
}else{
//执行语句2
}
//表达式为真执行语句1 为假执行语句2
if(表达式1){
//执行语句1
}else if(表达式2){
//执行语句2
}else if(表达式3){
//执行语句3
}else{
//执行语句4
}
//表达式1为真执行语句1 为假判断表达式2 表达式2为真执行语句2 为假判断表达式3 表达式3为真执行语句3 为假执行语句4
循环语句
break; --终止当前循环;
while(条件){//变量:1 2 3 4 5 6 7 8 9 10
if(条件){//取值为5
break;
}
System.out.println(变量);//结果:1 2 3 4
}countine; --结束本次循环;
while(条件){//变量:1 2 3 4 5 6 7 8 9 10
if(条件){//取值为5
continue;
}
System.out.println(变量);//结果:1 2 3 4 [5跳过本次循环]6 7 8 9 10
}
-
while循环
while(条件表达式){
//循环体
//迭代变量 i+=1
}
//条件表达式成立则一直执行循环体
-
for循坏
for(初始条件1;循环条件2;迭代变量4){
//循环体3
}
1 234 234 234....2不成立
-
加强for循环
for增强循环:每循环一次,将数组中的元素依次赋值为变量;
for(数组类型 变量:数组名){
System.out.println(变量);
}
-
do{}while循环
先无条件执行,再进行条件判断
do{
//循环体
}while(条件表达式);
-
switch开关分支语句
等值条件:变量与取值之间等于的关系;
变量的类型:byte short int char String,枚举类型
switch(变量){
case 值1:
语句1;
break;
case 值2:
语句2;
break;
case 值3
...
break;
default: //默认以上皆不满足时,执行的语句部分;
....
break;
}
语法:当变量取值1时,执行语句1;如果变量取值2时,执行语句2;
方法
函数也叫方法;用于实现一个功能;
注:同一类内方法不能同名,除非重载;
参数: 形参:定义方法时的形式参数,只有类型 实参:调用方法时的值,只有值 调用方法时,将实参的值依次赋给形参; 返回值: 将调用方法的结果通知调用者; 定义方法时,返回值类型与return后的值一致; 定义方法时,如果方法没有返回值,也可以在方法内使用空return 结束方法;
-
主方法:main
public static void main(String[] args){
//语句
}
-
方法的定义
public static void 方法名(){
//功能
}
注:
参数列表:类型、个数、顺序
返回值:return 值;return是方法的最后一句话;如果一个方法有多个出口,都必须有return语句;
-
方法调用
-
直接调用:
方法名() -
方法类型
-
有参数,有返回值;
-
有参数,无返回值;
-
无参,无返回值;
-
无参,有返回值
-
-
方法重载
在同一类内,方法同名,参数列表不同;
注:参数列表体现:参数个数、参数的顺序、参数的类型; 在类内出现相类似功能,但是参数不同,建议使用相同方法名定义;
-
方法重写
子类重写父类的方法:
@Override用于检查重写的语法
方法名/参数列表(参数个数、顺序、类型都相同)/ 返回值类型形同;
访问修饰符大于等于父类方法;
抛出异常小于等于父类方法
-
可变长参数
可变长参数: 类型固定,但是个数不确定,个数表示0个或任意多个: 在参数列表中只能出现一个; 必须出现在参数列表的最后; 被当作数组使用;
public static void test(int... x){ //x就是可变长参数
//x当作数组使用
for(int y:x){
System.out.println(y);
}
}
public static void test2(String... x){
}
//调用:
test()
test(10)
test(20,30)
....任意个参数
构造方法(构造器)
特征:
每个类都有一个默认的无参构造器,用于创建对象;
方法必须与类名相同,
构造器没有返回值 没有void
作用:
为了创建对象
单元测试
在方法声明前:添加注解@Test
alt+enter:添加测试环境;add junit4 to classpath;
单独运行测试方法:有@Test注解的方法就可以以run as junit运行
注:测试类建议不要使用Test作类名;
数组
一维数组
存储多个相同的数据类型;有固定长度;
属性:length
-
定义:数据类型[ ] 数组名 = new 数据类型[长度]
int[] arr = new int[n];
int[] arr = {1,2,3}
int[] arr = new int[]{1,2,3,4};
-
访问 读/写
数组名[下标];
arr[n]
数组名.length //数组长度
-
遍历:访问数组中所有元素
-
for
-
for each
-
-
数组的排序
-
冒泡排序
方式:
从第一位开始,相邻两位相比较,如果条件满足,执行两位置上的数相交换;依次,再将二三位的数相比较;
每比较一次,在数组中最后位置处获得最值;
int a[]
int temp = 0;
for(int j = a.length-1; j >=1;j++ ){
for(int i = 0;i<j;i++){
if(a[i]<a[i+1]){
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}-
选择排序
方式:
选择第一位与后续其它位相比较,如果条件满足,执行交换;依次再将第二位与其它位相比较,再将第三位与其它位相比较。。。。直到最后两个数比较完成
代码:从大小到/数组 int[] a
for(int i=0;i<a.length-1;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]<a[j]){
//两数交换
}
}
} -
-
数组扩容
数组的定义要求固定长度和统一类型;
int[] arr=new int[10];---原数组
需求:向原数组增加一个新元素;
问题:覆盖原数组的内容/下标越界;
解决方式:扩容
扩容原理:
创建新数组;
将原数组的内容依次赋值给新数组;
再将新数组返回;return
二维数组
数组中的元素又是一维数组
-
定义
int arr[][] = new int[行][列]
int arr[][] = {{0,0,0,},{0,0,0,},{0,0,0,}}
-
访问:读/写
//赋值
数组名[行下标][列下标]=值;
//取值
数组名[行下标][列下标];
-
遍历
数组名:brr
int[][] brr={
{1,2,3}, ---brr[0]
{4,5,6},
{7,8,9},
{10,11,12}
}
//for
for(int i = 0;i<arr.length;i++){
for(int j = 0;j<arr[i].length;j++){
System.out.print(a[i][j]);
}
System.out.println();
}
//加强for
for(int[] arr:brr){
for(int a:arr){
System.out.print(a);
}
System.out.println();
}
综合案列
登录;注册; 取款;存款;转账;修改密码;
[]数组; String[]user={"zhangsan"} String[]pass={"666"} String[]tel={"11111111"} int[]money={1000} 登录:用户名/密码 进行输入;比较;将输入的信息与存储的信息相比较 取款:输入取款金额;判断余额是否足够; 存款:放钞票;余额变化; 转账:另一个账户存在;余额判断;一方转出/另一方转入; 修改:输入原密码;验证正确;再次输入新密码,再次确认输入;密码保存;
字符串
-
比较
用equals方法:
String str = "aaa"
String str1 = "bbb"
str.equals(str1)
-
int 与 String之间转换
字符串转int,只包含数字字符串"123456"
/字符串转换整型:
int num = Integer.Valueof("123456");//字符串"123456" 转为int类型的 123456
//整型转换字符串转换:
int num = 3;
String str = num+"";
面向对象
类
抽取公共部分的行为、特征定义为一个类.
class Car{
//全局变量:属性====特征
//颜色/品牌/排量
//方法:普通方法====行为
//行驶/倒车/撞车
}
属性(fileld,字段,全局变量,属性,实例成员属性)
特点:
定义在类内、方法外;
在类内处处可用
有默认值
重名:
局部变量可与属性重名,此时局部变量优先级高
public class 类名{
int age;//属性
public void fangFa(){
}
}
随机类(Random)
Scanner---import java.util.Scanner;导包
Random--import java.util.Random导包
注:使用本包以外的其它先引入环境/导包/直接使用; 导入一个包里的多个类时,可以使用 * 通配;
//创建对象
Random rd = new Random();
//产生一个随机数
rm.nextInt(范围) [0~范围)左闭右开
rm.nextInt(9) 产生0~9的随机整数
-
随机字符串
String s =UUID.randomUUID().toString();
匿名内部类
相当于子类或实现类;多态使用场景;
抽象类 引用变理=new 抽象类(){
//抽象类的子类
//必须重写抽象方法
};
普通类 引用变量=new 普通类(){
//普通类的子类
//选择性重写方法
};
对象
创建对象,也叫实例化对象;
创建对象四步:
1.堆内存开辟空间
2.初始化对象属性
3.实现构造器代码块内容
4.赋值给引用变量
Car car = new Car();//堆内存中开辟新空间,新空间地址存入到引用变量;
引用变量的类型与对象要兼容
This关键字
调用本类内容
-
调用属性和方法
this.属性名
this.方法名
-
调用本类其他构造方法
调用本类构造时,必须定义在构造方法中的第一句话
this调用构造方法的语句只能出现一次
this()---调用无参构造
this(参数列表)--调用有参构造,按参数的类型、个数、顺序匹配对应的有参构造;
super关键字
super代表父类
调用父类属性、方法(非私有的)
super.属性
super.方法
-
调用父类的构造
super(参数):父类的构造
子类构造器中第一句默认super();
如果没有无参构造需要调用父类其他构造;
this()super()不能同时出现
super()的调用和super(参数)也不能同时出现;
封装
将复杂的实现过程封装在方法里,对外提供简单的调用
-
get/set
-
sexXXXX()通过方法传入数据(设置字段)
-
继承
父类:抽取子类共有的行为特征;
子类:可以调用父类的行为和特征,同时定义自己独有的行为和特征
//子类继承父类非私有成员
class 子类 extends 父类{
}
访问修饰符
private:仅限本类内访问
private 可以修改属性、方法、构造方法;
public:在任何地方都可以访问
public:可以修改类、方法、属性、构造方法
default:默认,当前类内、同一包
可以修饰类、属性、方法、构造方法
protected:当前类内、同一包、跨包后的子类中
用于修饰类、属性、方法、构造方法
多态
一种事务,多种不同形态:父类的引用指向子类的对象
子类和父类之间可以表现出多态;
任何一个子类都可以自动类型提升,提升为父类类型(宽泛的类型),可以将这个父类类型作为返回值/参数定义;达到统一编码,降低耦合度,减少冗余代码
场景一:将多态应用于返回值
class F3{}
class SF3 extends F3{}
class SF4 extends F3{}
class SF5 extends F3{}
class Factory{
public static 父类F3 getF3(int key){
//根据判断结果,返回不同的子类对象
if(key==1)
return new SF3();
else if(key==2)
.....
}
}
场景二:将多态应用于参数
class T{
public void test(){
Mster master=new Master();
Dog dog=new Dog();
master.feed(dog);
Cat cat=new Cat();
master.feed(cat);
master.feed(new Bird());
//以上参数中将子类对象自动向上类型提升,为父类Aniaml类型;
}
}
class Master{
/*public void feed(父类类型 参数){ //在方法调用时给参数传入具体的子类类型;
参数.eat();
}*/
public void feed(Animal obj){
//dog.eat();
obj.eat();
}
}
class Animal{
public void eat(){
System.out.println("eat....");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("dog eat....");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("cat eat....");
}
}
class Fish extends Animal{}
class Bird extends Animal{}
properties文件
在src下创建file-->后缀 properties的文件;
手动添加键值对:英文 键值=值
写程序:
// 创建对象:
Properties p=new Properties();
//加载文件:读文件的内容
p.load(当前类名.class.getClassLoader().getResourcesAsStream("properties文件名"));
// 根据键值获得值:
String 值=p.getProperty(键值)
向上转型(自动)
-
父类类型 引用变量 = 子类对象
向下转型(强制)
子类类型 引用变量 = (子类类型)父类对象
-
instanceof 用于判断父类类型中的真实类型与目标类型是否一致,可以防止运行时异常---类型转换异常
-
父类引用 instanceof 目标类型
-
Object obj=true;
if(obj instanceof String){//判断obj是否为String类型
String ss=(String)obj;
}
装箱
简单类型--》包装类;自动;
Integer num = 10;
拆箱
包装类--》简单类型;自动
Integer num = 10;
int a = num;
abstract关键字
抽象可以修饰类、方法
抽象类:被abstract修饰的类,不可被创建对象,类内可以包含抽象方法、普通方法
public abstract class 类名{
//属性、方法、构造方法(为子类而生)
//但是不能创建对象
//可能含有抽象方法
}
public class 子类 extends 抽象类{ //必须重写抽象父类的所有抽象方法
}
抽象方法:被abstract修饰的方法,没有方法体;只保留方法的声明,必须定义在抽象类内。
访问修饰符 abstract 返回类型 方法名(参数列表)异常 ;
static关键字(静态)
修饰属性、方法、代码块
-
静态属性
属于类的属性,类的所有实例对象都共享一个属性,
可以使用类名直接访问,也支持对象访问
-
静态方法
属于类;类的所有实例对象都共享一个方法;
可以使用类名直接访问,也支持对象访问
定义工具类里方法建议用static
静态方法里不能使用this和super,this和super代表对象,都需要先创建对象,而static与对象创建无关,有可能在对象创建之前就调用静态成员。
静态方法支持重载
静态方法可被继承
不支持重写和多态---多态情况下,不能访问子类独有的方法;
类加载
将类的信息读入到内存中保存
-
当前类创建对象
-
当前子类创建对象
-
调用当前类的静态属性、方法
-
Class.forName("全类名")
静态代码块
执行:
在类被加载时,优先创建对象和动态代码块之前,执行一次。
静态代码块里只能使用静态代码块
类内可以定义多个静态代码块,定义序即执行序;
static{
}
动态代码块
执行:
每创建一次对象,就优先于构造器执行一次
类内可以定义多个动态代码块,定义序即执行序;
动态代码块内可以使用静态属性和非静态属性;
{
}
final关键字
-
final表示不可改变的。
-
final修饰属性时,这个属性称为常量;一般建议全大写字母表示,多个单词之间下划线连接,在定义时必须初始化
关键字
final---最终的,可修饰类、方法、属性,不可修改
static---静态的,可修饰方法、属性、代码块(类加载时自动优先执行),属性类的成员
类加载:创建对象/创建子类对象/访问类成员方法/访问类成员属性/Class.forName(全类名即包名+类名)--反射技术
abstract--抽象的,可修饰类、方法;
private--私有,可以修饰属性、方法、构造方法(不允许类外创建对象)
interface--定义接口的关键字(属性都是public static final;方法都是public abstract;)
class--定义类的关键字;
public--公共的,没有任何限制;
default--默认;switch中有一个默认条件;
instanceof--在向下强转前,判断引用类型是不是一个子类对象
protected--受保护的,跨包后的子类中可以被访问;
this--代表当前类及其所有子类的对象;
super--代表父类的对象;
extends---继承的关键字;表示当前类的直接父类,而且只能有一个直接父类;
class 类1 extends 类2---类的声明;
interface 接口1 extends 接口2,接口3,接口4....---接口之间是多继承
注:如果一个类1继承一个父类2,同时实现一个子接口1,此时类1可以重写父类2中的方法,并且必须重写接口1中所有抽象方法(包含接口2、接口3、接口4.。。。);
class 类1 extends 类2 implements 接口1{
}
implements--类实现接口的关键字;类与接口之间是多实现;接口与接口之间是多继承;
注:abstract与private、final、static能不能同时使用;
接口
特殊的抽象类,用interface修饰,没有构造器,不能创建对象,静态常量属性;
声明接口:
public interface 接口名{
//属性:公开静态常量属性,默认含有public final static
public static final int AGE=20;
String name="test";
//方法:公开抽象方法,默认含有public abstract
public abstract void login(String name);
}
实现类:接口与类之间的关系用implements表示;也叫多实现;
public class 实现类 implements 接口1,接口2,接口3{
//当前类必须实现(重写)接口中所有抽象方法
}
泛型
用来定义一个类型的代号,并不是真正的
public interface Compare<T>{ //其中T表示泛型代号,并不是有一个类叫“T"
T test();
}
分包使用
实体类:com.qf.pojo,主要用于封装数据
数据访问层: com.qf.dao---Data Access Object数据访问对象,定义接口 com.qf.dao.impl--dao的实现包,定义接口对应的实现 注:一个接口可以有多个实现类; 定义一个标准,由不同的需要确定不同的实现类;
测试类: 单元测试;junit
集合
Collection集合
用于储存对象
泛型:Collection<引用类型>,此时泛型不能为简单类型
-
常用方法:
add(对象类型)
remove(对象):先查后删
查看所有:
-
迭代器遍历
Iterator<泛型> it=集合.iterator();
while(it.haxNext()){ //判断是否有下一个元素
it.next(); //取出下一个元素
}
-
for增强循环遍历
for(泛型类型 变量:集合){
//变量---取出的一个元素
}
-
removeif(Predicate filter)
按条件执行删除时使用;
Predicate<泛型> filter=new Predicate(){
public boolean test(泛型 变量){
//添加条件,满足则返回true;否则返回false;
return true/false;
}
};
List集合
有序的、有下标、可重复
常用实现类:LinkedList、ArrayList、Vector、Stack
集合的底层实现是数组:查询效率高 ArrayList
集合的底层实现是链表:增删效率高 LinkedList
List子接口比父接口Collection定义了更多的方法,体现在下标的访问,get(index)根据下标获得元素
遍历集合
for(int i=0;i<list.size();i++){
list.get(i);//获得一个集合中的元素
}
set集合
无序的、不可重复、没有下标
全部继承Collection接口的方法无额外的方法
HasHSet:可以去除元素的重复录入;如果录入重复,集合拒绝录入
判重依据:hashcode()如果相同,则再根据equals()方法,如果返回true,则判为相同;
系统内置类:String/Integer/Date/Boolean....
自定义类:
重写hashCode():返回相同值;
重写equals():在hashcode值相同的情况下,再根据equals方法返回结果判断,true--重复;false--没重复;
注:在equals方法中一般是属性值之间的比较
TreeSet:可以按默认规则对元素实现排序;
排序依据:要求添加到集合中的元素要实现compareable接口
系统内置类:String/Integer/Date/Boolean....
自定义类:
实现Comparable接口,重写compareTo方法,在方法内定义排序规则E
Map集合
Map是容器,可用于存储键值对,键值唯一,值可以重复
-
常用方法
新增:put(键值,值) / putAll(Map map)
修改:replace(键值,值) / replace(键值,原值,新值) / 当键值重复时,新值也会覆盖原值;
删除:remove(键值) / remove(键值,值)
查看:
查所有键值:Set<键值的类型> set= keySet();
查所有值:Collection<值的类型> c=values();
获得键值对:Set<Entry类型> s=entrySet(); ---Entry表示一对键值对
getKey()键值/getVlues()值
根据键值查一个值:get(键值)---获得值
String常用类
-
indexOf(str[,local]):从左向右查询,查询子串首次出现的下标,如果查不到,则返回-1;local默认为0; 例:"abcdefghilmn".indexOf("a")---返回0 "abcdefghilmn".indexOf("a",5)---返回-1
-
lastIndexOf(str[,local]):从右向左查询,查询子串首次出现的下标,如果查不到,则返回-1;local默认为字符串的最大下标(length()-1);
-
length():字符串长度;
-
endsWith: 以某个子串结尾
-
startsWith: 以某个子串开始
-
split("str"):使用str字符将原字符串分割为一个字符串数组String[]
String 常量字符
String ss1="ABC";
String ss2="ABC";
//ss1==ss2;字符串地址相同
String ss3=new String("ABC");
String ss4=new String("ABC");
//ss3==ss4;地址不同
//以下比较结果都为true
ss1.equals(ss2)
ss3.equals(ss4)
StringBuffer 动态字符串,线程安全,效率低
StringBuffer a1=new StringBuffer();
a1.append("字");
a1.append("符");
a1.append("串");
//输出a1的内容:字符串
StringBuilder 动态字符串,线程不安全,效率高
StringBuilder a1=new StringBuilder();
a1.append("字");
a1.append("符");
a1.append("串");
//输出a1的内容:字符串
注:String不能修改原字符串内容,每次修改时会创建一个新字符串; StringBuilder/StringBuffer可直接修改原字符串内容
Date类
日期类:java.util.Date父类; java.sql.Date子类;
-
创建时间
-
new Date()----当前时间
-
new Date(int年,int月,int日)----年月日
-
new Date(int 年,int 月,int 日,int 时,int 分,int 秒)-----年月日时分秒
-
-
格式转换
SimpleDateFormate格式化日期
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd")---字符串日期格式是yyyy-MM-dd
sdf.format(Date日期对象)----将Date转为字符串输出
sdf.parse(String)----将日期格式的字符串转为Date毫秒时间:从1970年1月1日 0时0分0秒开始计时;
异常
-
Error 错误
-
Exception 异常
Object Throwable Exception RuntimeException运行时异常:发生在程序运行过程中,可处理也可不处理; 编译异常:发生在文件编译时,必须处理,否则编译无法成功;
-
异常处理方式:
1.try--catch:在程序中就地处理
try{
//可能出现异常的部分
//后续的代码可能无法执行
}catch(捕获的异常){
//出异常时执行的部分
}
2.throws:向上抛出异常,抛给调用者......JVM
//定义方法
public void test() throws 异常{
}
//调用方法
test()----try-catch/throws
例:
public class A{
public void testA() throws Exception{
}
}
public class B{
public void testB()throws Exception{
new A().testA();
}
}
public class C{
public void testC(){
try{
new A().testA();
}catch(Exception e){
e.printStackTrace();//打印异常轨迹
}
}
}
public class Test1{
public void test(){
new B().testB();//必须在此处理异常:throws/try-catch
new C().testC();//此时不需要处理异常;因为C内已将异常处理过;
}
}
properties.load()
-
异常发生
手动抛出:throw new 异常名()
逻辑代码里出现
调用方法时,异常传递;
-
自定义异常
定义:
class 异常子类 extends 异常父类{
public 异常子类(){
super();//默认无参构造
}
public 异常子类(String message){
super(message);//message传递的异常原因
}
}
线程
程序:静态的代码块
进程:运行的程序;在进程中至少包含一个线程
线程:包含在进程中的最小单位;抢占式执行;独立运行方法; 组成:cpu时间片、运行数据、逻辑代码;
创建线程1:
继承Thread类,创建线程类/重写run方法/创建线程对象/调用start()方法启动线程;
父类 Thread
new Thread(){
public void run(){
//线程任务
}
}.start();
class Thread1 extends Thread{
public void run(){
//线程执行的任务
}
}
测试:t1和t2之间是抢占式执行
Thread1 t1=new Thread1();
t1.start()
Thread1 t2=new Thread1();
t2.start()
创建线程2:
实现Runable接口/重写run方法/创建对象/创建Thread对象/借用thread对象调用start()方法启动线程;
class T3 implements Runable(){
public void run(){
//线程任务
}
}
测试:
T3 t=new T3();
Thread thread=new Thread(t);
thread.start();//启动线程
线程的生命周期:
-
创建状态:新建一个线程类
-
就绪状态:启动线程后,所有线程在处理就绪队列
-
运行状态:获得CPU时间片,线程就将处理运行状态
-
阻塞状态:运行中的线程,出现某个阻塞的原因,直到阻塞原因消失,线程又回到就绪状态;
-
死亡状态:线程任务结束或被人为终止线程
同步安全:
多个线程在交替执行时可能因为争抢同一个临界而需要代码同步;
多个线程在交替执行是作为整体的部分不被打断;
实现线程安全:
synchronized关键字
使用同步锁:引用类型/类.class
synchronized(同步锁){
//同步代码块
}
Lock锁
和synchronized(锁对象)一样,具有互斥标识;
创建锁:Lock lock=new ReentrantLock();
创建一个监听线程的对象:Condition c=lock.newCondition();
定义同步代码块:具有原子性
lock.lock();
lock.unlock();
让出同步锁:c.await();
唤醒因await阻塞的线程:c.signal()/c.signalAll()
线程常用方法:
-
sleep(毫秒数)休眠时间
-
getName() 获得线程名字
线程的同步通信:
共享数据:临界资源
生产线程:向临界资源中存放数据
消费线程:从临界资源中取出数据
实现原理:通过同步锁的互斥标识控制生产线或消费线程
wait/notity
wait():让出同步互斥标识
notity():唤醒同一互斥标识的wait线程
-
死锁
两个线程都持有对方所需要的锁,同时又等待对方的锁,
class Boy extends Thread{
public void run(){
synchronized(锁A){
。。。。代码
//sleep
synchronized(锁B){
。。。代码
}
}
}
}
class Girl extends Thread{
public void run(){
synchronized(锁B){
。。。。代码
//sleep
synchronized(锁A){
。。。代码
}
}
}
}
-
线程池
减少线程的创建和关闭的耗时,创建线程池,调用线程池中的线程,用完后归还
创建线程池:
ExecutorService es=Executors.工厂类的方法
调用线程的任务:
es.submit(Runnable/Callable)
关闭线程池:
es.shutdown();
Callable接口
泛型接口,与Runnable相似;
new Callable<泛型>(){
public 泛型 call(){
//任务
return 返回值;
}
}
Future接口
实现类:FutureTask implements RunnableFuture{} //实现了Runnable和Future 接收Callable参数: FutureTask<泛型> task=new FutureTask(Callable类型参数); 接收任务返回值: task.get();
io流
流:数据传输的通道;
分类:
按方向:
输入流:从存储设备到程序
输出流:从程序到存储设备
按单位
字节流:一次读写操作一个字节,万能流
字符流:一次读写操作一个字符,限制读写文本,一个字符=两个字节,一个汉字是一个字符
按功能分:
节点流:具有起点和终点方向
过滤流(增强流):对节点流进行功能的增强
File类
表示物理路径下的文件或文件夹;
文件:有后缀、后缀就是文件类型
文件夹:又叫目录;
创建对象: File file = new File("文件地址")
file变量表示磁盘上的一个文件或文件夹
对文件执行io流操作;
对文件夹可以遍历;在文件夹里还可以创建文件/文件夹
常用方法:
file.isFile(); 表示是不是一个文件
createNewFile()创建一个新文件
mkdir()/mkdirs()创建一个新目录
delete()删除文件或空目录。
exists()判断File对象所对象所代表的对象是否存在。
getAbsolutePath()获取文件的绝对路径。
getName()取得名字。
getParent()获取文件/目录所在的目录。
isDirectory()是否是目录。
isFile()是否是文件。
length()获得文件的长度。
listFiles()列出目录中的所有内容。
文件夹
文件
renameTo()修改文件名为。
renameTo(File)
File f1=new FIle("d:/1.txt");
f1.renameTo(new File("d:/2.txt"));
io
-
字节流:
字节输入输出节点流:字节输入输出节点流:InputStream/OutputStream
输入流 InputStream
输出流 OutputStream
文件字节输入输出节点流:FileInputStream/FileOutputStream
输入流 FileInputStream
输出流 FileOutputStream
读入方法:
从文件到程序,一次读一个字节:read();如果达到文件末,则返回-1;否则,返回ASCII值;一次读一个数组:read(byte[]b),返回实际读到的字节数;如果返回-1表示读到文件末尾;
写出方法:
从程序到文件,一次写出一个字节:write();
关闭流:
close();
缓冲输入/输出字节过滤流:增加了缓冲区,提高了IO执行效率;
BufferedInputStream/BufferedOutputStream
注:没有增加其他的方法,只多了缓冲区;
在程序和文件之间增区的用于保存数据的区域;
如果是输出流,程序向文件中写出的内容,因为保存在缓冲区,需要及时清空缓冲区;
清空缓冲区的方式:
缓冲区满自动清空,缓冲区默认大小8192字节(8k);1k=1024b
关闭流时,调用close方法;
强制清空,调用fiush方法;
对象输入/输出字节过滤流:增加了缓冲区,还可以对八种基本类型及字符串、对象进行读写操作;
先写出操作:ObjectOutputStream
Write基本类型();
writeUTF(字符串);
writeObject(Object)
在读入操作:ObjectInputStream
read基本类型();
readUTF();返回String
readObject();返回Object
注:对对象写出,叫序列化;
从文件中读一个对象,叫反序列化;
对读写操作的对象要求实现序列化接口Serializable,不需要重写方法,只是作为序列化和反序列化版本比较的标识(比的是serialUID)
打印输出流:
PrintStream(OutputStream/File/String)
字符流
抽象父类:Reader/Writer
读:
read()
read(char[])
写:
write(int)
write(String)
write(char[])
字符输入/输出节点流:
FileReader/FileWrite
字符输入/输出缓冲流:
BufferedReader/BufferedWrite
提供了缓冲区,提高IO读写效率;
特别:一次读一行;read()/readLine()无东西返回null
打印字符输出过滤流:
PrintWrite(Write/File/String/OutPutStream)
Print/Println向外写出一行
转换流
标准输入流:
System.in;InPuttream类型
表示从键盘录入
标准输出流
System.out,OutPutStream类型
从控制台输出
网络编程
IP:网络中的每台设备的唯一一个点分十进制表示的地址
端口号:设备中的一个端口,表示一个程序,例:mysql--3306;oracle-1521;
Socket:也叫套接字,是网络的一个通信节点;
基于TCP协议的编程,基于套接字的编程方式:
第一步:双方(客户端与服务器)建立连接:
服务器:Sever
建立服务器:SeverSocket ss = new SeverSocket(端口号);
等待客户端连接:Socket socket = ss.accept();
开始通信:基于字节节点流
客户端:Client1
连接服务器:Socket socket = new Socket(服务器ip,端口号);
开始通信:基于字节节点流
客户端:Client
客户端:Client
...
第二步:双方通信,基于字节节点流InputStream/OutputStream
socket.getInputStream();
socket.getOputStream();
群聊:
建立正常通信
持续的收发消息
在客户端与服务器端添加while(true)实现双方通信
多客户端连接
在服务端接收、发消息单独定义为一个线程;
在客户端连接到服务器后,accept方法后,将所有的通信节点Socket收集起来(收集到List中);
启动每个线程;
实现群聊
在客户端收消息时定义在线程类中;
只要客户端与服务器端之间建立连接,在new Socket之后启动客户端收消息的线程;
在服务端发送消息时,需要将上一步收集到的所有Socket遍历并给每个客户端发送消息;
处理退出(线下)问题
客户端程序下线,输入“bye”,并且将当前客户的收消息线程结束掉,调用stop方法;
服务器端程序处理下线客户端,将该客户端从list集合中移除;
基于UDP协议的编程:无连接的传输层通信协议
发送方:--客户端
DatagramSocket socket = new DatagramSocket()
socket.send(数据包)
接收方:--服务器
DatagramSocket socket = newDatagramSocket(端口)
socket.receive(数据包)----阻塞式接收原理
拆包:获得发送方的相关信息
数据:getData()
内容长度:getLength()
主机:getAddress()
端口号:getPort()
数据包:
当作为空包:DatagramPacket packet = new DatagramPacket(byte[],int);
接收到数据的包并重组新包:
DatagramPacket packet = newDatapragramPacket(byte[],int,InetAddress,int端口);
反射技术
类对象:Class类型封装类(任意类)的成员信息,包括:属性、方法、构造。。。。
注:任何类的对象都是Class 每个类只有一个类对象
获得类对象
-
实例.getClass()
-
类.class
-
Class.forName("全类名");//全类名:包名+类名
获得方法:
Method m = 类对象.getMethod("方法名",Class...方法中参数的类对象);
获得所有方法:
Method[] m1 = 类对象.getDeclaredMethods();
获得一个方法:
Method m2 = 类对象.geetDeclaredMethod("方法名",Class...参数列表类对象)
反射创建实例:
Object obj=类对象.newInstance();
调用方法
m.invoke(obj,方法中的实参)
构造器
获得构造:
获得所有构造:
Constructor[] c = 类对象.getDeclaredConstructors()
获得某个构造:
Constructor c = 类对象.getDeclaredConstructor(参数的对象)
调用构造:
c.newInstance(实参的值)
获得属性
获得一个属性
getDeclaredField(属性名)
获得所有属性:
getDeclaredFields();
常用方法
| 含义 | 方法名 | 返回类型 |
|---|---|---|
| 获得修饰符 | getModifiers() | int |
| 获得方法名 | getName() | String |
| 获得返回类型 | getReturnType() | Class |
| 获得参数列表 | getParameterTypes() | Class[] |
| 获得异常 | getExceptionTypes() | Class[] |
| 获得所有构造器 | getDeclaredConstructors() | Constructor[] |
| 获得一个构造 | getDeclaredConstructor(Class...param) | Constructor |
| 调用构造器 | newInstance(Object...参数值) | Object |
| 获得所有方法 | getDeclaredMethods() | Method[] |
| 获得一个方法 | getDeclaredMethod(方法名,Class...参数的类对象) | Method |
| 调用方法 | invoke(实例,Object...实参的值) | Object |
| 获得所有属性 | getDeclaredFields() | Field[] |
| 获得一个属性 | getDeclaredField | Field |
自定义注解
元注解:注解中的注解
@Target表示注解的使用位置:可在类(TYPE)、方法(METHOD)、属性(FIELD)、构造等
@Retention注解生效的时间
class:注解记录在class文件中,运行java程序时,jvm不会保留,此为默认值
runtime:注解记录在class文件中,运行java程序时,jvm会保留,程序可以通过反射获取该注解
source:编译是直接对齐这种策略的注释
@Target(ElementType.METHOD,ElementType.TYPE,ElementType.FIELD)
@Retention(RetenttionPolicy.RUNTIME)
public @interface Mapping{
String url(); //没有默认值,必须在使用时添加值
int age=20;//默认20
}
使用:
@Mapping(url = "/user")
public 类名{
@Mapping(url = "/selectAll")
public void select(){
sout("查看所有方法")
}
@Mapping(url = "/deletetAll")
public void delete(){
sout("删除所有的方法")
}
}
测试
模拟前端:在浏览器中输入一个字符地址: user/selectAll
在后端测试:
获得一个类对象:
Class c=UserController.class;
获得类的注解内容:
Mapping m=(Mapping)c.getDeclaredAnnotation(Mapping.class);
String u1=m.url;
遍历出这个类对象中所有方法,判断每个方法中是否含有注解Mapping,以及区分注解中url的值是不是与前端的请求地址一致,如果一致,则调用该方法;
Method[] method=c.getDeclaredMethods();
for(Method m:method){
Annotation an=m.getDeclaredAnnoatation(Mapping.class);
if(an!=null){
Mapping mapping=(Mapping)an;
String u2=mapping.url;
//将前端输入的地址与当前行到的(u1+u2)相比较,比较一致时调用当前的 m;
//m.invoke();
}
}
三次握手、四次挥手
-
三次握手: 第一次:客户端向服务端发起连接 第二次:服务端接收请求并进行确认 第三次:客户端对服务端的响应进行确认
-
四次挥手: 第一次:客户端发起挥手请求 第二次:服务器端接收挥手请求 第三次:服务器发起关闭连接 第四次:客户端进入关闭连接的状态
-
通信:基于字节节点流 socket通信节点 socket.getInputStream socket.getOutputStream
UDP编程:无连接,相对通信效率高
数据报的一种通信方式:数据的携带使用的是DatagramPacket DatagarmSocket创建连接 send(packet) receive(packet) 拆包:在DatagramPacket中调用getData()获得数据相关信息,将字节数组转为字符串
网络编程实现上传 客户端: 1.读客户端本地的文件;InputStream is=new FileInputStream(本地文件) 2.将文件发到服务器端;OutputStream os=socket.getOutputStream(); 6.接收服务端发回的处理结果;InputStream is2=socket.getInputStream(); 服务器端: 3.从客户端读文件;InputStream is=socket.getInputStream(); 4.将文件保存到服务端;OutputStream os=new FileOutputStream(本地文件); 5.将上传的结果发回到客户端; OutputStream os2=socket.getOutputStream();
网络编程实现下载 客户端: 1.连接服务器; 4.从服务器读文件:InputStream is=socket.getInputStream(); 5.保存到本地:OutputStream os=new FileOutputStream(本地文件); 服务器端: 2.从本地读文件:InputStream is=new FileInputStream(本地文件) 3.向客户端发送文件;OutputStream os=socket.getOutputStream();
网络编程实现登录 客户端: 1.发送昵称和密码: OutputStream os=socket.getOutputStream(); 4.接收服务器端发的信息:InputStream is=socket.getInputStream(); 服务器端: 1.接收客户端的信息:InputStream is=socket.getInputStream(); 2.读本地的文件内容:InputStream is2=new FileInputStream() 3.将本地文件内容与接收到的信息相比较,并将比较结果发回到客户端:OutputStream os=socket.getOutputStream() 网络编程实现注册 客户端: 1.发送昵称和密码: OutputStream os=socket.getOutputStream(); 4.接收服务器端发的信息:InputStream is=socket.getInputStream(); 服务器端: 1.接收客户端的信息:InputStream is=socket.getInputStream(); 2.向本地的文件中写内容:OutputStream os=new FileOutputStream(); 3.将注册结果发回到客户端:OutputStream os=socket.getOutputStream()
枚举
固定实例,是一个终止类,内部属性值是静态常量;声明用enum关键字;同时可以出现抽象abstract方法;
枚举类的定义
enum 类名{
实例1,实例2,实例3//必须定义在第一行
}
有构造的枚举
enum 类名{
实例1(实参),实例2(实参),实例2(实参);//必须定义在第一行
类名(性参数){
}
}
调用枚举的实例、方法时,枚举的所有实例均提前创建完毕
抽象枚举类:含有抽象方法的枚举类
enum 类名{
//abstract void test();
实例1(){
//重写部分
},
实例2(){}.....//抽象枚举类的实例就是它的普通子类;此时必须重写抽象方法
}
自定义了抽象方法的枚举类会自动提升为抽象枚举类;
设计模式
一套解决特定问题的方式;长哟领的设计模式有23种;
-
工厂设计模式:用于动态创建对象
class 类名{
public static 接口/父类 方法名(参数){
//根据参数判断
return 实现类对象/子类对象;
}
}
-
模板设计模式:抽象类/抽象方法/普通方法;把变化的代码定义在抽象方法里由子类重写;普通方法实现对抽象方法的调用;
abstract class 类Template{
abstract void test1();
abstract void test2();
public void normal(){
//固定代码
test1();
//固定代码
test2();
//固定代码
}
}
子类 extends Template{
//重写test1
//重写test2
}
子类2 extends Template{
//重写test1
//重写test2
}
测试:Template t1=new 子类();
Template t2=new 子类2();
t1.normal();
t2.normal();
-
单例模式:只允许创建一个该类的对象。
私有构造器:在类外不允许被访问private
公有静态获得对象的方法:
私有静态属性:保证对象必须是唯一的
//懒汉式
class SingleTon1 {
//私有构造
private SingleTon1() {
}
private static SingleTon1 s;//私有静态---只属性类
//公有静态获得对象
public static SingleTon1 getInstance() {
if (s == null) {
s = new SingleTon1();
}
return s;
}
}
//饿汉式
class SingleTon2 {
//私有构造
private SingleTon2() {
}
private static SingleTon1 s= new SingleTon1();//私有静态---只属性类
//公有静态获得对象
public static SingleTon1 getInstance() {
return s;
}
}
JDK8特性
Lambda表达式:对匿名内部类格式的简化
lambda
语法:
(参数)->{//方法体}
函数式接口:接口中的方法只能定义一个抽象方法;
void test();---无参无返回值的方法;----
接口类型 变量 =()->{ sout("无参无返回值的方法")};
void test2(int x,int y);---有参无返回值的方法---
接口类型 变量 = (m,n)->{sout(m+n)}
int test3();---无参有返回值--------
接口类型 变量 = ()->值;
int test4(int x, int y)---有参有返回值----
接口类型 变量 = ()->x+y;
接口类型 变量 = ()->{return x+y;};
Straeam流
Stream中保存对集合或数组的操作
使用步骤:
创建流:
-通过Collention对象的stream()或parallelStream()方法
-通过Arrays类的stream()方法。
-通过Stream接口的of()、itearte()、generate()方法。
-通过InStream、longStream、DoubleStream接口中的of、range、rangeClosed方法。
中间操作:
-filter、limit、skip、distinct、sorted
-map
-parallel
终止操作:
-forEach、min、max、count
-reduce、collect
案例:
创建流:
Stream<Integer> stream = Stream.of(10,20,33,55,100)
//中间操作:filter
//终止操作:forEach
stream.filter(x->x%2==0).forEach(System.out::println);
日期类型
-
java.util.Date
常用于声明属性:
private Date birth;
-
java.sql.Date
在jdbc中支持的数据类型:
java.util.Date与java.sql.Date之间的转换;
new java.sql.Date(new java.util.Date().getTime());
-
java.tetx.SimpleDateFormat(格式化日期)
将java.util.Date的日期与字符串之间的转换:
parse
format
-
java.util.Calender日历类
实例化:Calendar c = Calendar.getInstance();
调用实例方法:
c.set(int year,int month,int date);
c.get(字段名);---c.get(Calendar.YEAR)获得某个字段的值
调用字段:
Calender.YEAR
Calendar.Day_OF_MONTH
-
LocalDateTime jdk8的日期类
创建时间:
LocalDateTime localDateTime = LocalDateTime.now()
LocalDateTime localDateTime2 = LocalDateTime.of(year,month,dayOfMonth,hour,minute)
-
DateTimeFormatter jdk8格式化日期类
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
format:通过这个方法转为字符串表示;
LocalDateTime.parse("2020-02-10 10:20:35",dtf);通过这个方法将字符串转换为LocalDateTime

浙公网安备 33010602011771号