Java基础

Java

java基础

java是一门跨平台的语言:一次编写,处处运行

java能够跨平台的原因,是因为有各种类型的jvm,且各个jvm不跨平台

java开发:写代码(java)——>编译(class)——>执行(class)

jvm:java虚拟机

jre:jvm+核心类库:只能运行java程序,但不能开发(写代码)

jdk: jre+运行环境工具:既能运行,也能开发

jvm<jre<jdk

安装jdk

配置环境变量

  • path(必须):安装jdk的根目录\bin
  • classpath:安装jdk的根目录\lib
  • java_home:安装jdk的根目录

验证:cmd(win+r) ,输入java -version

程序详解

class 后面的是类名

每个java文件可以有多个类class ,但只能有一个public class(公共类)

转义符 \

\n 换行

\t 制表符 (Tab)补满一定位数

编码问题

java默认编码集是unicode

注释

单行 //

多行 /* */

文档注释 /** */

Eclipse

提示/自动补全: Alt+/

Idea

自动补全 : Tab

​ main方法: psvm+Tab

​ 输出:sout+Tab

提示: Alt+回车

Ctrl+P:查看方法参数

变量

变量存在于内存中(程序结束,计算机关机后,变量失效)

变量:1.声明数据类型(整数,小数,字符串…) 2.赋值 3.使用

变量名不能重复

变量名区分大小写

局部变量使用之前必须赋初值

变量的有效范围:最近的一对{}

java数据类型

原生数据类型(基本数据类型)8个

数字

​ 整数byte<short<int<long 默认int

​ 小数float<double 默认double

非数字

​ 字符char 只能放一个字符,并且需要用单引号引起来

​ 布尔boolean :只有true/false

整数<小数<字符串

引用数据类型(对象类型)

String 字符串

变量应用

java可以直接表示的进制

二进制 :0b数字

十进制

八进制:0数字

十六进制:0x数字

从控制台输入Scanner

Scanner 中有很多类型的输入方法,但没有输入字符char的方法

Scanner input = new Scanner(System.in);
int num = input.nextInt();
System.out.println(num);

输入字符串的方法:String name = input.next();//输入字符串

​ String name = input.nextLine();//输入字符串

nextLine()与next()的区别:

​ next():不接收空格,回车,并将空格,回车作为终止符

​ nextLine():接收空格,回车

数据类型的转换

自动转换

范围小的类型可以自动转化为范围大的类型

范围小的类型遇到范围大的类型,自动转换为范围大的类型

整数<小数<字符串,任何类型遇到字符串,自动转换为字符串

char<int

强制转换

范围大的赋值给范围小的,必须强转

通用写法: int num = (int)1.2; 范围小的 = (小类型)范围大的

特殊写法:float f = 123.4f;

算术运算符

+加号 /连接

—减号

*乘法

/除法

%求余,结果永远与被除数一致

关系运算符(比较运算符)

大于>

小于<

大于等于 >=

小于等于 <=

等于 ==

不等于 !=

字符串比较 equals() !equals()

运算结果全是布尔值

位运算

效率最高

逻辑运算符

非,不等于 !

且 &&

或 ||

i++ 先用后加

++i 先加后用

三目运算符

布尔判断?a:b

如果true返回a,如果false返回b

小数运算可能遇到的问题

System.out.println(3*0.3);//的结果是0.8999999999999999

int的范围能够容纳下2的32次方个数字,float/double是小数,无穷无尽个数字,因此2的32 个位置无法容纳所有小数

选择结构

if

if(布尔条件){

​ …//如果条件为真则执行

}

if后面如果只有一条语句,则{}可以省略,如果有多条语句,则不可以省

if…else…

java语言的if(表达式),表达式必须是boolean类型

if(布尔条件){

​ …//如果条件为真则执行

}else{

​ …//如果条件为假则执行

}

简单的if…else…赋值语句可以等价为三目运算符

多重if:多重选择

if(布尔条件){

​ …

}else if(布尔条件){

​ …

} else{

​ …

}

嵌套if

if(){

​ if(){

​ }

}else{

}

如果使同一件事情用多重if,如果不是同一件事情,用嵌套if

switch选择

switch(表达式){

​ case 值:

​ …

​ break;//整个switch全部结束

​ case 值:

​ …

​ break;

​ default://都不匹配

​ …

}

switch会用表达式和所有的case匹配,如果匹配成功,则执行响应case后的语句,如果所有匹配都不成功则执行default后的语句

switch后支持的表达式类型:int ,short,byte,char,String,枚举

case后面的值必须是常量,且case值不能重复

default可以省略

switch只有遇到break或最后的}才会结束,否则都不结束

如果判断的是区间值用多重if,如果是离散值,用switch,多重if都可

随机数

Math.random();//产生[0,1)之间的随机数

产生n位随机整数:(int)(Math.random()*n位数最大值+1-n位数的最小值)+n位数的最小值;

循环

重复执行的事情

循环 = 循环条件 + 循环操作

while循环

先判断在执行

while(循环条件){

​ 循环操作;

}

循环要注意更新变量,防止死循环(无限循环)

do…while

先执行后判断

do{

​ 循环操作;

}while(循环条件);

do…while至少执行一次

for循环

while的变形

for(初始值;循环条件;更新变量){

​ 循环操作

}

适合循环次数已知,或者始末条件已知

break退出循环

退出循环,终止循环

仅仅对当前层次的循环有效

continue跳过当前循环

跳过当前循环

仅仅对当前层次的循环有效

二重循环

循环里边套循环

while(){

​ while(){

​ }

}

外层循环执行一次,内层循环执行一轮

foreach

for(元素类型 变量名:数组){

​ …

}

数组

定义整数数组: int[] students = new int[300];

​ 数据类型[] 数组名 = new 数据类型[数组长度];

数组的使用: 数组名[下标]——>数组元素

数组四要素: 数组名,下标,类型,数组元素

什么时候使用数组?: 当多个元素类型一致时,考虑用数组

数组定义有三种形式

​ int[] students = new int[3];只声明数组的元素个数,但不赋值(默认值)

​ int[] students2 = new int[]{1,2,3};只赋值,但不声明元素个数

​ int[] students3 = {1,2,3};理解为只赋值的简化形式,不能拆开写

数组长度: students.length

数组的最后一个元素下标 : students.length-1

对数组进行升序排序: Arrays.sort(numbers);

冒泡排序

总结:几轮? 元素个数-1

​ 使用双重循环,外层几轮,内层两两元素比较

int[] numbers = new int[]{8,5,2,1,23,344,12};
for (int i=0;i<numbers.length-1;i++){for (int j=0;j<numbers.length-1-i;j++){if(numbers[j]>numbers[j+1]){int temp = numbers[j];numbers[j]= numbers[j+1];numbers[j+1] = temp;}}
}
for(int i=0;i<numbers.length;i++){System.out.print(numbers[i]+"\t");
}

二维数组

