Java基础

Java

java基础

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

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

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

jvm:java虚拟机

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

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

jvm

安装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

​ 小数float

非数字

​ 字符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 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 abstract
    public 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转成String
            System.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.txt
        try {
            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.txt
        try {
            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  端口8080
        try {
            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 /socket
               if(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 {
            //获取本机ip
            host = 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.类名.class
        Class<?> 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 {
        //数组类型位int
        Class 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 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.ppt
        byte[] 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-->Enumeration
        Enumeration<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  -->Json
    public 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(普通对象)-->Json
    public static void demo02(){
        Person per01 = new Person("zs",13);
        JSONObject json = new JSONObject(per01);
        System.out.println(json);
        //{对象的属性名:对象的属性值;对象的属性名:对象的属性值;}
    }

    //c.   字符串-->Json
    public 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.jar
        String 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

字符串->十六进制串

不可逆

//MD5
	public static String md5Encode(byte[] input) {
		return DigestUtils.md5Hex(input);
	}
	
	//SHA256
	public 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 block
			e.printStackTrace();
		} catch (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 block
			e.printStackTrace();
		} catch (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;
	}

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 block
		e.printStackTrace();
	} catch (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;
}

## 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);

你可能感兴趣的:(Java,java,开发语言)