java
01 基础语法
1.环境问题
1.1 jdk的配置
JAVA_HOME 配置的就是 JDK 安装的一个根目录
Path 无需新建,只需要添加值(JDK 下的 bin 目录)即可
CLASS_PATH 配置的就是 JDK 的 lib 目录
1.2 JVM的语言特性
JVM是Java语言能够跨平台的前提,但是JVM本身不跨平台
我们编写的文件是以”.java”为后缀的源代码文件,Ctrl+S保存时会触发编译器Eclipse对写好的代码进行编译,编译后生成以”.class”为后缀的字节码文件,当Ctrl+F11运行代码时,JVM就会加载字节码文件, 并加载main方法执行程序, 进而在控制台显示代码效果
2.语法基础
2.1标识符
标识符就是一个名字
由字母、数字、下划线、美元符号$四种组成($一般在内部类.class文件可以见到),
别的元素都是非法的.不能用数字开头,严格区分大小写,不能使用 Java 的关键字,见名知意
2.2关键字
Java 中一些具有特殊意义的单词,一共有 53 个,2 个保留字 const goto
2.3注释
单行注释 //
多行注释 /* */
文档/doc 注释 /** */ 除了注释的效果以外,还可以添加一些关键信息,作者…
2.4变量
变量中存储的都是一些可能会发生变化的值,格式:
int a = 18 ; --完成的是声明+初始化,一步到位
int a; a = 18; --先声明,再赋值
2.5成员变量
类里方法外,属于类资源,可以不手动初始化,直到类消失,它才会消失
2.6局部变量
写在方法里或者局部代码块中,必须进行手动初始化,当局部代码执行完毕就释放了
变量有一个就近原则,如果成员变量与局部变量同名,需要this额外指定
3.数据类型
3.1基本类型(8种)
byte、short、int、long、float、double、char、boolean
3.2引用类型
存的是地址值
3.3字面值规则
整数类型的字面值是 int 类型,46836--->int 类型
浮点数类型的字面值是 double 类型,4.56--->double 类型
byte,short,char 三种比 int 小的类型,可以使用范围内的值直接赋值
三个后缀 LFD 进制前缀 0b 0x \u
3.4类型转换
能否转换取决于类型的取值范围,而不是字节数,字节数只能做参考
小转大,直接转 大转小,强制转 浮变整,小数没
3.5运算规则
int/int--->int int/double--->double
整数运算—>溢出(光年)
byte,short,char 三种比 int 小的类型,运算时会自动提升成 int 类型
浮点数的特殊值 Infinity NAN
浮点数运算不精确 解决方案:BigDecimal
不能使用 double 类型参数的构造,使用的是 String 类型的构造函数,否则还会不精确
除法运算时,如果出现除不尽的现象会报错,需要指定保留位数和舍入规则
4.运算符
4.1算术运算符
+ - * / +(拼接) %(取余) 3%2=1
自增自减运算符 a++ ,++a ,a-- ,--a
需要注意的是:如果在本行使用,符号在前,先变化,再使用;符号在后,先使用,再变化
4.2比较运算符
比较运算符 == != >= <= > < 结果是boolean类型
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
import java.util.ArrayList; import java.util.Vector; public class Main { public static void main(String[] args) { Object testObject = new ArrayList(); displayObjectClass(testObject); } public static void displayObjectClass(Object o) { if (o instanceof Vector) System.out.println("对象是 java.util.Vector 类的实例"); else if (o instanceof ArrayList) System.out.println("对象是 java.util.ArrayList 类的实例"); else System.out.println("对象是 " + o.getClass() + " 类的实例"); } }
4.3逻辑运算符
& | ^ ~ 二进制的运算
&& || 复合的逻辑运算符,只不过增加了短路的功能,效率更高
4.4三目运算符
三元运算符 1 ? 2 : 3 ?根据 1 号位置的表达式结果确定三元的最终结果,1 表达式如果对就取2,反之取2
4.5赋值运算符
+= -= *= /= :简写,比较方便 运算时会自动进行类型转换
() 多层复杂运算想要控制优先级,可以使用小括号
5.流程控制
5.1 if-else
5.2switch-case
switch:里边只能放byte short char int String enum类型的数据
default:保底选项 break:不加会穿透 拓展: enum
package cn.tedu.Test; public class SwitchCaseTest { public static void main(String[] args) { String day="周一"; switch (day) { case "周日" : System.out.println("玩");break; case "周六" : System.out.println("自习");break; default:System.out.println("上课"); } } }
5.3for
普通for循环:for(开始条件;循环条件;更改条件){ 循环体 }
增强for循环:for(遍历到的元素的类型 遍历到的元素的名字 : 要遍历的元素){ }
嵌套for循环:for 里有 for!外层循环执行一次,内层循环执行多次,外层循环控制行,内层循环控制列
5.4while
while:先判断后执行
5.5do-while
do-while:先执行一次,再判断是否继续执行
6.方法
6.1格式
访问控制符 返回值类型 方法名(参数列表){ 方法体 }
public void eat (){ System.out.println("吃吃吃"); }
6.2调用
方法名+参数列表
eat();
6.3返回到调用位置
解释:比如 main()中我们可以调用一个方法,如果这个方法有返回值,我们有两种选择:
1 接收这个方法的返回值 (在 main()中可以继续使用这个方法的返回值)
2 忽略这个方法的返回值
6.4方法的重写与重载
重载:在同一个类中,存在方法名相同,但参数列表不同的方法参数。
列表不同是指:参数个数不同/对应位置上的参数类型不同,与参数名无关
重写:发生在两个类中,规则:两同两小一大(
-
方法名相同
-
参数列表相同
-
子类的返回值类型要小于等于父类的返回值类型
-
子类抛出的异常要小于等于父类的
-
子类修饰符要大于等于父类修饰符的权限)
6.5break&continue&return
-
break:直接跳出本层循环,但是注意,如果是多层循环,不能一次性都跳出
-
continue:不执行本轮循环中后边的语句,直接开始下一轮循环
-
return:直接结束本方法,如果有返回值,就返回结果
7.数组
7.1数组的创建
我们通过数组下标来操作数组中的元素,适合查询场景,不适合增删
1:动态创建&静态创建
//动态初始化 int[] a = new int[5]; //静态初始化 int[] b = new int[]{1,2,3,4,5}; int[] c = {1,2,3,4,5};
2:数组一旦创建,长度不可改变,数组名是一个引用类型变量,存着的是数组的地址
3:数组的长度 length 是数组的属性,而且数组的长度允许为 0
7.2数组的工具类 Arrays
toString() sort() copyOf()
int[] arr ={9,3,8,4,1}; System.out.println(arr);//[I@1b6d3586 System.out.println(Arrays.toString(arr));//[9, 3, 8, 4, 1] Arrays.sort(arr); System.out.println(Arrays.toString(arr));//[1, 3, 4, 8, 9] int[] arr1=Arrays.copyOf(arr, 3); System.out.println(Arrays.toString(arr1));//[1, 3, 4] int[] arr2=Arrays.copyOfRange(arr,2,4 ); System.out.println(Arrays.toString(arr2));//[4, 8]
02 面向对象
1.面向过程
面向过程是一种思想,意思是我们要做任何事,都需要亲力亲为,强调的是过程。
2.面向对象
面向对象也是一种编程思想,相对于面向过程,我们可以由原来问题的执行者变为指挥者,进而把生活中很多复杂的问题变得简单化。
3.类和对象的关系
我们可以通过类来描述一类事物,用成员变量描述事物的属性,用方法描述事物的行为.
4.面向对象的三大特征
4.1封装
1:总结归纳一类事物的特点与行为,通过抽象,封装成一个“类”组件【重用性】 2:使用private关键字封装属性与方法,组织外界直接访问资源【安全性】 封装属性 1>使用private修饰类中的成员变量,被private修饰的资源只能在本类中使用 2>对外提供公共的getXxx()【获取值】与setXxx()【设置值】 3>我们可以通过封装组织外界直接访问资源,想要访问,必须按照我的方式来 封装方法 1>使用private修饰类中的方法,被private修饰的资源外部无法直接访问 2>可以在本类的公共方法中调用此私有方法的功能
4.2继承
-
我们通过关键字extends建立子类与父类的继承关系,格式:子类 extends 父类
-
子类继承父类,相当于子类把父类的功能复制了一份
-
父类的私有资源子类不可用,是因为被private修饰不可见
-
java只支持单继承,一个子类只能有一个父类,但一个父类可以有多个子类
-
继承具体传递性,爷爷的功能传给爸爸,爸爸的功能传给孙子
-
子类可以拥有自己的特有的功能,实现功能的拓展
-
继承是is a的关系,依赖性非常强,强耦合
4.3多态
多态的前提:继承+重写 口诀1:父类引用指向子类对象 口诀2:编译看左边,运行看右边 解释:如果想要使用多态的效果,方法的声明看的是父类,而具体实现使用的是子类我们目前学习的多态对象都是把自己当作是一个父类类型,所以: 1)多态对象不可以使用子类特有的功能 2)多态对象使用的成员变量是父类的 3)多态对象使用时,如果父子类中出现同名静态方法,使用的还是父类的 4)多态对象在使用方法时,如果子类重写了,使用的是子类的方法体 TIPS:静态资源属于优先加载的类资源,静态方法不存在重写的现象
4.4抽象
后面详见抽象类
5.构造方法
6.构造代码块
执行时机:静态代码块—>构造代码块—>构造方法—>对象创建成功—>局部代码块
6.1构造代码块
位置:类里方法外,与成员变量一样 执行时机:创建对象时执行,并且先于构造方法执行 作用:用于提取所有构造方法的共性内容
6.2局部代码块
位置:方法里 执行时机:调用此局部代码块所在的方法时才会执行 作用:用于控制变量的作用范围,范围越小越好
6.3静态代码块 static
位置:类里方法外,格式:static{ } 执行时机:随着类的加载而加载,优先与对象加载,并且只加载一次 作用:用于加载一些需要第一时间就加载并且只加载一次的资源
7.this 与 super
是一个关键字,可以把它看作是”类对象“,比如看作:Cat this = new Cat(); 1: 由于变量的就近原则,如果成员变量与局部变量同名想使用成员的变量的话,是用”this.“来调用类资源-成员变量 2:this可以实现构造方法间的调用,但注意不能来回互相调用!!! 规定:this必须写在构造方法的第一行!!! 格式:this();--调用无参构造 this("");--调用含参构造
this 代表的是本类对象 super 代表是父类对象
this 用于变量名相同时指定成员变量
this 可以实现构造方法间的调用,但是不能来回调用 this();
1.super是一个关键字,而且位置必须是首行 2.super代表的是父类的一个引用,你可以把它看成是Father super = new Father(); 3.如果子类与父类的成员变量同名时,可以使用”super.“进行指定
super 也可以调用构造方法,子类的构造方法中默认存在 super();
8.static
1.static是一个关键字 2.static可以修饰成员变量和方法,被修饰的资源就是静态资源 3.静态资源优先于对象加载,随着类的加载而加载 4.被静态修饰的资源可以通过类名直接调用 5.静态资源全局共享(被所有对象共享),值只有一份
静态资源只能调用静态资源
静态区域内不能使用 this 和 super
final用来修饰不可变的量,static用来就是共享资源,类加载时加载。
9.final
被 final 修饰的类,不能被继承
被 final 修饰的方法,不能被重写
被 final 修饰的变量是个常量,值不能被改变
常量的定义形式: final 数据类型 常量名 = 值;
10.抽象类
抽象 关键字 abstract 1.修饰类--被abstract修饰的类是抽象类 2.修饰方法--被abstract修饰的方法是抽象方法 格式:修饰符 abstract 返回值类型 方法名(参数列表);--没有方法体
1>一旦一个类中有抽象方法,那么这个类必须是抽象类 2>抽象类中既可以都是普通方法,也可以都是抽象方法,还可以混着来 3>抽象类不允许实例化--创建对象 4>如果一个类继承了抽象父类,那么: 方案一:继续抽象,作为抽象子类 方案二:实现抽象父类中的(所有!!!)抽象方法 5>创建时,如果想使用抽象父类,可以创建多态对象进行测试
11.接口
类与类的关系 继承关系,而且只支持单继承--“单继承” A extends B ,A是子类,B是父类,子类可以使用父类的所有非私有资源 如果子类对父类的功能不满意,是可以重写的 接口与接口的关系 继承关系,接口可以多继承 Inter1 extends Inter2,Inter3 Inter2和Inter3是父接口,Inter1是子接口 接口的继承关系类似于功能的汇总,接口1拥有接口2 3的所有功能定义 Inter1 extends Inter2{}--本接口只有一个父接口 类与接口的关系 实现关系,一个类可以实现多个接口--"多实现" class implements Inter1,Inter2{} class2 implements Inter3{}
03 基础 API
1.常用 API
Object 顶级父类, 所有类默认把 Object 作为自己的超类
hashCode() --返回对应对象的哈希码值
equals()—默认实现是==比较, 比较的是地址值 比如 String 就重写了这个方法, 比较的是两个字符串的具体内容
toString()—默认实现: 打印包名.类名@哈希码值 如果想要查看对象的属性与属性值, 可以重写这个方法
String 底层维护了一个 char[]
String s = “abc”;//放在了常量池
使用+进行拼接, 效率很低
优化: StringBuffer StringBuilder
append()方法拼接效率高
2.正则
例如:\d{17}[0-9X]身份证号
3.包装类
3.1自动装箱与自动拆箱
Integer 创建对象 方式一: new Integer(5); 方式二: Integer.valueOf(5); Integer类中包含256个Integer缓存对象,范围是 -128~127 使用valueOf()时,如果指定范围内的值,直接访问缓存对象不新建;如果指定范围外的值,直接新建对象。
String转换成int类型: parseInt(String s)
Integer i1 =5;//自动装箱 int i2=i1;//自动拆箱
3.2BigDecimal
用来解决浮点数不精确的问题
4.集合
4.1Collection
public static void main(String[] args) { Collection<Integer> c= new ArrayList<Integer>(); c.add(100);c.add(200);c.add(300);c.add(400);c.add(500); //1.添加 System.out.println(c); //c.clear(); //2.清空集合 //System.out.println(c);[] System.out.println(c.contains(100)); //3.是否包含指定元素 System.out.println(c.hashCode()); //4.获取当前对象的哈希码值 System.out.println(c.isEmpty()); //5.判断当前集合是否为空 System.out.println(c.remove(600)); //6.移除指定元素(首次出现) System.out.println(c.size()); //7.获取当前集合中元素的个数 System.out.println(c.equals(200)); //8.集合对象与Integer200不等 Object[] array = c.toArray(); //9.将集合转成数组 System.out.println(Arrays.toString(array)); Collection<Integer> c2 =new ArrayList<Integer>(); //10.向集合中添加指定集合的全部元素 c2.add(2);c2.add(4);c2.add(6); c2.addAll(c); System.out.println(c2); System.out.println(c2.contains(c));//false因为c2中没有元素c //11.查看当前集合中是否包含指定集合 System.out.println(c2.containsAll(c)); System.out.println(c2.retainAll(c)); //12.取两个集合的公共部分(交集) System.out.println(c);//[100, 200, 300, 400, 500] System.out.println(c2.removeAll(c)); //13.删除c2集合中c也有的元素 System.out.println(c2); System.out.println(c); Iterator<Integer> it = c.iterator(); //14.迭代 while(it.hasNext()){ System.out.println(it.next()); } }
4.2List
4.2.1ArrayList
ArrayList没有自己的方法,都是利用多态继承过来的
new ArrayList(20); 这个意思是初始容量为20(默认初始容量为10)
4.2.2LinkedList
public static void main(String[] args) { LinkedList<String> list = new LinkedList<>(); list.add("唐僧");list.add("悟空");list.add("八戒"); list.add("沙僧");list.add("白龙马"); System.out.println(list); list.addFirst("蜘蛛精"); //1.添加一个首元素 list.addLast("白骨精"); //2.添加一个尾元素 System.out.println(list); System.out.println(list.getFirst()); //3.获取首元素 System.out.println(list.getLast()); //4.获取尾元素 System.out.println(list.removeFirst()); //5.删除首元素 System.out.println(list.removeLast()); //6.删除尾元素 System.out.println(list); LinkedList<String> list2 = new LinkedList<>(); list2.add("西游记");list2.add("红楼梦"); list2.add("三国演义");list2.add("水浒传"); System.out.println(list2); /*别名:查询系列*/ System.out.println(list2.peek()); //1.获取但不移除首元素 System.out.println(list2.peekFirst()); //2.获取但不移除首元素 System.out.println(list2.peekLast()); //3.获取但不移除尾元素 /*别名:新增系列*/ System.out.println(list2.offer("斗罗大陆")); //1.添加到集合末尾 System.out.println(list2.offerFirst("斗破苍穹")); //2.添加到集合首 System.out.println(list2.offerLast("海贼王")); //3.添加到集合末尾 System.out.println(list2); /*别名:移除序列*/ System.out.println(list2.poll()); //1.获取并移除集合中首元素 System.out.println(list2); System.out.println(list2.pollFirst()); //2.获取并移除集合中首元素 System.out.println(list2); System.out.println(list2.pollLast()); //3.获取并移除集合中尾元素 System.out.println(list2); System.out.println(list2.element()); //4.获取但不移除首元素 System.out.println(list2); }
4.3Set
-
Set是一个不包含重复数据的Collection
-
Set集合中的数据是无序的(因为Set集合没有下标)
-
Set集合中的元素不可以重复 – 常用来给数据去重
4.3.1HashSet
-
HashSet : 底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
-
Set<String> set2=new HashSet<>(); set2.add("小狮几");set2.add("小海藤"); set2.add("小兔纸");set2.add("小脑斧"); System.out.println(set2);//[小兔纸, 小狮几, 小海藤, 小脑斧] System.out.println(set.addAll(set2));//true System.out.println(set);//[小兔纸, 虎虎生威, 小狮几, 牛气冲天, 小海藤, 小脑斧] System.out.println(set.containsAll(set2));//true System.out.println(set);//[小兔纸, 虎虎生威, 小狮几, 牛气冲天, 小海藤, 小脑斧] /*retainAll去两个集合的交集,谁来调用就影响谁 **如果没有交集,那么调用的会为空*/ System.out.println(set.retainAll(set2)); System.out.println(set); System.out.println(set2); Iterator<String> it = set.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } for(String s: set){ System.out.print(s+" "); }
4.3.2TreeSet
底层是TreeMap,也是红黑树的形式,便于查找数据
4.4Map
map中都是无序的数据 map中的key值不可以重复,如果重复,次key值对应的value会被覆盖 {9527=白骨精, 9528=玉兔精, 9529=鲤鱼精}打印结果没有9528的黑熊精
Map<Integer,String> map =new HashMap<>(); map.put(9527,"白骨精"); map.put(9528, "黑熊精"); map.put(9528, "玉兔精"); map.put(9529, "鲤鱼精"); System.out.println(map); //map.clear(); System.out.println(map.containsKey(9528));//true //1.判断当前集合是否包含指定的key System.out.println(map.containsValue("白骨精"));//true //2.判断当前集合是否包含指定的value System.out.println(map.get(9529));//鲤鱼精 //3.根据key取出对应的value System.out.println(map.remove(9528));//玉兔精 //4.根据指定的key取删除(<k,v>均删除) System.out.println(map.get(9528));//null //5.获取指定key对应的value的值 System.out.println(map.containsKey(9528));//false //6.判断当前集合是否包含指定的value System.out.println(map.size());//2 //7.获取集合中键值对的个数 System.out.println(map.hashCode());//70221251 //8.获取map对象对应的哈希码值 System.out.println(map.equals("黑熊精"));//false //9.判断两个是否相等(map为地址值,不可能相等) System.out.println(map.values());//[白骨精, 鲤鱼精] //10.获取当前集合中所有value取出放到一个集合中
5.SET 集合的迭代
Set<String> set2=new HashSet<>(); set2.add("小狮几");set2.add("小海藤"); set2.add("小兔纸");set2.add("小脑斧"); Iterator<String> it = set.iterator(); while(it.hasNext()){ System.out.print(it.next()+" "); } for(String s: set){ System.out.print(s+" "); }
6.IO
1) 按照方向进行分类:输入流 输出流(相对于程序而言,从程序写数据到文件中是输出)
2) 按照传输类型进行分类:字节流 字符流
3) 组合: 字节输入流 字节输出流 字符输入流 字符输出流
5.1File
File file = new File("D:\\ready\\1.txt"); System.out.println(file.length()); //1.获取文件字节数/字节量大小 System.out.println(file.exists()); //2.判断指定文件是否存在 System.out.println(file.isFile()); //3.判断指定File是否是一个文件 System.out.println(file.isDirectory()); //4.判断指定File是否是一个文件夹 System.out.println(file.getName()); //5.获取指定File的名字 System.out.println(file.getParent()); //6.获取指定File的父级目录 System.out.println(file.getAbsolutePath()); //7.获取指定File的绝对路径 file = new File("D:\\ready\\2.txt"); System.out.println(file.createNewFile()); //8.根据指定路径在相应的路径下创建相应的文件(当前文件不存在为true) file = new File("D:\\ready\\m"); //9.根据指定路径在相应的路径下创建相应的单层目录 System.out.println(file.mkdir()); file = new File("D:\\ready\\a\\b\\c"); //10.根据指定路径在相应的路径下创建相应的多层目录 System.out.println(file.mkdirs()); System.out.println(file.delete()); //11.删除文件或空文件文件夹,这种情况只删除c file = new File("D:\\ready"); //12.文件列表测试 String[] list = file.list(); System.out.println(Arrays.toString(list)); File[] files = file.listFiles(); System.out.println(Arrays.toString(files)); System.out.println(list.length); System.out.println(files.length);
5.2InputStream
--InputStream 抽象类,不能new,可以作为超类,学习其所提供的共性方法
--FileInputStream 子类,操作文件的字节输入流,普通类
--BufferedInputStream 子类,缓冲字节输入流,普通类
package cn.tedu.file; import java.io.*; import java.util.Arrays; /*本类用于练习字节输入流*/ public class TestIn { public static void main(String[] args) { //method();//字节流的读取 method2();//高效字节流读取 } private static void method2() { InputStream in=null; try { //InputStream in =new BufferedInputStream(new FileInputStream(new File("D:\\ready\\1.txt"))); in=new BufferedInputStream( new FileInputStream("D:\\ready\\1.txt")); int b; while((b=in.read())!=-1){ System.out.println(b); } } catch (Exception e) { e.printStackTrace(); }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void method(){ InputStream in = null ; try { //方式一 //InputStream in=new FileInputStream(new File("D:\\ready\\1.txt")); in =new FileInputStream("D:\\ready\\1.txt"); /*每次调用都会读取一个字节,如果读到了数据的末尾,返回-1*/ //System.out.println(in.read()); int b; while((b=in.read())!=-1){ System.out.println(b); } } catch (Exception e) { e.printStackTrace(); /*try-catch结构中的第三个部分:finally{} **这部分不论是否能捕获到异常,是一定会执行到的代码,常用于关流*/ }finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5.3OutputStream
--OutputStream 抽象类,不能new,可以作为超类,学习其所提供的共性方法
--FileOutputStream 子类,操作文件的字节输出流,普通类
--BufferedOutputStream 子类,缓冲字节输出流,普通类
package cn.tedu.file; import java.io.*; /*本类用于测试字节输出流*/ public class TestOut { public static void main(String[] args) { //method(); method2(); } private static void method2() { OutputStream out =null; try { //out=new BufferedOutputStream(new FileOutputStream(new File("D:\\ready\\3.txt"))); out=new BufferedOutputStream( new FileOutputStream("D:\\ready\\3.txt",true)); out.write(97); out.write(98); out.write(99); } catch (Exception e) { e.printStackTrace(); } finally{ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void method() { OutputStream out=null; try { //out=new FileOutputStream(new File("D:\\ready\\3.txt")); out=new FileOutputStream("D:\\ready\\3.txt"); out.write(100); out.write(100); out.write(100); out.write(100); } catch (Exception e) { e.printStackTrace(); }finally{ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5.4Reader
-Reader 抽象类,不能new,可以作为超类,学习其所提供的共性方法
--FileReader,子类,操作文件的字符输入流,普通类
--BufferedReader,子类,缓冲字符输入流,普通类
package cn.tedu.file; import java.io.*; /*本类用于测试字符流的读取*/ public class TestIn2 { public static void main(String[] args) { //method();//普通 method2();//高效 } private static void method2() { Reader in=null; try { //in=new BufferedReader(new FileReader(new File("D:\\ready\\1.txt"))); in = new BufferedReader(new FileReader("D:\\ready\\1.txt")); int b; while((b=in.read())!=-1){ System.out.println(b); } } catch (Exception e) { e.printStackTrace(); }finally{ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void method() { Reader in=null; try { //Reader r=new FileReader(new File("D:\\ready\\1.txt")); in = new FileReader("D:\\ready\\1.txt"); int b; while((b=in.read())!=-1){ System.out.println(b); } } catch (Exception e) { e.printStackTrace(); }finally{ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5.5Writer
--Writer 抽象类,不能new,可以作为超类,学习其所提供的共性方法
--FileWriter,子类,操作文件的字符输出流,普通类
--BufferedWriter,子类,缓冲字符输出流,普通类
package cn.tedu.file; import java.io.*; /*本类用于字符输出流测试*/ public class TestOut2 { public static void main(String[] args) { //method(); method2(); } private static void method2() { Writer out =null; try { //out=new BufferedWriter(new FileWriter(new File("D:\\ready\\3.txt"),true)); out=new BufferedWriter(new FileWriter("D:\\ready\\3.txt",true)); out.write(100); out.write(101); out.write(102); out.write(103); out.write(104); } catch (IOException e) { e.printStackTrace(); }finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void method() { Writer out=null; try { //out = new FileWriter(new File("D:\\ready\\3.txt"),true); out=new FileWriter("D:\\ready\\3.txt",true); out.write(105); out.write(105); out.write(105); } catch (IOException e) { e.printStackTrace(); }finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5.6序列化
序列化:ObjectOutputStream把对象保存到磁盘
构造方法: ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream 普通方法: writeObject(Object obj) 将指定的对象写入 ObjectOutputStream
反序列化:ObjectInputStream 磁盘序列化后的数据重新恢复成对象
构造方法:
ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream 普通方法: readObject() 从 ObjectInputStream 读取对象
package cn.tedu.serializable; import java.io.*; //本类用于测试序列化和反序列化 public class TestSerializable { public static void main(String[] args) { method();//序列化 method2();//反序列化 } private static void method2() { ObjectInputStream in =null; try { in =new ObjectInputStream(new FileInputStream("D:\\ready\\1.txt")); Object o=in.readObject(); System.out.println(o); System.out.println("反序列化成功"); } catch (Exception e) { System.out.println("反序列化失败"); e.printStackTrace(); }finally{ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } private static void method() { ObjectOutputStream out = null; try { out=new ObjectOutputStream(new FileOutputStream("D:\\ready\\1.txt")); Student obj=new Student("乐乐",18,"快乐星球",'男'); out.writeObject(obj); System.out.println("序列化成功"); } catch (Exception e) { System.out.println("序列化失败"); e.printStackTrace(); }finally{ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } }
7.线程
7.1线程与进程
一个操作系统中可以有多个进程,一个进程中可以包含一个线程(单线程程序),也可以包含多个线程(多线程程序)
进程就是正在运行的程序
独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,在没有经过进程本身允许的情况下,一个用户进程不可 以直接访问其他进程的地址空间 动态性::进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合,程序加入了时间的概念以后,称为进程,具有自己的生命 周期 和各种不同的状态,这些概念都是程序所不具备的. 并发性 :多个进程可以在单个处理器CPU上并发执行,多个进程之间不会互相影响
7.3多线程的特性&状态(随机性)
7.4多线程的实现方式
继承的方式&&实现Runnable接口的方式
package cn.tedu.thread; public class Thread1{ public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); t1.start();t2.start();t3.start(); MyThread2 runnable = new MyThread2(); Thread t4 = new Thread(runnable); Thread t5 = new Thread(runnable); Thread t6 = new Thread(runnable); t4.start();t5.start();t6.start(); } } class MyThread extends Thread{ @Override public void run() { for (int i = 0; i <10 ; i++) { System.out.println(i+super.getName()); } } } class MyThread2 implements Runnable{ @Override public void run() { for (int i = 0; i <10 ; i++) { System.out.println(i+"="+Thread.currentThread().getName()); } } }
7.5线程不安全问题解决方案
双重校验(进行ticket>0判断和同步代码块)
package cn.tedu.thread; public class Thread1{ public static void main(String[] args) { Thread t1 = new TicketThread(); Thread t2 = new TicketThread(); Thread t3 = new TicketThread(); t1.start();t2.start();t3.start(); } } class TicketThread extends Thread { static int ticket = 100; @Override public void run() { while (true) { synchronized (TicketThread.class) { if (ticket > 0) { System.out.println(getName()+" "+ticket--); } else { break; } } } } }
8.反射
8.1获取字节码的三种方式
Class.ForName("类的全路径")
类名.class
对象.getClass
8.2获取构造方法
物料类
package cn.tedu.Test; public class Student { int age; int id; public void eat(int age){ System.out.println("吃"+age+"年了"); } public void play(int id){ System.out.println("我的id是"+id); } public Student() { } public Student(int age, int id) { this.age = age; this.id = id; } }
@Test public void getConstruct() throws Exception { Class<?> clazz = Class.forName("cn.tedu.Test.Student"); Constructor<?>[] cs = clazz.getConstructors(); for (Constructor c :cs){ System.out.println(c.getName());//cn.tedu.Test.Student Class[] pt = c.getParameterTypes(); System.out.println(Arrays.toString(pt));//[int, int] [] } }
8.3获取成员方法
成员方法包括自定义的还有集成超级父类Object的方法
@Test public void getMethod(){ Class<?> clazz = Student.class; Method[] methods = clazz.getMethods(); for(Method m:methods){ System.out.println(m.getName()); Class<?>[] pt = m.getParameterTypes(); System.out.println(Arrays.toString(pt)); } }
8.4获取成员变量
注意:获取成员变量要把变量设置成公共的,不然访问不到
@Test public void getField(){ Class<?> clazz = new Student().getClass(); Field[] fs = clazz.getFields(); for(Field f:fs){ System.out.println(f.getName());//age id System.out.println(f.getType().getName());//int int } }
8.5创建对象
@Test public void getObject() throws Exception { Class<?> clazz = Student.class; Object o = clazz.newInstance();//方式一调用无参构造 Student s =(Student)o;//先向上转型再向下转型 s.eat(18);//吃18年了 //方式二调用全参构造 Constructor<?> ct = clazz.getConstructor(int.class, int.class); Object o1 = ct.newInstance(18, 2021);//先向上转型再向下转型做 Student s2 =(Student)o1; System.out.println(s2.age);//18 }
8.6暴力反射
物料类
package cn.tedu.Test; public class Student { private String name; private int age; private void eat(){ System.out.println("吃"); } private void play(int a){ System.out.println("他几年"+a+"了"); } }
获取和设置私有属性
@Test public void getField() throws Exception { Class<?> clazz = Student.class; Field f = clazz.getDeclaredField("name");//获取属性 Object o = clazz.newInstance();//创建对象 o的name属性可能为张三,o1的name属性可能为李四,所以要创建对象 f.setAccessible(true);//暴力反射!!!设置私有可见 f.set(o,"张三");//指定是哪个对象 System.out.println(f.get(o));//张三 }
获取和设置私有方法
@Test public void getMethod() throws Exception { Class<?> clazz = Student.class; Method m = clazz.getDeclaredMethod("play", int.class);//获取方法 Object o = clazz.newInstance();//创建对象 o的play方法可能为18,o1的play方法可能为19,所以要创建对象 m.setAccessible(true);//暴力反射!!!设置私有可见 //通过反射技术invoke(对象,值) m.invoke(o, 18);//他今年18了 }
9.注解
9.1JDK自带注解
@Override :用来标识重写方法
9.2元注解
元注解使用来定义注解的注解
@Target 注解用在哪里:类上、方法上、属性上等等
ElementType.TYPE 应用于类的元素 ElementType.METHOD 应用于方法级 ElementType.FIELD 应用于字段或属性(成员变量) ElementType.ANNOTATION_TYPE 应用于注释类型 ElementType.CONSTRUCTOR 应用于构造函数 ElementType.LOCAL_VARIABLE 应用于局部变量 ElementType.PACKAGE 应用于包声明 ElementType.PARAMETER 应用于方法的参数
@Retention 注解的生命周期:源文件中、字节码文件中、运行中
SOURCE 在源文件中有效(即源文件保留)
CLASS 在class文件中有效(即class保留)
RUNTIME 在运行时有效(即运行时保留)
9.3自定义注解
定义格式:@interface 注解名字{ }
package cn.tedu.Test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; public class TestAnnotation { } @Target({ElementType.METHOD,ElementType.FIELD})//可以选多个 @Retention(RetentionPolicy.SOURCE)//只能选一个 @interface Test{ //int a() default 0;//普通变量 int value();//特殊变量 } class TestAnno{ //@Test(a=18)//int a()赋值不赋值都可以 String a; @Test(18) public void eat(){ System.out.println("吃"); } }
10.内部类
10.1成员内部类
被 private 修饰
package cn.tedu.Test; public class TestInner { public static void main(String[] args) { Outer out = new Outer(); out.getInner(); } } class Outer{ private class Inner{ public void eat(){ System.out.println("哈哈哈"); } } public void getInner(){ Inner in = new Inner(); in.eat();//哈哈哈 } }
被 static 修饰【可以被类名直接调用, 链式加载】
package cn.tedu.Test; public class TestInner { public static void main(String[] args) { new Outer.Inner().eat();//吃吃吃 Outer.Inner.play();//玩玩玩 } } class Outer{ static class Inner{ public void eat(){ System.out.println("吃吃吃"); } public static void play(){ System.out.println("玩玩玩"); } } }
10.2局部内部类
需要在方法里创建内部类对象并进行内部类功能调用
package cn.tedu.Test; public class TestInner { public static void main(String[] args) { Outer out = new Outer(); out.eat();//吃吃吃 } } class Outer{ public void eat(){ class Inner{ public void play(){ System.out.println("吃吃吃"); } } Inner inner = new Inner(); inner.play(); } }
10.3匿名内部类
强制要求重写抽象方法, 通常与匿名对象一起使用,匿名对象只能选择一个, 只能使用一次.eat() .drink()
package cn.tedu.Test; public class TestInner { public static void main(String[] args) { new Inner(){//匿名内部类 @Override public void eat() { System.out.println("吃"); } @Override public void play() { System.out.println("玩"); } }.eat();//吃 new Inner2(){ @Override public void drink() { System.out.println("喝喝喝"); } }.drink();//喝喝喝 } } interface Inner{ void eat(); void play(); } abstract class Inner2{ public void study(){ System.out.println("学习"); } public abstract void drink(); }
11.设计模式之单例
11.1饿汉式
直接创建对象
package cn.tedu.Test; public class Singleton1 { public static void main(String[] args) { MySingle.getSingle(); } } class MySingle{ private MySingle(){ System.out.println("哈哈哈哈"); } private static MySingle single = new MySingle(); public static MySingle getSingle(){ return single; } }
11.2懒汉式
先定义引用类型变量, 获取对象时没有再创建
懒汉式优化: 解决了多线程情况下的数据安全隐患
package cn.tedu.Test; public class Singleton2 { public static void main(String[] args) { MySingle.getSingle(); } } class MySingle{ private MySingle(){ System.out.println("哈哈哈哈"); } private static MySingle single; public static MySingle getSingle(){ synchronized (MySingle.class) { if (single == null) {//如果调用方法时single的值为null,说明之前没有创建过对象,这时才需要new对象, single = new MySingle();//没有对象时才创建对象,并赋值给single } return single;//如果single的值不为null,直接return single即可 } } }