String[][] citys = {{…},{…},{…}} ;

类和对象

面向过程:将每一个过程全部写明白

面向对象:只需要写事情的目标即可

在面向对象编程中,将具体的成为对象(张三),将抽象的成为类(人)

多个对象可以抽象出类,类可以产生多个对象

类和对象的组成部分:

​ 静态:属性(名值对——属性名,属性值)——身高,体重

​ 动态(功能):方法——吃饭,睡觉

类可以细分,但细分的产物并不一定是对象。例如,人可以分为男人,女人

类:由一组抽象的属性,方法构成;对象:由一组特定的属性,方法构成。

Person zs = new Person();一般而言,栈里边的zs是引用,对象是指堆中的东西

栈里边存放基本类型,引用类型,方法,堆里边放的是实例对象

引用:相当于C语言中的指针,持有对象的内存地址

对象之间的直接赋值,赋值的是内存地址

语法:

​ 创建类:public class Person(){

​ …}

​ 对象使用前必须实例化(new)

​ 创建类的对象: 类 对象 = new 类();

​ 调用类中的属性和方法: 对象.属性 对象.方法

方法是多个对象共享的,属性是各个对象独有的

属性就是全局变量。全局变量:方法以外,类以内(有初始值,数据类型的默认值)

​ 局部变量:方法以内(没有初始值,在使用前必须赋初始值)

局部变量可以和全局变量重名,并且局部变量优先级高

方法调用的常见情况:

​ 同一个类中

​ 都有static,都没static或者没的调有的,则可以直接调用

​ 有static的不能直接调没static的方法

​ 不在同一个类中

​ 万能方法: 先new 对象 然后 对象.方法

​ 如果调用的方法是static静态的方法,可以直接类名.方法

//静态方法
public static void play(){}
//非静态方法
public void play(){}

static方法是类级别的,属于类

非static方法是对象级别的,属于对象

类有的,对象自然有;对象有的,类不一定有

方法:

  • 有返回值

public 返回值类型 方法名(){

​ return 类型对应的数据;

}

在调用有返回值的方法时,需要接收

  • 无返回值(返回值位void)

  • 有参数

    个性

    参数越多越个性化

    public void sleep(参数列表){}
    //参数列表必须满足:类型,个数,顺序完全一致
    public void sleep(String name){}public void sleep(String name,String place){}
    //多个元素类型相同--数组public void sleep(String[] names){}
    //多个元素类型不同--类/对象public void sleep(People people){}
    
  • 无参数

    共性

对象数组

类型[] 数组名 = new 类型[];

缺点

​ 数组长度固定,不可改变

​ 数组无法求出真实有效数据的个数

​ 用数组实现对象的增删改查操作比较麻烦

字符串

定义字符串方式

String a = “abc”;

String a1 = new String(“abc”);

String a2 = new String();//默认生成的使""

通用的理论:对于非基本类型(对象类型/引用类型)

​ 1.只定义,不new,默认都是null

​ 2.new实例化,就是“空”(数据类型的默认值)

==判断内存地址

任何类型遇到字符串,转为字符串

String是final类型的,一旦定义不可改变,如果在方法中对其修改,只是在堆中新开辟了一个空间,存放新值

常见的String方法

//判断两个字符串内容是否相等,返回值是boolean值,区分大小写,==判断内存地址
boolean result = a.equals("abc");//判断两个字符串内容是否相等,返回值是boolean值,不区分大小写
boolean result = a.equalsIgnoreCase("ABC");//字符串的长度,返回值是int类型
int length = a.length();//将小写转化成大写,返回值是String类型
String b = a.toUpperCase();//将大写转化成小写,返回值是String类型
String b = a.toLowerCase();//判断b是否存在与字符串a中,如果存在,返回值是b所在的位数,如果不存在,返回-1
int c = a.indexOf("b");//倒着查找
int b1 = a.lastIndexOf("c");//去掉首尾的空格,返回值是String类型
String trim = a.trim();//截取字符串,从start截取到end,start能取到,end取不到,返回值是String类型
String a = phone.substring(start,end);//截取字符串,从start截取,返回值是String类型
String a = phone.substring(start);//字符串拆分 split(),根据-分隔开字符串,返回字符串的数组,特殊符号不适用:. | \ $ + *且拆分符如果在末尾,则末尾字符无法被统计
String[] splits = a.split("-");//万能的字符串拆分
String str = "hello|world";
StringTokenizer token = new StringTokenizer(str,"|");
while (token.hasMoreTokens()){System.out.println(token.nextToken());
}//根据位置找字符,返回值时字符类型
char c = str.charAt(2);//replace,替换
String str = str.replace("老字符", "新字符");

StringBuffer类

String的增强版,比String最大的升级,可以在原来的内存空间中直接修改变量值

StringBuffer不是final类型的

如果对字符串需要频繁的修改,则不建议使用String类,而是使用StringBuffer类

//赋初始值 
StringBuffer sb = new StringBuffer("abc");//字符串拼接,往最后拼接
sb.append("aaa");//字符串插入,往第二个位置插入bbb
sb.insert(2,"bbb");//倒序
sb.reverse();

StringBuffer与String之间各自独立,他们之间可以相互转换

//String ---> StringBuffer
String a = "abc";
StringBuffer a1 = new StringBuffer(a);//StringBuffer ---> String
String s = sb.toString();
String a2 = sb+"";//任何类型遇到字符串转为字符串

字符串常量池

使用字符串时,现在常量池中寻找,如果有,则使用,如果没有,则创建后放入常量池,并使用

new就是在堆中开辟空间,产生对象

字符串,如果直接使用字面量String str = “abc”;则从常量池中找,如果使用的时new,则从堆中找(而堆又会从常量池中查找,如果常量池没有,则在常量池中创建,并使用,就是引用常量池中的内存地址)

如果new之后,仍想从常量池中获取,则需要使用intern()方法

包package

作用和文件夹/目录的作用一摸一样

1.将类等资源进行结构化存储

2.防止重名问题

打包:package MyPackage; 如果多个类在同一个包中,通过package打包

导包:import com.Person; 如果多个类不在同一个包中,并且需要相互调用,就需要导包

访问修饰符

一般建议对属性/方法添加访问修饰符

private 私有的,只有当前类能够访问;其他类不能直接访问,如果要访问,需要借助于访问器:setter ,getter private和set,get方法配套使用

//this  代表当前类的属性
this.name = name;

public :全部可以访问

一般属性全是private ,方法全是public

继承重载重写与this和super

继承extends

多个类(子类)有多个相同的属性和方法,可以相同的属性和方法提出来放在一个单独的类里(父类)

作用:减少代码冗余

注意:如果一个方法,方法名相同,方法体不同,也不能提取到父类;只有完全相同的属性和方法才能提取到父类

子类继承父类中:private,构造方法无法被继承,但是子类可以显示的调用父类的构造方法(super)

重写

子类重写父类的方法

