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 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<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.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);
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!