父类中已经存在a()方法,子类中又重新写了一个a()方法

super直接去父类中寻找方法,跳过子类

this在当然类中查找,如果当前类没有,去父类中查找

方法名一致,参数列表相同

方法重载

方法名一致,参数列表不一致(类型不同,个数不同,顺序不同)

注意两点:1.与返回值无关 2.与参数名无关

构造方法

//无参构造方法
public 类名(){
}dog d= new dog();

作用:实例化(new),产生一个对象

​ 含参构造的作用:一次性可以赋多个属性值

默认是无参构造方法dog()

如果类中没有任何构造方法,则系统自动提供一个无参构造方法;如果类中有构造方法,则系统不会提供无参构造方法

建议:如果给类中编写构造方法,则手动编写一个无参构造方法,防止报错

构造方法调用构造方法要用this(…),且this只能放第一行,多个构造方法之间不能循环调用;如果构造方法调用普通方法,可以直接调用

如果子类要调用父类的构造方法要用super(…),且super只能放第一行

this调本类构造,super调父类构造,this/super只能放在第一行

构造方法不能被重写

初始化顺序

new(Xxx)之前干了什么事情:

父类static

子类static

父类普通代码块

父类无参

子类普通代码块

子类无参

抽象类abstract

抽象方法:abstract,没有方法体

抽象方法必须包含在抽象类中

抽象类不能实例化(new),原因:抽象类中可能存在抽象方法,而抽象方法没有方法体

子类必须重写父类中的抽象方法

final

final修饰的类不能被继承

final修饰的方法不能被重写

final修饰的变量,属性不能被修改

多态

父类引用指向子类对象

//多态,小范围赋值给大范围,父类对象引用子类对象
Pet pet = new dog();
//父类 名字 = new 子类();

步骤:1.编写父类,2.编写子类,并且子类重写父类的方法,3.运行时,父类引用指向子类对象

多态的几种实现方法:

​ 1.方法重载

​ 2.方法重写

​ 3.使用父类作为方法的形参

​ 4.使用父类作为方法的返回值

多态时:父类和子类之间的转换

​ 1.从小到大,自动转换(double = int)

​ Pet dog = new Dog();

​ 2.从大到小,强制转换(int = (int)double)

​ Dog dog = (Dog)(new Pet());

对象 instanceof 类型 :判断对象是什么类型,返回值是true或者false

接口

class 普通类 底层员工

abstract class 抽象类 中层

interface 接口 高层

接口里边的方法全部是抽象方法

public interface Person{//属性全部都是static final类型//全部都是抽象方法,默认全部都是public abstractpublic abstract void eat();
}

抽象方法相当于一种约定,能力 : 门(类)有锁(接口)的能力

接口和抽象类一样不能实例化(new)

实现类必须实现接口中的所有抽象方法

如果既有继承又有接口,必须先继承后实现接口

!!!!!!java类中单继承,但可以实现多个接口

接口注意事项:接口之间可以相互继承,多继承

​ 接口也可以实现多态

​ 接口中不存在构造方法

java值传递

java只有值传递

如果将a()方法中的基本类型变量x传入到b()方法中,并且在b()方法中对x进行了修改,则a()方法中的x变量值保持不变

如果将a()方法中的引用类型变量x传入到b()方法中,并且在b()方法中对x进行了修改,则a()方法中的x变量值与b()方法中保持一致

JDK8

lambda表达式

简化代码

lambda ( λ)的组成结构:

  • 逗号隔开的参数列表(x,x,x) ()
  • 箭头符号 ->
  • 方法体( λ代码块)

lambda语法上要求重写的接口,抽象类中有且只能有一个抽象方法

lambda重写的接口,抽象类中会标识一个@FunctionalInterface,称之为函数式接口。

函数式接口:标注@FunctionalInterface,语法上要求有且只有一个抽象方法

lambda表达式重写的必须是函数式接口(或者只有一个抽象方法的抽象类)

函数式接口要注意以下几点

  • 即使没有标注@FunctionalInterface,但是只有一个抽象方法,也称为函数式接口
  • 特殊情况,如果某个接口中有多个抽象方法,但只有一个抽象方法是本接口新定义的,其他方法与Object中已有的抽象方法重复,那么该接口仍然是函数式接口

函数式接口从哪来?

  • JDK自带(很多存在与java,util.function包中)

    四大核心函数式接口

    • 有参,无返回值(消费型)
    • 有参,有返回值(函数型)
    • 无参,有返回值(供给型)
    • 断言式接口(返回值是boolean)
  • 自定义

lambda表达式的使用方式

方式一

函数式接口 引用名 = lambda表达式;

//抽象方法
int add(int num1,int num2);
//实现
public static void tets(){//lambda自带类型推断机制,因此参数的类型可以省略MyInterface mi = (n1,n2)->{return n1+n2;};System.out.println(mi.add(5,6));
}
方式二

将lambda表达式所代表的函数式接口,作为一个方法的参数存在

方法A(方法B):函数式编程。scala,javascript本身就支持函数式编程

public static void test2(){System.out.println(upper((x)->x.toUpperCase(),"hello"));
}public static String upper(Function<String,String> fun ,String str){return fun.apply(str);
}

JDK8的其他特性

接口的m默认方法与静态方法
方法引用
重复注解
其他

集合框架

对象数组的缺点

​ 数组长度固定,不可改变

​ 数组无法求出真实有效数据的个数

​ 用数组实现对象的增删改查操作比较麻烦

因此提出集合

1.Collection的长度自动适应,不必人工干预

2.size(); 返回集合中真实数据的个数,int

3.用数组实现对象的增删改查很方便

集合 Collection是一个接口,一些 Collection允许由重复的元素,而另一些不允许,一些 Collection是有序的(输入顺序和输出顺序一致),而另一些是无序的

Collection:存储的数据是不唯一,无序的对象

List:存储的数据是不唯一,有序(输入顺序是否与输出顺序一致)的对象

Set:存储的数据是唯一(不能重复),无序的对象

Collection最常见的方法

add(Object e)像集合中增加一个元素

clear() 清空集合中的所有元素

size() 返回集合中真实数据的个数,返回类型为int

addAll(Collection c) 可以将一个集合中的全部元素,增加到另一个集合中

contains(Object e) 判断集合中是否包含指定元素,返回类型为boolean类型

containsAll(Collection c) 判断此集合中是否包含指定集合中的所有元素,返回类型为boolean类型

equals(Object e) 判断集合与指定对象是否相等 ,返回类型为boolean类型

isEmpty() 判断集合是否为空 ,返回类型为boolean类型,如果为空返回true,非空返回false

iterator()迭代器 ,迭代当前集合的每一个元素,返回值为迭代器类型

 Iterator iterator = coll1.iterator();
//iterator.hasNext(); 判断集合是否有下一个元素
while (iterator.hasNext()){Object  result = iterator.next();//取出下一个元素System.out.println(result);
}

remove(Object e) 从当前集合中删除指定的对象,如果存在的话

removeAll(Collection c) 从当前集合中删除指定集合中的所有元素

retainAll(Collection c) 与removeAll是相反操作,从当前集合中,只保留另一个集合中的元素

toArray() 将集合转换为数组,返回类型为Object[]

List常见方法

List是有序的

List有Collection中的所有方法,另外List有自己新增的方法

重载的 add(int index,Object element) 向集合中指定位置插入元素

重载的 addAll(int index,Collection c) 可以将一个集合中的全部元素,增加到另一个集合中的指定位置

get(int index) 返回列表中指定位置的元素,类似于数组的下标

indexOf(Object o) 返回集合中第一次出现指定元素的位置,如果此集合中不包含该元素,返回-1

lastIndexOf(Object o) 返回集合中最后一次出现指定元素的位置,如果此集合中不包含该元素,返回-1

remove(int index) 从当前集合中删除指定位置的对象,如果存在的话

set(int index,Object element) 用指定元素替换集合中指定位置的元素

subList(int index,int index) 截取集合 [) 左闭右开

ArrayList与LinkedList的区别

ArrayList是动态数组,数组长度“可变”,元素与元素之间是相邻的,查询比较方便,增删改比较麻烦

LinkedList(相当于链表) 增删改比较方便,查询比较麻烦

Map

Collection与Map之间相互独立

Collection:单值集合

Map:双值集合,“键值对”(key-value)集合,可以根据键找到值,kv之间一一对应

Map中key是唯一的,value不是唯一的

Map是无序的

Map常用的方法

put(key,value) 像map中增加对象

get(key) ,根据key获取value, 返回值为value

size(), 返回元素的个数

containsKey(key) 判断是否包含了指定的key

containsValue(value),判断是否包含了指定的value

keySet() 将Map转换为只包含key的单值集合,返回值为Set, 因为key是唯一的

values() 将Map转换为只包含value的单值集合,返回值为Collection

remove(key) 删除Map中的对象

​ 删除:Collection中的类(List,Set),删除的返回值都是boolean值

​ Map中的类,是根据Key删除的,返回值是Value

如何遍历集合?

单值集合list,set

1.循环for(普通for[只适用于有序的集合];foreach,增强for[建议])

		List list = new ArrayList();list.add("a");list.add("b");list.add("c");System.out.println(list);for (int i=0;i<list.size();i++){System.out.println(list.get(i));}//无序Set set = new HashSet();set.add("dd");set.add("ee");set.add("ff");for (Object a:set){System.out.println(a);}

2.迭代器

//迭代器
public interface Iterator<E>{...}boolean hasNext();//1.判断是否有下一个元素,true/false//2.如果又下一个元素,引用后移next();//取出当前元素//使用
Iterator iterator = set.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
多值集合Map

将双值集合砖和单值集合

HashMap map = new HashMap();
map.put("s01","zs");
map.put("s02","ls");
map.put("s03","ww");
Set set = map.keySet();
Collection values = map.values();
for(Object o:set){Object o1 = map.get(o);System.out.println(o+"\tvalue\t"+o1);
}

通过entry遍历

entry = key+value,一个entry就是一个键值对(kv对)

HashMap map = new HashMap();
map.put("s01","zs");
map.put("s02","ls");
map.put("s03","ww");
Set set = map.entrySet();
for (Object o:set){Map.Entry e1 = (Map.Entry)o;Object key = e1.getKey();Object value = e1.getValue();System.out.println("k:"+key+"\tvalue:"+value);
}

泛型

Collection ,Map接口中都可以使用

自JDK1.5开始提供

作用:

(1)数据安全

(2)防止类型转换时出错

list.add默认是Object类型,如果加了泛型,则自动变成list.add(泛型的类型),返回值类似,直接返回泛型类型

泛型只能是引用类型,不能是基本类型

例如

List<Double> list = new ArrayList<Double>();
list.add(2.4);
Double aDouble = list.get(0);

集合工具类

集合工具类Collections

//按字典顺序排序
Collections.sort(list);
System.out.println(list);//取最大值,最小值
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));

数组工具类Arrays

比较器

Collections.sort() 只能够识别一些自然顺序

自定义比较器:Comparable , Comparator

Comparable:内部比较器(侵入性,需要修改原有代码)

​ 在比较对象中实现Comparable接口,重写里边的compareTo()方法,在compareTo()方法中编写比较的逻辑,重点是返回值 -1,0,1

Comparator:外部比较器(无侵入性,不影响原有代码)

​ 定义外部比较器,实现Comparator接口,重写里边的compare()方法,在compare()方法中编写比较的逻辑,重点是返回值 -1,0,1

包装类

自动装箱:基本类型—>包装类型

自动拆箱:包装类型—>基本类型

java中将8个基本类型,包装成8个对象类型(引用类型)。这8个对象类型,就称为包装类

异常

try{

​ 一切正常,执行的代码

}catch(Exception e){

​ 如果不正常,执行这里

}

如果代码出现问题时,使用“异常机制”比“选择结构”更加方便

异常的继承结构图

运行时异常:代码在编辑(编译阶段)时不报错,运行时才报错。语法上,可以选择性处理

检查异常:代码在编辑(编译阶段)时报错,在编辑时,必须处理

异常重点

try catch finally throws throw

处理异常 try catch 或者 throws

try catch

自己(当前方法)能够处理,使用try catch

try:将可能发生异常的代码用 {} 包裹起来

catch: 捕获特定类型的异常

如果try中的代码发生了异常,则程序不在执行try中异常之后的代码,而是直接跳到catch中的代码

throws

自己(当前方法)不能处理,上交给方法调用处处理,使用throws

finally

无论正常还是异常都会执行的代码

1.即使遇到return,也仍然会执行finally

2.除非虚拟机关闭,才不会执行finally

多个catch块

try{

}catch(){

}catch(){

}

先写范围小的类型,再写范围大的类型

throw

一般和自定义异常一起使用

jdk中自带了很多类型的异常,但如果这些内置异常仍不能满足项目的需求,那么就需要创建自定义异常

如何编写自定义异常

1.类继承子Exception,调用super(“异常信息”)

2.使用throw声明一个自定义异常,并进行try catch或throws

java注解

类:要给一个类增强一些功能,可以继承,实现一个接口,还可以使用注解

可以通过使用注解增强类,方法,属性的功能

内置注解

@Override:可以确保 重写的方法 的确存在于父类或接口中,可以有效的避免单词拼错

自定义注解

元注解

元数据:修饰数据的数据

元注解:修饰注解的注解

@Target : 限制注解能够使用在哪些元素上(属性,方法,类)

@Retention : 限制注解的生命周期

@Document

@Inherited

自定义注解什么时候使用? 一般结合反射使用,注解+反射一般在开发框架时使用

IO

I:InputStream 输入流

O:OutputStream 输出流

文件:硬盘上的文件 txt docx 电影,图片

通过IO操作文件

java.io.*

//file  可以代表一个不存在的文件File file = new File("F:\\前端 works\\html\\abc.txt");System.out.println("相对路径:"+file.getPath());System.out.println("绝对路径:"+file.getAbsolutePath());System.out.println("文件名:"+file.getName());//        boolean flag = file.exists();
//            try {
//                if (!flag){
//                    file.createNewFile();
//                System.out.println("创建成功");}
//                else {
//                    file.delete();
//                    System.out.println("删除成功");
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }

流是一种FIFO的数据结构 ,先入先出

分类

​ 按流向(以内存为参照点)分类:

​ 输入流 : java.io.InputStream 抽象类 /Reader

​ 输出流 : java.io.OutputStream 抽象类 /Writer

​ 按照处理单元

​ 字节流: FileInputStream FileOutputStream ;字节流就是将文件内容转为了字节形式进行传输,1字节—>8bit(二进制),二进制可以传输任何类型的数据,因此字节流也可以传输任何类型的数据,字节流缓冲区使用的是byte[]

​ 字符流: Reader Writer ;只用于处理字符,字符流缓冲区使用的是char[]

​ 其他流

字节输入流
InputStream in = null;try {in = new FileInputStream("F:\\前端 works\\html\\abc.txt");byte[] buf = new byte[in.available()];//在内存中定义字节数组in.read(buf);  //将文件中的内容存在字节数组中//将buf转成StringSystem.out.println(new String(buf));} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {in.close();} catch (IOException e) {e.printStackTrace();}}
字节输出流
OutputStream out = null;try {out = new FileOutputStream("F:\\前端 works\\html\\def.txt");out.write("Hello Word".getBytes());} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {out.close();} catch (IOException e) {e.printStackTrace();}}
字节流文件复制
//文件复制InputStream in = null;OutputStream out = null;//abc.txt  ->  内存   ->  xyz.txttry {in = new FileInputStream("F:\\前端 works\\html\\abc.txt");out = new FileOutputStream("F:\\前端 works\\html\\xyz.txt");//一次开辟10字节内存byte[] buf = new byte[10];int len = -1;while ((len=in.read(buf))!=-1){out.write(buf,0,len);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {if(out!=null)   out.close();} catch (IOException e) {if(in!=null)   e.printStackTrace();}try {in.close();} catch (IOException e) {e.printStackTrace();}}
字符流文件复制
 		Reader re = null;Writer wr = null;//文件到内存try {re = new FileReader("F:\\前端 works\\html\\abc.txt");char[] buf = new char[4];int len = -1;StringBuffer sb = new StringBuffer();while ((len = re.read(buf))!=-1){sb.append(buf,0,len);//将每次读取到的数据存储到sb中}
//            System.out.println(sb);//在内存中替换占位符String a = sb.toString();a = a.replace("name","韩延丰");a = a.replace("address","济南");//将替换过的内容输出到文件  ,内存到文件wr = new FileWriter("F:\\前端 works\\html\\def.txt");wr.write(a);System.out.println("输出成功");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {if(wr!=null) wr.close();if(re!=null) re.close();} catch (IOException e) {e.printStackTrace();}}
自带缓冲区的字符流

缓冲区大小:默认是一行

BufferedReader / BufferedWriter

package MyPackage;import java.io.*;public class Test9 {//自带缓冲区的字符流public static void main(String[] args) {Reader re = null;Writer wr = null;BufferedReader br = null;BufferedWriter bw = null;//文件到内存try {re = new FileReader("F:\\前端 works\\html\\abc.txt");wr = new FileWriter("F:\\前端 works\\html\\gh.txt");br = new BufferedReader(re);bw = new BufferedWriter(wr);//            char[] buf = new char[4];
//            int len = -1;StringBuffer sb = new StringBuffer();
//            while ((len = re.read(buf))!=-1){
//                sb.append(buf,0,len);//将每次读取到的数据存储到sb中
//            }
//            System.out.println(sb);String line = null;while ((line = br.readLine())!=null){sb.append(line);}//在内存中替换占位符String a = sb.toString();a = a.replace("name","韩延丰");a = a.replace("address","济南");//将替换过的内容输出到文件  ,内存到文件//            wr.write(a);bw.write(a);System.out.println("输出成功");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {/*** 先关出,在关入* 从外往内关    br外 = new BufferedReader(re内);*/try {if(br!=null) br.close();if(bw!=null) bw.close();if(wr!=null) wr.close();if(re!=null) re.close();} catch (IOException e) {e.printStackTrace();}}}
}
二进制流

DataInputStream / DataOutputStream

二进制流 对象 = new 二进制流(字节流);

package MyPackage;import java.io.*;public class Test10 {//二进制流public static void main(String[] args) {InputStream in = null;OutputStream out = null;InputStream di = null;OutputStream dataout = null;//abc.txt  ->  内存   ->  xyz.txttry {in = new FileInputStream("F:\\前端 works\\html\\abc.txt");di = new DataInputStream(in);     //字节流 -->  二进制流out = new FileOutputStream("F:\\前端 works\\html\\xyz.txt");dataout = new DataOutputStream(out);    //字节流 -->  二进制流//一次开辟10字节内存byte[] buf = new byte[10];int len = -1;while ((len=di.read(buf))!=-1){dataout.write(buf,0,len);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {if(di != null)  di.close();if(dataout!=null) dataout.close();if(out!=null)   out.close();if(in!=null)  in.close();} catch (IOException e) {e.printStackTrace();}}}
}

装饰模式

IO设计的核心思想

在不影响原有对象的前提下,无侵入的给一个对象增加一些额外的功能

网络编程

IP地址:网络上的唯一标识

ip的组成:32位,由4个8位二进制组成

协议:为了让网络中不同的计算机之间能够相互通信而建立的规则,标准,约束。

  • TCP协议:面向连接的,可靠的(不丢失,不重复,有序),基于字节流的传输通信协议,传输速度相对较慢
  • UDP协议:无连接的协议。提供不可靠的数据传输,传输速度相对较快

socket

socket (套接字):基于TCP协议的网络通信技术,可以提供双向安全连接的网络通信。

scoket需要借助于数据流(字节流)来完成数据的传递工作

模板:1.客户端建立连接,服务端准备服务(ip:端口)

​ 2.通过socket生成OutputStream 以及 InputStream(准备发送数据)

​ 3.使用OutputStream / InputStream 发送接收数据

​ 4.关闭OutputStream / InputStream /socket

    //服务端
package SocketProject;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class MyServer {public static void main(String[] args) {ServerSocket serverSocket = null;Socket socket = null;InputStream in = null;BufferedReader reader = null;OutputStream out = null;//        1.准备服务,ip:默认本机127.0.0.1  端口8080try {serverSocket = new ServerSocket(8080);//准备完毕,可以监听客户请求//accept()  用于监听客户端连接System.out.println("服务端启动");socket = serverSocket.accept();System.out.println("服务端检测到客户端连接成功");//​			2.通过socket生成OutputStream 以及 InputStream(准备发送数据)//​			3.使用OutputStream / InputStream 发送接收数据in = socket.getInputStream();reader = new BufferedReader(new InputStreamReader(in));String info = null;while ((info = reader.readLine()) != null){System.out.println("服务端-------"+info);}//服务端做出反馈out = socket.getOutputStream();out.write("welcome".getBytes());} catch (IOException e) {e.printStackTrace();}finally {try {//​			4.关闭OutputStream / InputStream /socketif(reader!=null) reader.close();if(out!=null) out.close();if(in!=null) in.close();if(socket!=null)  socket.close();if(serverSocket!=null)  serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}
}
    //客户端
package SocketProject;import java.io.*;
import java.net.Socket;public class MyClient {public static void main(String[] args) {Socket socket = null;OutputStream out = null;InputStream in = null;BufferedReader bufferedReader = null;try {socket = new Socket("127.0.0.1",8080);System.out.println("客户端连接成功");out = socket.getOutputStream();out.write("hello".getBytes());socket.shutdownOutput();//接收服务端返回的数据in = socket.getInputStream();bufferedReader = new BufferedReader(new InputStreamReader(in));String info = null;while ((info = bufferedReader.readLine())!=null){System.out.println("客户端----------"+info);}} catch (IOException e) {e.printStackTrace();}finally {try {if(bufferedReader!=null) bufferedReader.close();if(in!=null) in.close();if(out!=null) out.close();if(socket!=null) socket.close();} catch (IOException e) {e.printStackTrace();}}}
}

对象流

网络传递一个对象:1.将要传递的对象序列化 2.使用对象流(ObjectInputStream/ObjectOutputStream)

多客户端问题

思路: 客户端代码不变;服务端:每当有一个客户端,就开启一个新线程去处理(每个线程专门处理一个客户端对象)。

UDP的实现

DatagramPacket(数据):封装了数据报的数据,数据长度,目标地址和目标端口

DatagramSocket(收发器):接收发送DatagramPacket中封装好的数据

网络编程中的一些工具类

InetAddress

package demo01;import java.net.InetAddress;
import java.net.UnknownHostException;public class InetAddressDemo {public static void main(String[] args) {InetAddress host = null;try {//获取本机iphost = InetAddress.getLocalHost();System.out.println(host);//获取网络中任意一台InetAddress ip163 = InetAddress.getByName("www.163.com");System.out.println(ip163);} catch (UnknownHostException e) {e.printStackTrace();}}
}

URL / URLConnection(连接)

以下示例,注意点:输入流url->内存 ;输出流 内存->本地

package demo01;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
//从网络上下载源码到本地,   网络->内存->本地
public class URLDemo {public static void main(String[] args) {URL url = null;InputStream in = null;OutputStream out = null;URLConnection urlConnection = null;try {url = new URL("http://www.163.com");urlConnection = url.openConnection();in = urlConnection.getInputStream();out = new FileOutputStream("F:\\前端 works\\html\\xyz.txt");byte[] buf = new byte[64];int len = -1;while ((len = in.read(buf))!=-1){out.write(buf,0,len);}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {out.close();in.close();} catch (IOException e) {e.printStackTrace();}}}
}

反射

反射机制是在运行状态中:

  • 对于任意一个类,都能够知道这个类的所有属性和方法
  • 对于任意一个对象,都能够调用他的任意一个方法和属性

反射提供的功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理
package demo02;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ReflectDemo {//通过反射获取类public static void test01(){//获取反射对象(反射入口):Class//3种方法   1.Class.forName(全类名)     2.类名.class    3.对象.getClass()//1.Class.forName(全类名)try {Class<?> aClass = Class.forName("demo02.Person");System.out.println(aClass);} catch (ClassNotFoundException e) {e.printStackTrace();}//2.类名.classClass<?> bClass =  Person.class;System.out.println(bClass);//3.对象.getClass()Person person = new Person();Class<? extends Person> cClass = person.getClass();System.out.println(cClass);}//通过反射获取方法public static void test02(){//Class入口Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}//获取所有的公共(1.本类以及父类接口中的所有方法,2.符合访问修饰符规律)的方法Method[] methods = aClass.getMethods();for(Method method:methods){System.out.println(method);}System.out.println("=========================");//获取当前类的所有的方法,(1.只能时当前类, 2.忽略访问修饰符的限制)Method[] declaredMethods = aClass.getDeclaredMethods();for(Method declaredMethod:declaredMethods){System.out.println(declaredMethod);}}//获取所有的接口public static void test03(){Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Class<?>[] interfaces = aClass.getInterfaces();for (Class<?> inter:interfaces){System.out.println(inter);}}//获取所有父类public static void test04(){Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Class<?> superclass = aClass.getSuperclass();System.out.println(superclass);}//获取所有的构造方法public static void test05(){Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Constructor<?>[] constructors = aClass.getConstructors();for (Constructor<?> constructor:constructors){System.out.println(constructor);}}//获取所有的公共属性public static void test06(){Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Field[] fields = aClass.getFields();for (Field field:fields){System.out.println(field);}System.out.println("=====================");//获取当前类的所有属性Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField:declaredFields){System.out.println(declaredField);}}//获取当前反射所代表(接口)的对象(实例)public static void test07(){Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Object o = null;try {o = aClass.newInstance();Person per = (Person)o;per.interfaceMehod();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}public static void main(String[] args) {
//        test01();
//        test02();
//        test03();
//        test04();
//        test05();
//        test06();test07();}
}
package demo02;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class ReflectDemo2 {//获取对象的实例,并操作对象public static void test01() throws IllegalAccessException, InstantiationException {Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Person per = (Person)aClass.newInstance();per.setId(1);per.setName("zs");System.out.println(per.getId()+"===="+per.getName());}//操作属性public static void test02() throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Person per = (Person)aClass.newInstance();Field idField = aClass.getDeclaredField("id");//访问的是private修饰的id,但是private是私有的//修改属性的访问权限,使用反射时,如果因为访问修饰符限制造成异常,可以通过setAccessible(true)idField.setAccessible(true);idField.set(per,1);System.out.println(per.getId());}//操作方法public static void test03() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Person per = (Person)aClass.newInstance();//无参的Method a = aClass.getDeclaredMethod("a", null);a.setAccessible(true);a.invoke(per,null);System.out.println("====================");//有参的Method b = aClass.getDeclaredMethod("b", String.class);b.setAccessible(true);b.invoke(per,"zs");}//操作构造方法public static void test04() throws NoSuchMethodException {Class<?> aClass = null;try {aClass = Class.forName("demo02.Person");} catch (ClassNotFoundException e) {e.printStackTrace();}Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(int.class);System.out.println(declaredConstructor);}public static void test05() throws ClassNotFoundException {Class<?> aClass = Class.forName("demo02.Person");Method[] declaredMethods = aClass.getDeclaredMethods();for(Method declaredMethod:declaredMethods){System.out.println(declaredMethod);}}public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
//        test01();
//        test02();
//        test03();
//        test04();test05();}
}
package demo02;//用反射操作动态数组import java.lang.reflect.Array;
import java.util.Scanner;public class ReflectDemo3 {//通过反射操作一维数组public static void test01() throws ClassNotFoundException {//通过键盘输入Scanner input = new Scanner(System.in);System.out.println("请输入数组的类型:");String type = input.next();System.out.println("请输入数组的长度:");int num = input.nextInt();Class<?> aClass = Class.forName(type);//Array.newInstance(class(类型),个数)Object arr = Array.newInstance(aClass,num);//给数组的一个元素赋值Array.set(arr,0,"zs");System.out.println(Array.get(arr,0));}//通过反射操作二维数组public static void test02() throws ClassNotFoundException {//数组类型位intClass c = Integer.TYPE;//数组的长度int dim[] = {3,3};Object arr = Array.newInstance(c, dim);//从二维数组中获取一行Object arr1 = Array.get(arr, 2);Array.set(arr1,1,369);System.out.println(Array.get(arr1,1));}public static void main(String[] args) throws ClassNotFoundException {
//        test01();test02();}
}

RPC

远程过程调用

RPC:1.客户端通过Socket请求服务端,并且通过字符串(或者Class)的形式将需要请求的接口发送给服务端

2.服务端将可以提供的接口注册到服务中心(通过Map保存,key:接口的名字, value:接口的实现类)

3.服务端接收到客户端的请求后,通过请求的接口名字,在服务中心的Map中寻找对应的接口实现类

找到之后,解析刚才客户端发来的接口名,方法名,解析完毕后,通过反射技术将该方法执行,执行完毕后,再将该方法的返回值返回给客户端

文件拆分合并

1.将一个文件拆分成若干个子文件

2.将拆分后的子文件合并成源文件

拆分

package FileProject.Split;import java.io.*;
import java.util.Properties;public class SplitFile {public static void main(String[] args) throws IOException {//待拆分的文件,源文件File resFile = new File("F:\\前端 works\\html\\01_01oracle体系结构.ppt");//拆分后的目录File splitDir = new File("F:\\前端 works\\html\\splitDir");spiltFile(resFile,splitDir);}//拆分public static void spiltFile(File resFile,File splitDir) throws IOException {//判断目录是否存在,如果不存在,则创建if (!splitDir.exists()){splitDir.mkdirs();}//思路:拆分1个输入流,n个输出流//    合并n个输入流,1个输出流(注意顺序)//输入流InputStream in = null;in = new FileInputStream(resFile);//输出流OutputStream out = null;//定义缓冲区为1M,当缓冲区填满时,一次性刷出一个文件byte[] buf = new byte[1024*1024];int len = -1;int count = 1;while ((len = in.read(buf)) != -1){//new File(文件目录,文件名)out = new FileOutputStream(new File(splitDir,count +".part"));out.write(buf,0,len);count++;//关闭流,关闭之前会强行清理缓冲区out.close();}//拆分的时候如果将文件名,分割的数量保留,为后续合并做准备//生成一个配置文件,保存上述描述信息//方式一:
//        out = new FileOutputStream(new File(splitDir,count+".config"));//查询当前操作系统的换行符
//        String lineSeparator = System.getProperty("line.separator");
//        out.write(("filename="+resFile.getName() + lineSeparator).getBytes());
//        out.write(("partcount="+(count-1)).getBytes());
//        out.close();//方式二  :Properties,将内存中的多个属性以key=value的形式写到硬盘中Properties prop = new Properties();prop.setProperty("filename",resFile.getName());prop.setProperty("partcount",(count-1)+"");//写入硬盘(保存:持久化)out = new FileOutputStream(new File(splitDir,count+".config"));prop.store(out,"注释");out.close();in.close();}
}

合并

package FileProject.Merge;import java.io.*;
import java.util.*;public class MergeFile {/*** 方法一:*public static void main(String[] args) throws IOException {//读取多个拆分后的文件List<FileInputStream> inputs = new ArrayList<>();for (int i=1;i<=4;i++){inputs.add( new FileInputStream("F:\\前端 works\\html\\splitDir\\"+i+".part") );}//指定合并后的文件输出流OutputStream output = new FileOutputStream("F:\\前端 works\\html\\MergeDir\\1.ppt");//将多个输入流依次读入内存,最后再一次性输出到1.pptbyte[] buf = new byte[1024*1024];for (FileInputStream input:inputs){int len = input.read(buf);output.write(buf,0,len);}//关闭流output.close();for (FileInputStream input:inputs){input.close();}}*///方法二public static void main(String[] args) throws IOException {//指定拆分后的文件位置File splitDir = new File("F:\\前端 works\\html\\splitDir");//指定合并后的文件位置File mergeDir = new File("F:\\前端 works\\html\\MergeDir");//软件使用次数if(hasRemainingTries()){//拆分文件Merge(splitDir,mergeDir);}else{System.out.println("试用次数已用完");}}//文件合并public static void Merge(File splitDir,File mergeDir) throws IOException {//合并之前,先读取配置文件信息Properties prop = getProperties();int partcount =  Integer.parseInt(prop.getProperty("partcount"));//读取多个拆分后的文件List<FileInputStream> inputs = new ArrayList<>();for (int i=1;i<=partcount;i++){inputs.add( new FileInputStream("F:\\前端 works\\html\\splitDir\\"+i+".part") );}//List-->EnumerationEnumeration<FileInputStream> en = Collections.enumeration(inputs);//多个流-->一个流SequenceInputStream sin = new SequenceInputStream(en);//指定合并后的文件输出流OutputStream output = new FileOutputStream("F:\\前端 works\\html\\MergeDir\\9.ppt");//sin输出byte[] buf = new byte[1024];int len = -1;while ((len = sin.read(buf)) != -1){output.write(buf,0,len);}output.close();sin.close();for (FileInputStream input:inputs){input.close();}}//读取配置文件信息public static Properties getProperties() throws IOException {//找到配置文件的位置String configFileName = "F:\\前端 works\\html\\splitDir\\5.config";Properties prop = new Properties();prop.load(new FileInputStream(configFileName));return prop;}//试用次数,判断是否还有试用次数,将当前用的次数保存在硬盘中,然后每一次使用时和5比较public static boolean hasRemainingTries() throws IOException {Properties prop = new Properties();int count = 0;//每使用一次:1.先获取之前的使用的次数,2.将之前的次数+1//查询本次之前用了几次prop.load(new FileInputStream(new File("F:\\前端 works\\html\\splitDir\\6.config")));String times = prop.getProperty("times");if(times == null){count = 1;prop.setProperty("times",count+"");}else {int timecount = Integer.parseInt(times);timecount++;prop.setProperty("times",timecount+"");if(timecount>5) return false;}prop.store(new FileOutputStream(new File("F:\\前端 works\\html\\splitDir\\6.config")),"try times..");return true;}
}

序列化,反序列化

把对象从内存——>硬盘 序列化

把对象从硬盘——>内存 反序列化

实现序列化和反序列化 对象所属的类必须实现 Serializable 接口

ObjectOutputStream 序列化流 ObjectInputStream 反序列化流

Json

{kay:value,key:value}

下载json库

Map,字符串,对象——>Json : JSONObject json = new JSONObject(Map/字符串/对象);

 //a.   Map  -->Jsonpublic static void demo01(){Map<String,String> map = new HashMap<>();map.put("name","zs");map.put("age","13");JSONObject json = new JSONObject(map);System.out.println(json);//可以得到json的格式:{key:value,key:value}}//b.   JavaBean(普通对象)-->Jsonpublic static void demo02(){Person per01 = new Person("zs",13);JSONObject json = new JSONObject(per01);System.out.println(json);//{对象的属性名:对象的属性值;对象的属性名:对象的属性值;}}//c.   字符串-->Jsonpublic static void demo03(){String str = "{\"name\":\"zs\",\"age\":13}";JSONObject json = new JSONObject(str);System.out.println(json);}

文件——>Json对象 思路:文件——>String——>Json

 //文件——>Json   (file ——> String ——> Json)public void demo04() throws IOException {//文件 -> String//方法一:
//        InputStream in = super.getClass().getClassLoader().getResourceAsStream("Json/per.json");
//        byte[] buf = new byte[10];
//        int len = -1;
//        StringBuffer sb = new StringBuffer();
//        while ((len = in.read(buf)) != -1){
//            //byte[] -> String
//            String str = new String(buf,0,len);
//            sb.append(str);
//        }
//        System.out.println(sb);//方法二:commons-io.jarString s = FileUtils.readFileToString(new File("F:\\Idea works\\Javajichu\\src\\Json\\per.json"));//String -> Json
//        String s = sb.toString();JSONObject json = new JSONObject(s);System.out.println(json);}

生成Json文件

Json对象.write();

public static void demo05() throws IOException {//准备Json数据Map<String,String> map = new HashMap<>();map.put("name","ls");map.put("age","13");JSONObject json = new JSONObject(map);FileWriter fileWriter = new FileWriter("F:\\前端 works\\html\\1.json");json.write(fileWriter);fileWriter.close();}

JsonArray

JSONArray jArray = new JSONArray();

加密解密

使用异或进行加密解密

异或:a.同为0,异为1

​ b.一个数,两次异或之后,是原数本身

“xxxx” ——> 异或一次是加密 ;异或两次是解密

package utils;
public class SecurityUtil {//通过异或实现加密,解密      ,   传入String  ,返回String   ;xor:异或  ;  i,String对i进行异或public static String xor(String input) {//对每一个字符进行加密,先把字符串变成字符数组   :  "abc" --->  {'a','b','c'}char[] chs = input.toCharArray();for(int i=0;i<chs.length;i++) {//对每一位进行加密chs[i] = (char)(chs[i]^3000);//大类型转换为小类型要强转}return new String(chs);}//测试public static void main(String[] args) {//一次异或String str = xor("abc");System.out.println(str);//二次异或str = xor(str);System.out.println(str);}
}

MD5/SHA256

字符串->十六进制串

不可逆

//MD5public static String md5Encode(byte[] input) {return DigestUtils.md5Hex(input);}//SHA256public static String sha256(byte[] input) {return DigestUtils.sha256Hex(input);}

Base64

//Base64加密public static String base64Encode(byte[] input){String result = null;try {Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method method = clazz.getMethod("encode", byte[].class);result = (String)method.invoke(null, input);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}//Base64解密public static byte[] base64decode(String input) {byte[] result = null;try {Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method method = clazz.getMethod("decode", String.class);result = (byte[])method.invoke(null, input);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}

XML解析

Dom解析

Sax解析

事件驱动:程序再执行时,到n哪个阶段时,自动触发哪个阶段对应的方法

图表

1.使用DefaultPieDataset(饼图) / DefaultCategoryDateset(柱形图,折线图,区域图)对象创建数据集

2.创建JFreeChart对象

3.获取图片(3中方式)

//创建图表的数据
DefaultPieDataset dateset = new DefaultPieDataset();
dateset.setValue("value1", 20.0);
dateset.setValue("value2", 30.0);
dateset.setValue("value3", 50.0);//创建jFree对象
JFreeChart jFree = ChartFactory.createPieChart("DATA pige", dateset);
//获取绘图区
PiePlot pieplot = (PiePlot)jfree.getPlot();//展示1
OutputStream out = response.getOutputStream();
response.setContentType("image/png");
ChartUtils.writeChartAsJPEG(out, jFree, 300, 300);		
//关闭流
out.close();//展示2
//ChartUtils.saveChartAsJPEG(new File("F:\\前端 works\\html\\pie.jpg"), jFree, 500, 500);//展示3
String fileName = ServletUtilities.saveChartAsJPEG(jFree, 500, 500,request.getSession());
String url = request.getContextPath()+"/servlet/DisplayChart?filename="+fileName;	
request.setAttribute("url", url);
request.getRequestDispatcher("show.jsp").forward(request, response);

绘图区:Point区域

h (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}

//Base64解密
public static byte[] base64decode(String input) {byte[] result = null;try {Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");Method method = clazz.getMethod("decode", String.class);result = (byte[])method.invoke(null, input);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;
}

## XML解析Dom解析Sax解析事件驱动:程序再执行时,到n哪个阶段时,自动触发哪个阶段对应的方法## 图表1.使用DefaultPieDataset(饼图) / DefaultCategoryDateset(柱形图,折线图,区域图)对象创建数据集2.创建JFreeChart对象3.获取图片(3中方式)```java
//创建图表的数据
DefaultPieDataset dateset = new DefaultPieDataset();
dateset.setValue("value1", 20.0);
dateset.setValue("value2", 30.0);
dateset.setValue("value3", 50.0);//创建jFree对象
JFreeChart jFree = ChartFactory.createPieChart("DATA pige", dateset);
//获取绘图区
PiePlot pieplot = (PiePlot)jfree.getPlot();//展示1
OutputStream out = response.getOutputStream();
response.setContentType("image/png");
ChartUtils.writeChartAsJPEG(out, jFree, 300, 300);		
//关闭流
out.close();//展示2
//ChartUtils.saveChartAsJPEG(new File("F:\\前端 works\\html\\pie.jpg"), jFree, 500, 500);//展示3
String fileName = ServletUtilities.saveChartAsJPEG(jFree, 500, 500,request.getSession());
String url = request.getContextPath()+"/servlet/DisplayChart?filename="+fileName;	
request.setAttribute("url", url);
request.getRequestDispatcher("show.jsp").forward(request, response);