目录

1、文档注释

2、String api

1、String 字符串

2、int length() 返回当前字符串的长度

3、int indexOf(String str):

4、String substring(int start,int end)

例:求域名

5、String trim() 去除当前字符串两侧的空白字符

6、 char charAt(int index) 获取当前字符串中指定位置处的字符

7、startsWith 和 endsWith:判断字符串是否是以给定的内容开始或结束的

8、toUpperCase() 和 toLowerCase()

9、ValueOf() 将其他类型转换为String

10、StringBuilder 修改字符串内容

11、StringBuffer

12、matches

13、split 将字符串分割

14、replaceAll 将字符串中内容替换为给定内容

3、Object 在java类继承结构中,java.lang.Object

1、toString()

2、equals 比较

4、Ingeter 基本类型

1、valueOf:使用包装类的静态方法

2、parseXXX(String str):将字符串解析为对应的基本类型

3、自动拆装箱:

5、File

java.io.File类

1、createNewFile() 创建新文件

2、delete() 文件的删除

创建多个文件

3、mkdir() 创建文件目录

4、listFiles 将当前File表示的目录中的所有子项返回,

重载listFile方法

5、Lambda 表达式

6、IO流

Java IO 输入与输出

2、文件的输入(FileInputStream)----文件流

3、文件的复制

4、向文件中写入文本数据----文件流---FileOutputStream

5、从文件中读取字符串

实现简易记事本工具

6、缓冲流:

缓冲输出流的缓冲区问题 flush():

7、对象流(实现对象序列化)

使用对象输入流(ObjectOutputStream)写入数据(序列化)

使用对象输出流(ObjectInputStream)写入数据(反序列化)

8、转化流 --- OutputStreamWriter 和 InputStreamReader

OutputStreamWriter

InputStreamReader

9、缓冲字符流----BufferedReader 和 BufferedWriter 和 缓冲字符输出流PrintWrite

在流连接中使用PW

--实现简易记事本工具

10、使用缓冲字符输入流按行读取文本数据

11、总结

7、异常处理机制

1、异常处理机制中的try-catch

2、异常处理机制在IO中的应用

3、JDK 7 之后推出了一个新的特性:AutoCloseabe

4、finally块

5、finally 常见面试题

8、多线程

1、多线程

2、线程的创建有两种方式:

2.1、第一种创建线程的方式的优点在于:

缺点有两个:

第二种创建方式

3、java中所有的代码都是靠线程运行的,main方法也不例外。运行mian方法的线程

4、线程提供了一组获取自身相关信息的方法

5、线程的优先级

void setPriority(int priority)

6、static void sleep(long ms) 该方法可以让运行这个方法的线程处于阻塞状态指定毫秒,超时后线程会自动

7、interrput()--该方法会抛出中断异常并打断阻塞状态

8、守护线程

9、join()方法---用来协调线程的同步运行

10、多线程并发安全问题----synchronized(同步锁)

多线程并发安全问题

10.2、同步块----synchronized(同步监视器对象){需要同步执行的代码片段}

10.3、静态方法上使用synchronized---那么该方法一定具有同步效果

10.4、互斥锁

10.5、死锁

9、网络编程---Socket

10、java集合---Collection

1、Collection-----List、Set

2、集合中与元素定义的方法相关的操作

1、boolean contains(Object o)---判断当前集合是否包含给定元素

2、boolean remove(Object o)---删除当前集合与equals比较为true的元素

3、boolean addAll(Collection c)--求并集

4、boolean containsAll(Collection c)--求是否为真子集

5、removeAll()---删除当前集合中与给定集合的共有元素

6、集合的遍历-----迭代器(Iterator)

增强型for循环----for(元素类型 变量名 :集合|数组){}

3、List集合

---ArrayList:内部使用数组实现,查询性能更好

---LinkedList:内部使用链表实现,增删性能更好

1、List提供了一对重载的add,remove方法

2、List subList(int start,int end)--获取当前集合中指定范围内的子集

3、集合转换为数组---toArray

4、数组转换为List集合---asList

5、变长参数

6、自然排序---sort

7、排序自定义类型元素---Comparable

8、队列---java.util.Queue

9、双端队列---java.util.Dequq

10、栈结构----方法(pop和push)

11、并发安全的集合

11、Map

V put(K k,V v)方法:

V get(K k)方法

2、Map的遍历

2.1)遍历所有的key

2.2)遍历每一组键值对

2.3)遍历所有的value

12、Java反射

1、java反射机制

反射是java的动态机制,它将原来写程序时进行的实例化操作以及操作属性,调用

方法从编码期间确定转移到在程序运行期间确定.这大大的提高了代码的灵活度.

但是反射带来了更多的系统开销和较慢的运行效率,因此仅在必要地方使用而不是过度的依赖反射

使用反射机制操作一个类时,第一步就是获取该类的类对象 Class的实例: JVM中每个被加载的类有且只有一个Class实例与之对应, 这个Class的实例称为这个类的"类对象".通过类对象我们可以 在程序运行期间获取到该类的一切信息(类名,有那些方法,属性,构造器等等) 从而进行对应的操作. 获取一个类的类对象有三种方式: 1:类名.class 例如: Class cls = String.class; Class cls = int.class; 这种方式比较直接,但是缺点是硬编码获取一个类的类对象,不灵活. 注:基本类型获取类对象的方式只有这一种

2:Class.forName(String className) 例如: Class cls = Class.forName("java.lang.String");

3:类加载器ClassLoader

2、使用反射进行实例化操作:

3、使用指定的构造器进行实例化操作

4、使用反射机制调用方法

5、使用反射机制访问类的私有成员

注意:此操作会破坏类的封装性.

6、调用私有方法

7、自动调用



1、文档注释

  • 档注释只在三个地方使用,分别是类上,方法上和常量上

  • 在类上使用时用来说明当前类的设计意图,功能等介绍

public class Demo {public static final String INFO = "你好";/***** @param name  给定的用户名* @return 返回的是一个字符串,内容为:问候用语+name*/public String sayHello(String name){return INFO+ name;}
}

2、String api

1、String 字符串

  • String 字符串

  • 字符串是不变的对象,即:字符串一旦创建内容不可改变,改变一定创建新对象,这是由于JAVA对字符串的优化导致的

  • 字符串一个优化为: 常量池

  • 常量池是在堆内存中开辟的一段空间,用于缓存所有使用字面量形式创建的字符串,当我们使用已有的字面量再次创建字符串时会重用对象来避免内存中堆积大量内容相同的字符串。

public class StringDemo {public static void main(String[] args) {String s1 = "123abc";String s2 = "123abc";   //重用s1对象System.out.println("s1:"+s1);System.out.println("s2:"+s2);System.out.println(s1==s2);String s3 = "123abc";System.out.println(s2==s3);/*** new 是强制操作,一定创建新对象* 面试题经常问:下面代码创建了几个字符串对象?* String s = new String("123abc");* 答:两个,第一个是参数 "123abc" 这个字面量产生的字符串对象*         第二个是 new String() 产生的字符串对象*/String s4 = new String("123abc");System.out.println("s4:"+s4);System.out.println(s2==s4);/*** 字符串判断 “相等” 绝大多数的情况都是判断字符串的内容是否相同* 因此实际开发中我们都是使用字符串提供的方法 equals 来判断两个字符串* 对象是否相同*/boolean equal = s2.equals(s4);System.out.println(equal);s1 = s1+"!";    //字符串是不变对象,修改内容会创建新对象System.out.println("s1:"+s1);System.out.println(s1==s2); //s1与s2的地址不同了/*** 编译器有一个特性:如果在编译期间可以确定一个计算表达式结果的时候编译器* 就是进行计算并将结果放在编译后的class文件中,这样以来JVM每次执行时就* 无需每次计算了*下面代码就会被编译器计算并改为:* String s5 = "123abc";    //JVM 运行时就会重用常量池对象*/String s5 = "123" + "abc";System.out.println("s5:"+s5);System.out.println(s2==s5);String s = "123";String s6 = s + "abc";System.out.println("s6:"+s6);System.out.println(s2 == s6);}
}

2、int length() 返回当前字符串的长度

public class LengthDemo {public static void main(String[] args) {String str = "我爱java";System.out.println("len:"+  str.length());}
}

3、int indexOf(String str):

检索给定字符串在当前字符串中的位置,如果给定的字符串在当前字符串中不存在则返回值为-1

public class IndexOfDemo {public static void main(String[] args) {String str = "thinking in java";//检索第一次出现“in”的位置int index = str.indexOf("in");System.out.println(index);//从小标8(第9个字符处开始)开始第一次出现“java”的位置index = str.indexOf("java",8);System.out.println(index);//检索最后一次出现“in” 的位置index = str.lastIndexOf("in");System.out.println(index);}
}

4、String substring(int start,int end)

  • String substring(int start,int end)

  • 截取当前字符串中指定范围内的字符串

  • 两个参数分别表示开始位置和结束位置

  • 注:在JAVA API 中有一个特点,通常使用两个数字表示范围时都是 “含头不含尾”的。

  • 即:包含开始位置的内容但是不包含结束位置的内容

    public class SubstringDemo {public static void main(String[] args) {String str = "www.tedu.cn";//截取从那个位置到那个位置的字符String s1 = str.substring(0,4);System.out.println(s1);//重载的方法从指定位置开始截取到字符串末尾s1 = str.substring(4);System.out.println(s1);}
    }

例:求域名

public class Test {public static void main(String[] args) {String n1 = getName("www.tedu.cn");String n2 = getName("http://doc.canglaoshi.org");String n3 = getName("www.tarena.com.cn");System.out.println(n1); //teduSystem.out.println(n2); //canglaoashiSystem.out.println(n3); //tarena}public static String getName(String line){int index1 = line.indexOf(".")+1;   //求第一个点的位置int index2 = line.indexOf(".",index1);  //求第二个点的位置String str = line.substring(index1,index2);return str;}
}

5、String trim() 去除当前字符串两侧的空白字符

public class TrimDemo {public static void main(String[] args) {String str = "  Hello   ";String stim = str.trim();System.out.println(str);System.out.println(stim);}
}

6、 char charAt(int index) 获取当前字符串中指定位置处的字符

public class CharAtDemo {public static void main(String[] args) {String line = "thinking in java";char c = line.charAt(9);System.out.println(c);//检索回文String str = "上海自来水来自海上";for (int i=0;i<str.length()/2;i++){char c1 = str.charAt(i);char c2 = str.charAt(str.length()-1-i);/*if (c1 != c2){System.out.println("不是回文!");return;}*/if(c1!=c2){System.out.print("不");break;}}System.out.println("是回文!");}
}

7、startsWith 和 endsWith:判断字符串是否是以给定的内容开始或结束的

  • boolean startsWith(String str)

  • boolean endsWith(String str)

  • 判断字符串是否是以给定的内容开始或结束的

public class StartsWithDemo {public static void main(String[] args) {String line = "www.tedu.cn";boolean starts = line.startsWith("www.");System.out.println("starts: "+starts);boolean ends = line.endsWith(".com");System.out.println("ends: "+ends);}
}

8、toUpperCase() 和 toLowerCase()

  • String toUpperCase()

  • String toLowerCase()

  • 将当前字符串中的英文部分转换为全大写或全小写

public class ToUpperCaseDemo {public static void main(String[] args) {String str = "My name is Hero   ";System.out.println(str.toUpperCase());System.out.println(str.toLowerCase());}
}

9、ValueOf() 将其他类型转换为String

  • String 提供一组重载的静态的 valueOf方法,作用是将其他类型转换为String

比较常见的是将基本类型转换为String

public class ValueOfDemo {public static void main(String[] args) {int a = 123;String s1 = String.valueOf(a);System.out.println(s1);double d = 123.123;String s2 = String.valueOf(d);System.out.println(s2);}
}

10、StringBuilder 修改字符串内容

  • String 的优化导致字符串不适合频繁修改(开销大,性能低)

  • JAVA提供了一个专门用于修改字符串内容的API:StringBuilder

  • 其内部维护一个可变的char数组,修改性能好,开销小,并且由于是专门修改字符串的API

  • 对此提供了一套修改字符串的方法:增、删、改、查

    • append :追加内容

    • replace:替换字符串内容

    • delete :删除当前字符串的部分内容

    • insert : 将给定内容插入到指定位置

public class StringBuilderDemo {public static void main(String[] args) {String line = " Study good java";/*** StringBuilder 常见的构造方法* StringBuilder() 无参构造器创建的StringBuilder内部表示空字符串* StringBuilder(String str) 将给定字符串内容复制一份到 StringBuilder*///StringBuilder builder1 = new StringBuilder();   //空字符串 “”StringBuilder builder = new StringBuilder(line);/*** Study good java* Study good java,Working nice* append:追加内容*/builder.append(",Working nice");System.out.println(builder);/*** Study good java,Working nice* Study good java,Change world!* replace(): 替换字符串部分内容*/builder.replace(17,29,"Change world!");System.out.println(builder);/*** Study good java,Change world!* ,Change world!* delete : 删除当前字符串中的部分内容*/builder.delete(0,16 );System.out.println(builder);/*** ,Change world!* Live,Change world!* insert : 将给定内容插入到指定位置*/builder.insert(0,"Live");System.out.println(builder);}
}

11、StringBuffer

  • StringBuilder与StringBuffer的功能是完全一样的。

  • StringBuffer出现在JDK1.0,而StringBuilder出现在JDK1.5

  • 区别在与:StringBuilder不是线程安全的,而StringBuffer是线程安全的

public class StringBufferDemo {public static void main(String[] args) {String line = " Study good java";/*** StringBuilder 常见的构造方法* StringBuilder() 无参构造器创建的StringBuilder内部表示空字符串* StringBuilder(String str) 将给定字符串内容复制一份到 StringBuilder*///StringBuilder builder1 = new StringBuilder();   //空字符串 “”StringBuffer builder = new StringBuffer(line);/*** Study good java* Study good java,Working nice* append:追加内容*//*** StringBuilder与StringBuffer的功能是完全一样的。* StringBuffer出现在JDK1.0,而StringBuilder出现在JDK1.5* 区别在与:StringBuilder不是线程安全的,而StringBuffer是线程安全的**/builder.append(",Working nice");System.out.println(builder);/*** Study good java,Working nice* Study good java,Change world!* replace(): 替换字符串部分内容*/builder.replace(17,29,"Change world!");System.out.println(builder);/*** Study good java,Change world!* ,Change world!* delete : 删除当前字符串中的部分内容*/builder.delete(0,16 );System.out.println(builder);/*** ,Change world!* Live,Change world!* insert : 将给定内容插入到指定位置*/builder.insert(0,"Live");System.out.println(builder);builder.reverse();System.out.println(builder);String str = builder.toString();System.out.println(str);}
}

12、matches

String 支持正则表达式的方法一:

  • boolean matches(String regex)

  • 使用给定的正则表达式验证当前字符串的内容是否符合格式要求

public class MatchesDemo {public static void main(String[] args) {String email = "wwsd@edu.com";/*** 邮箱的正则表达式:*  [a-zA-Z0-9_]+@[a-zA-Z0-9]+(\.[a-zA-Z]+)+*/String regex = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";if(email.matches(regex)){System.out.println("true");}else {System.out.println("false");}}
}

13、split 将字符串分割

String[] spllit(String regex)

  • 将当前字符串按照满足正则表达式的部分进行拆除。将部分的所有部分以一个数组的形式返回

  • 拆分时如果连续遇到两次可拆分项,那么中间会拆除一个空字符串

    • 如果字符串中最开始就遇到了可拆分项,则一开始就会拆出一个空字符串

    • 如果是在字符串末尾连续出现可拆分项,则所有拆分出来的空字符串都会被忽略

public class SplitDemo {public static void main(String[] args) {String line = "abc123de456fc4513";//将字符串按照数字部分拆分每个字母部分String[] str = line.split("[0-9]+");System.out.println(Arrays.toString(str));String[] st = line.split("[a-zA-Z]+");System.out.println(Arrays.toString(st));line = "abc.de.fgl";str = line.split("\\.");System.out.println(Arrays.toString(str));/*** 拆分时如果连续遇到两次可拆分项,那么中间会拆除一个空字符串:""* 如果字符串中最开始就遇到了可拆分项,则一开始就会拆出一个空字符串* 如果是在字符串末尾连续出现可拆分项,则所有拆分出来的空字符串都会被忽略*/line = "abc,,de,fgl";str = line.split(",");System.out.println(str.length);System.out.println(Arrays.toString(str));}
}

14、replaceAll 将字符串中内容替换为给定内容

  • String replaceAll(String regex,String str)

  • 将当前字符串中满足正则表达式的部分替换为给定内容

public class ReplaceAllDemo {public static void main(String[] args) {String line = "abc123def456ghi";//将当前字符串中的数字部分替换为“#NUMBER#”line = line.replaceAll("[0-9]+","#NUMBER#");System.out.println(line);}
}

3、Object 在java类继承结构中,java.lang.Object

1、toString()

  • 我们经常使用System.out.println() 输出一个对象的内容

  • 实际上该方法会将传入的对象调用它的toString方法(Object提供的方法)

  • 将其转化为一个字符串后,将该字符串内输出到控制台

  • Object 提供的toString方法将返回的字符串格式:类名@地址

  • 实际开发中帮助不大,我们通常输出希望看到的是该对象保存的内容,因此我们

  • 可以妥善的重写toString方法,使得输出时更有意义

  • 在字符串链接操作中,非字符串类型在拼接时也是调用其toString方法先将其

  • 转换为String后进行的链接操作。

public class Demo extends Object{public static void main(String[] args) {Point point = new Point(10,20);/*** 我们经常使用System.out.println() 输出一个对象的内容* 实际上该方法会将传入的对象调用它的toString方法(Object提供的方法)* 将其转化为一个字符串后,将该字符串内输出到控制台* Object 提供的toString方法将返回的字符串格式:类名@地址* 实际开发中帮助不大,我们通常输出希望看到的是该对象保存的内容,因此我们* 可以妥善的重写toString方法,使得输出时更有意义*/System.out.println(point);/*** 在字符串链接操作中,非字符串类型在拼接时也是调用其toString方法先将其* 转换为String后进行的链接操作。*/String line = "point:" + point;System.out.println(line);}
}public class Point {private int x;private int y;public Point(int x, int y) {this.x = x;this.y = y;}public int getX() {return x;}public int getY() {return y;}@Overridepublic String toString() {return x + "," + y;}
}

2、equals 比较

  • equals 方法并不关心是否为同一个对象,而是比较两个对象的内容是否相同

  • 但是如果子类不重写Object中的 equals 方法,则 equals 方法并没有实际意义,

  • 原因是 Object提供的equals内部就是使用 == 比较的

public class Demo extends Object{public static void main(String[] args) {Point p2 = new Point(10,20);//==是值比较,对于引用类型变量而言存的是地址,因此 == 是比较是否为同一个对象System.out.println(point==p2);  //false/*** equals 方法并不关心是否为同一个对象,而是比较两个对象的内容是否相同* 但是如果子类不重写Object中的 equals 方法,则 equals 方法并没有实际意义,* 原因是 Object提供的equals内部就是使用 == 比较的*/System.out.println(p2.equals(point));   //true}}public class Point {private int x;private int y;public Point(int x, int y) {this.x = x;this.y = y;}public int getX() {return x;}public int getY() {return y;}@Overridepublic String toString() {return x + "," + y;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Point point = (Point) o;return x == point.x &&y == point.y;}@Overridepublic int hashCode() {return Objects.hash(x, y);}
}

4、Ingeter 基本类型

1、valueOf:使用包装类的静态方法

  • 基本类型-->包装类

    Integer i1 = Integer.valueOf(123);

  • 包装类-->基本类型

    int d = i1.intValue();

 public class IntegerDemo {public static void main(String[] args) {//基本类型与对应的包装类之间的转换//基本类型->包装类   使用包装类的静态方法:valueOfInteger i1 = Integer.valueOf(123);Integer i2 = Integer.valueOf(123);System.out.println(i1==i2);System.out.println(i1.equals(i2));//包装类->基本类型int d = i1.intValue();System.out.println(d);double dou = i1.doubleValue();System.out.println(dou);}
}

2、parseXXX(String str):将字符串解析为对应的基本类型

  • String line = "123";
  • int d = Integer.parseInt(line);
/*** 包装类常见的一些功能*/
public class IntegerDemo2 {public static void main(String[] args) {/*** 数字类型的包装类都支持两个常量:MAX_VALUE 和 MIN_VALUE* 用于表示对应的基本类型的取值范围*/int imax = Integer.MAX_VALUE;System.out.println(imax);int imin = Integer.MIN_VALUE;System.out.println(imin);long lmax = Long.MAX_VALUE;long lmin = Long.MIN_VALUE;System.out.println(lmax);System.out.println(lmin);float fmax = Float.MAX_VALUE;float fmin = Float.MIN_VALUE;System.out.println(fmax);System.out.println(fmin);/*包装类提供类静态方法:parseXXX(String str)作用是将字符串解析为对应的基本类型,前提是该字符串正确表示了基本类型可以保存的值,否则会抛出异常:NumberFormatException*/String line = "123";int d = Integer.parseInt(line);System.out.println(line);double dou = Double.parseDouble(line);System.out.println(line);}
}

3、自动拆装箱:

  • 当编译器在编译代码时发现有

  • 基本类型和引用类型之间相互赋值的情况时,会补充代码完成他们直接的转换操作

/*** 自动拆装箱* JDK1.5之后java推出的特性,该特性是编译器认可的,当编译器在编译代码时发现有* 基本类型和引用类型之间相互赋值的情况时,会补充代码完成他们直接的转换操作*/
public class IntegerDemo3 {public static void main(String[] args) {//触发了自动拆箱特性,代码会被改为:int d = new Integer(123).inValue();int d = new Integer(123);//触发了自动装箱特性,代码会被改为:Integer i = Integer.valueOf(123);Integer i = 123;}
}

5、File

java.io.File类

  • 该类的每一个实例用于表示硬盘上的一个文件或目录(实际表示的是一个抽象路径)

  • 操作系统中有一个子系统称为:文件系统,是用来管理硬盘的。它将数据保存在文件中,并使用

  • 目录来归类,File就是用来访问文件系统中的文件和目录的

  • File可以:

    • 1、访问其表示的文件或目录的属性信息,比如:名字、大小、修改时间等

    • 2、可以创建或删除文件和目录

    • 3、可以访问一个目录中的子项

    • 但是不能访问文件数据(java有其他的api可以做其他的事)

  • 实际开发中,我们使用路径时都是使用的相对路径,它有更好的跨平台性

    • "./" 称为当前目录,当前目录是哪里要视当前程序的运行环境而定,如果是在

    • idea中执行我们的程序,那么当前目录就是当前程序所在的项目目录

public class FileDemo {public static void main(String[] args) {/*** 实际开发中,我们使用路径时都是使用的相对路径,它有更好的跨平台性* "./" 称为当前目录,当前目录是哪里要视当前程序的运行环境而定,如果是在* idea中执行我们的程序,那么当前目录就是当前程序所在的项目目录*/File file = new File("./Test01/test.txt");System.out.println(file.getName());//返回文件的绝对路径System.out.println(file.getAbsolutePath());//返回文件的大小,单位是字节System.out.println("大小:"+file.length());//可读,可写boolean cr = file.canRead();boolean cw = file.canWrite();boolean hid = file.isHidden();System.out.println("可读:"+cr);System.out.println("可写:"+cw);System.out.println("是否隐藏:"+hid);}
}

1、createNewFile() 创建新文件

public class newFileDemo {public static void main(String[] args) {//在当前目录下新建文件demo.txtFile file = new File("./demo.txt");/*** boolean exists()* 判断当前File表示的文件是否存在*/try {if (!file.exists()){file.createNewFile();System.out.println("Successful...");}}catch (Exception e){e.printStackTrace();}}
}

2、delete() 文件的删除

public class DeleteFileDemo {public static void main(String[] args) {//将当前项目下的demo.txt文件删除File file = new File("demo.txt");if (file.exists()){file.delete();System.out.println("Successful...");}}
}

创建多个文件

/*** 在当前目录下创建10个文件。* 分别是test1.txt --- test10.txt*/
public class Test {public static void main(String[] args) throws IOException {for (int i=1;i<=10;i++){File file = new File("test"+i+".txt");if (!file.exists()){file.createNewFile();}}}
}

3、mkdir() 创建文件目录

  • mkdir 方法要求创建的目录所在的目录必须存在

  • mkdies 方法则是会自动将所有不存在的父目录一同创建出来

/*** 创建目录 mkdir()*/
public class MKDirDemo {public static void main(String[] args) {//在当前项目目录下创建一个目录文件denoFile file = new File("./demo");if (!file.exists()){file.mkdirs();System.out.println("Successfull..");}}
}

4、listFiles 将当前File表示的目录中的所有子项返回,

  • File[] listFiles()

  • 将当前File表示的目录中的所有子项返回,

  • 每个子项(文件或目录)都以一个File对象形式存入数组

  • 并最终将数组返回

public class ListFileDemo {public static void main(String[] args) {/*** File[] listFiles()* 将当前File表示的目录中的所有子项返回,* 每个子项(文件或目录)都以一个File对象形式存入数组* 并最终将数组返回*/File dir = new File("./Test01");File[] subs = dir.listFiles();System.out.println(subs.length);for (int i=0;i<subs.length;i++){System.out.println(subs[i].getName());}}
}

重载listFile方法

  • File[] listFiles(FileFilter filter)

  • 该方法要求我们传入一个文件过滤器,然后仅该目录中满足这个过滤器要求的

  • 子项返回

public class ListFilesDemo2 {public static void main(String[] args) {//获取当前目录下所有的文本文件(.txt文件)File dir = new File(".");if (dir.isDirectory()){
//            MyFilter filter = new MyFilter();//匿名内部类FileFilter filter = new FileFilter() {@Overridepublic boolean accept(File file) {String name = file.getName();System.out.println("正在过滤: "+name);return name.endsWith(".txt");}};File[] subs = dir.listFiles(filter);System.out.println(subs.length);for (int i=0;i<subs.length;i++){System.out.println(subs[i].getName());}}}
}

5、Lambda 表达式

JDK8之后推出了一个新的特性:Lamdba表达式

  • lambda 可以以更精简的语法创建匿名内部类

  • 语法:

  • (参数列表)->{

    方法体

  • }
  • 注:使用 lambda 创建匿名内部类时所实现的接口只能有一个抽象方法

/*** JDK8之后推出了一个新的特性:Lamdba表达式* lambda 可以以更精简的语法创建匿名内部类* 语法:* (参数列表)->{*     方法体* }* 注:使用 lambda 创建匿名内部类时所实现的接口只能有一个抽象方法**/
public class LamdbaDemo {public static void main(String[] args) {//匿名内部类
//        FileFilter file = new FileFilter() {
//            @Override
//            public boolean accept(File file) {
//                return file.getName().endsWith(".txt");
//            }
//        };//lambda 表达式FileFilter filter =  (File file)->{return file.getName().endsWith(".txt");};FileFilter filter2 = (file)->{return file.getName().endsWith(".txt");};//如果方法中只有一句代码,则方法{}可以忽略不写,// 如果这句话有return,怎return也必须忽略不写FileFilter filter3 =(file)->file.getName().endsWith(".txt");//如果只有一个参数,那么参数的()可以忽略不写FileFilter filter4 =file->file.getName().endsWith(".txt");File dir = new File(".");File[] subs = dir.listFiles(f->f.getName().endsWith(".txt"));for (int i=0;i<subs.length;i++){System.out.println(subs[i].getName());}}}
/*** 使用lambda表达式创建的文件过滤器,获取当前目录下所有名字中含有s的子项*/
public class Text {public static void main(String[] args) {File dir = new File(".");File[] subs = dir.listFiles(//f->f.getName().indexOf("s")>=0f->f.getName().contains("s"));for (int i=0;i<subs.length;i++){System.out.println(subs[i].getName());}}
}

6、IO流

Java IO 输入与输出

  • java的IO是用来完成我们的程序与外界交换数据的方式,并且将输入与输出

    • 按照方向分为读与写操作。

    • 其中输入负责读取,是外界到程序的方向

    • 输出负责写,是程序到外界的方向

  • java中定义的输入流与输出流可以看做事连接程序与外界设备的”管道“,而管道中向着同一方向顺序移动字节数据

  • 实际开发中,读写不同的设备我们会使用专门的输入与输出流,好比我们读写文件就可以使用文件输入与输出流

  • java定义了输入流与输出流的超类,用于规范输入与输出的读写操作

  • java.io.InputStream 是输入流的超类,所有字节输入流都继承自它。

  • java.io.OutInputStream 是输出流的超类,所有字节的输出流都继承自它。

  • JAVA将流分为两类:节点流和处理流

    • 节点流:也称为低级流,是真实连接程序与另一端的”管道“,负责实际读写数据的流,IO操作一定是基于某个节点流基础上进行的

    • 处理流:也称为高级流,它不能独立存在,必须连接在其他流上,目的是当数据流经当前流事对其进行某些加工操作,使得我们读写数据得以简化

    • 实际开发中我们经常会串联一组高级流到某个低级流上,读写数据以流水线式的加工处理,这也称为”流的连接“

  • 文件流(是一对低级流)

    • java.io.FileInputStream和FileOutStream

    • 它们是用来读写文件数据的流,是连接程序与文件之间的管道

  • void write(int d) 向文件中写入一个字节,写入的内容是给定的int值对应的2进制的低8位

public class FOSDemo {public static void main(String[] args) throws IOException {//向当前目录下的文件fos.dat中写入字节/*文件输出流常见的构造方法FileOutputStream(String path)FileOutputStream(File file)*/File file = new File("fos.dat");FileOutputStream fos = new FileOutputStream(file);// FileOutputStream fos = new FileOutputStream("fos.dat");fos.write(1);/*void write(int d)向文件中写入一个字节,写入的内容是给定的int值对应的2进制的低8位for.write(1)int 型的1对应的2进制:         vvvvvvvv00000000  00000000  00000000 00000001fos.dat 文件中:00000001*/String str = "Today is sunny,The weather nice";byte[] bytes = str.getBytes();fos.write(bytes);System.out.println("Successful...");FileInputStream fis = new FileInputStream(file);fis.read();fos.close();    //流使用完毕后必须关闭}
}

2、文件的输入(FileInputStream)----文件流

文件输入流,用于从文件中读取自己数据

  • int read() 从文件中读取一个字节,返回值的int值的2进制最低八位就是读取 到的字节数据,如果返回的是int值为-1则表示读取到了文件末尾

  • fos.dat文件中: 00000001 00000010 ^^^^^^^^ 返回值d:00000000 00000000 00000000 00000001

  • fos.dat 文件中: 00000001 00000010 文件末尾 ^^^^^^^^ 返回值d: 11111111 1111111 11111111 11111111

package IO;import java.io.*;/*** 文件输入流,用于从文件中读取字节数据*/
public class FISDemo {public static void main(String[] args) throws IOException {File file = new File("fos.dat");FileInputStream fis = new FileInputStream(file);/*int read()从文件中读取一个字节,返回值的int值的2进制最低八位就是读取到的字节数据,如果返回的是int值为-1则表示读取到了文件末尾fos.dat文件中:00000001 00000010^^^^^^^^返回值d:00000000 00000000 00000000 00000001fos.dat 文件中:00000001  00000010 文件末尾^^^^^^^^返回值d: 11111111 1111111 11111111 11111111*/int d = fis.read();System.out.println(d);Reader reader = new InputStreamReader(fis);int temp;while((temp = reader.read())!=-1){if (((char)temp)!='\r') {System.out.print((char)temp);}}reader.close();}
}

3、文件的复制

原文件数据:
11001010 00001111 11110000 10101010 10101010 文件末尾
^^^^^^^^d = fis.read();
d:11111111 11111111 11111111 11001010^^^^^^^^fos.write(d);
复制文件:
11001010
/*** 文件复制*/
public class CopyDemo {public static void main(String[] args) throws IOException {FileInputStream fis= new FileInputStream("img.png");FileOutputStream fos= new FileOutputStream("img_cp.png");  //复制图片的名字int d;  //记录每次读取的字节/*原文件数据:11001010 00001111 11110000 10101010 10101010 文件末尾^^^^^^^^d = fis.read();d:11111111 11111111 11111111 11001010^^^^^^^^fos.write(d);复制文件:11001010*/long start = System.currentTimeMillis();    //获取毫秒值while ((d = fis.read()) != -1){fos.write(d);}long end = System.currentTimeMillis();System.out.println("所需时间:"+(end-start)+"ms");System.out.println("复制完毕!");fis.close();fos.close();}
}

通过提高每次读写的数据量,减少实际读写的次数可以提高读写效率

  • 一次读写一个字节的形式是一种随即读写形式

  • 而一次读写一组字节的形式是块读写形式

  • 块读:

  • int read(byte[] data) 一次性读取给定的字节数组总长度的字节量并存入该数组中 返回值实际读取到的字节量,若返回值为-1,则表示读取到了末尾

  • void write(byte[] data) 一次性将给定的自己数组中所以字节写出

void write(byte[] data,int offset,int len) 将给定的字节数组从下标offset处开始的连续len个字节一次性写出

package IO;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*** 通过提高每次读写的数据量,减少实际读写的次数可以提高读写效率* 一次读写一个字节的形式是一种随即读写形式* 而一次读写一组字节的形式是块读写形式*/
public class CopyDemo2 {public static void main(String[] args) throws IOException {FileInputStream fis= new FileInputStream("img.png");FileOutputStream fos= new FileOutputStream("img_cpoy.png");  //复制图片的名字/*块读:int read(byte[] data)一次性读取给定的字节数组总长度的字节量并存入该数组中返回值实际读取到的字节量,若返回值为-1,则表示读取到了末尾void write(byte[] data)一次性将给定的自己数组中所以字节写出void write(byte[] data,int offset,int len)将给定的字节数组从下标offset处开始的连续len个字节一次性写出原文件数据:11001010 00001111 11110000 10101010 10101010 文件末尾^^^^^^^^ ^^^^^^^^ ^^^^^^^^*//*原文件数据:11001010 00001111 11110000 10101010 10101010 文件末尾^^^^^^^^ ^^^^^^^^ ^^^^^^^^d = fis.read();d:11111111 11111111 11111111 11001010^^^^^^^^fos.write(d);复制文件:11001010*/byte[] data = new byte[1024*10];    //10kbint len;  //每次读取的字节量long start = System.currentTimeMillis();    //获取毫秒值while ((len = fis.read(data)) != -1){fos.write(data,0,len);}long end = System.currentTimeMillis();    //获取毫秒值System.out.println("复制完毕!耗时: "+(end-start)+"ms");fis.close();fos.close();}
}

4、向文件中写入文本数据----文件流---FileOutputStream

  • String提供了将字符串转换为一组字节的方法: byte[] getBytes(String csn) 按照指定的字符集将当前字符串转化为一组字符.字符集的名字 不区分大小写.

  • 文件默认的创建方式称为覆盖模式 即:如果指定的文件存在,则创建文件流时会将该文件原有的数据 全部抹除。然后将写入的数据全部保存到文件中

  • 文件流支持一个重载的构造器,允许我们在传入一个boolean值 作为参数,如果这个值为true,则当前文件流追加默认,即: 创建文件流是若指定的文件存在,则原数据保留,新写入的数据都 会顺序追加到文件末尾 FileOutputStream(String path,boolean append) FileOutputStream(File file,boolean append)

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 向文件中写入文本数据*/
public class WriteStringDemo {public static void main(String[] args) throws IOException {/*文件默认的创建方式称为覆盖模式即:如果指定的文件存在,则创建文件流时会将该文件原有的数据全部抹除。然后将写入的数据全部保存到文件中*/FileOutputStream fos= new FileOutputStream("fos.txt",true);//String line = "跨海大打开--覅扫街--到家了?姐撒[]点几分就撒开";String line = "想你的夜.";/*String提供了将字符串转换为一组字节的方法:byte[] getBytes(String csn)按照指定的字符集将当前字符串转化为一组字符.字符集的名字不区分大小写.*/byte[] data = line.getBytes(StandardCharsets.UTF_8);fos.write(data);System.out.println("写出完毕!");}
}

5、从文件中读取字符串

import java.io.FileInputStream;
import java.io.IOException;/*** 从文件中读取字符串*/
public class ReadStringDemo {public static void main(String[] args) throws IOException {FileInputStream fis= new FileInputStream("fos.txt");byte[] data = new byte[1000];int len = fis.read(data);System.out.println("实际读取到的字节数: "+len);String line = new String(data,0,len,"UTF-8");//0,len 取长度为0-字符长度len的字符System.out.println(line);fis.close();}
}

实现简易记事本工具

  • 程序启动后再控制台输入的每一行字符串第一能顺序写文件note.txt中,

  • 当单独输入exit时程序退出

package IO;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** 实现简易记事本工具* 程序启动后再控制台输入的每一行字符串第一能顺序写文件note.txt中,* 当单独输入exit时程序退出*/
public class Test {public static void main(String[] args) throws IOException {/*File file = new File("note.txt");while(true){Scanner cin = new Scanner(System.in);String str = cin.nextLine();if ("exit".equals(str)){break;}str += "\r\n";FileOutputStream fos = new FileOutputStream(file,true);byte[] data = str.getBytes(StandardCharsets.UTF_8);fos.write(data);}fos.close();FileInputStream fis = new FileInputStream(file);byte[] data2 = new byte[1000];int len = fis.read(data2);String line = new String(data2,0,len,"UTF-8");System.out.println("note.txt内容有: "+line);fis.close();*/FileOutputStream fos= new FileOutputStream("note.txt");Scanner cin = new Scanner(System.in);System.out.println("请开始输入内容,单独输入exit时退出");while (true){String line = cin.nextLine();if ("exit".equals(line)){break;}line += "\r\n";byte[] bytes = line.getBytes(StandardCharsets.UTF_8);fos.write(bytes);}System.out.println("结束");fos.close();FileInputStream fis = new FileInputStream("note.txt");byte[] data = new byte[1000];int len = fis.read(data);String line = new String(data,0,len,"UTF-8");System.out.println("内容为: "+line);fis.close();}
}

6、缓冲流:

  • java.io.BufferedInputStream 和 BufferedOutputStream

  • 缓冲流是一对高级流,在流连接中的作用是提高读写字节数据的效率

/***使用缓冲流完成文件的复制操作** 缓冲流:* java.io.BufferedInputStream 和 BufferedOutputStream* 缓冲流是一对高级流,在流连接中的作用是提高读写字节数据的效率*/
public class CopyDemo3 {public static void main(String[] args) throws IOException {FileInputStream fis= new FileInputStream("abb.png");BufferedInputStream bis= new BufferedInputStream(fis);FileOutputStream fos= new FileOutputStream("abb_cp.png");BufferedOutputStream bos= new BufferedOutputStream(fos);int d;long start = System.currentTimeMillis();while ((d = bis.read())!=-1){bos.write(d);}long end = System.currentTimeMillis();System.out.println("复制完毕!时间为: "+(end-start)+"ms");bis.close();bos.close();}
}

缓冲输出流的缓冲区问题 flush():

  • void flush()方法
  • 该方法是所以输出流共有的方法,定义在超类上,
  • 作用是将缓冲流 的缓冲区中已经缓存的数据一次性写出
package IO;import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 缓冲输出流的缓冲区问题*/
public class BOS_flushDemo {public static void main(String[] args) throws IOException {FileOutputStream fos= new FileOutputStream("bos.txt");BufferedOutputStream bos= new BufferedOutputStream(fos);String line = "夜空中最亮的星。";byte[] bytes = line.getBytes(StandardCharsets.UTF_8);bos.write(bytes);/*void flush()方法该方法是所以输出流共有的方法,定义在超类上,作用是将缓冲流的缓冲区中已经缓存的数据一次性写出*/bos.flush();System.out.println("写出完毕!");bos.close();}
}

7、对象流(实现对象序列化)

  • 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化的。

  • 对象序列化:将对象按照其结构转换为一组字节

  • 反序列化:将一组字节还原为java对象

  • transient 关键字 当一个对象在序列化时,忽略所有被transient修饰的属性, 忽略不必要的属性可以达到对象序列化的“瘦身”工作,减少开销

使用对象输入流(ObjectOutputStream)写入数据(序列化)

package IO;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;/*** 对象流* 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化的。* 对象序列化:将对象按照其结构转换为一组字节* 反序列化:将一组字节还原为java对象*/
public class OOSDemo {public static void main(String[] args) throws IOException {//将一个Person对象写入文件Person.obj中String name = "苍老师";int age = 36;String gender = "女";String[] otherInfo = {"电影演员","来自岛国","启蒙老师","爱好写毛笔字"};Person p = new Person(name,age,gender,otherInfo);System.out.println(p);FileOutputStream fos =new FileOutputStream("person.obj");ObjectOutputStream oos= new ObjectOutputStream(fos);/*对象输出流提供的方法:void writeObject(Object obj)该方法会将给定的对象按照其结构转换为一组字节,但是要求该对象所属的类型必须实现可序列化接口,否则会抛出异常:java.io.NotSerializableException*/oos.writeObject(p);System.out.println("写出完毕!");oos.close();}
}
package IO;import java.io.Serializable;
import java.util.Arrays;/*** 使用当前类测试对象序列化*/
public class Person implements Serializable {private String name;   //名字private int age;    //年龄private String gender;  //性别private transient String[] otherInfo; //其他信息/*transient 关键字当一个对象在序列化时,忽略所有被transient修饰的属性,忽略不必要的属性可以达到对象序列化的“瘦身”工作,减少开销*/public Person(String name, int age, String gender, String[] otherInfo) {this.name = name;this.age = age;this.gender = gender;this.otherInfo = otherInfo;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String[] getOtherInfo() {return otherInfo;}public void setOtherInfo(String[] otherInfo) {this.otherInfo = otherInfo;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +  ", otherInfo=" + Arrays.toString(otherInfo) +'}';}
}

使用对象输出流(ObjectInputStream)写入数据(反序列化)

package IO;import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;/*** 使用对象输入流反序列对象*/
public class OISDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {FileInputStream fis= new FileInputStream("person.obj");ObjectInputStream ois= new ObjectInputStream(fis);Person p = (Person)ois.readObject();System.out.println(p);ois.close();}
}

8、转化流 --- OutputStreamWriter 和 InputStreamReader

java IO 将流按照读写数据的单位划分为:字节流与字符流

  • java.io.InputStream和OutputStream时所有字节流的超类,比如

    文件流,缓冲字节流,对象流都继承自上述的两个超类,读写单位最小都是以字节

    为单位进行的。 *

  • java.io.Reader和 Writer 都是所以字符流的超类,读写单位最小的是以char(字符)

    为单位进行的

    • 字符流底层本质还是要进行字符与字节的转换(因为计算机底层只有2进制)

    • 但是字符流为我们提供的便利是可以让我们直接读写文本数据

  • 因此注意:字符流仅适合读写文本数据 *

  • 转换流

    • 转换流是一对高级流,实际开发中我们不能直接操作这对流,但是在流连接中他们

      是非常重要的一环,负责衔接其他字符流与下面的字节流,并进行着字符与字节

      的转换工作

  • java.io.InputStreamReader 和 OutputStreamWriter

    • 他们是唯一可以连接在字节流上的字符流,其他字符流通过连接上它就可以与

      底下的字节流连接使用了,他们之所以称为转化流就相当于起到了“转换器”的

      作用

OutputStreamWriter

package IO;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;/*** java IO 将流按照读写数据的单位划分为:字节流与字符流* java.io.InputStream和OutputStream时所有字节流的超类,比如* 文件流,缓冲字节流,对象流都继承自上述的两个超类,读写单位最小都是以字节* 为单位进行的。** java.io.Reader和 Writer 都是所以字符流的超类,读写单位最小的是以char(字符)* 为单位进行的* 字符流底层本质还是要进行字符与字节的转换(因为计算机底层只有2进制)* 但是字符流为我们提供的便利是可以让我们直接读写文本数据* 因此注意:字符流仅适合读写文本数据** 转换流* 转换流是一对高级流,实际开发中我们不能直接操作这对流,但是在流连接中他们* 是非常重要的一环,负责衔接其他字符流与下面的字节流,并进行着字符与字节* 的转换工作*/
public class OSWDemo {public static void main(String[] args) throws IOException {FileOutputStream fos= new FileOutputStream("osw.txt");OutputStreamWriter osw= new OutputStreamWriter(fos,"UTF-8");
//        String line = "我可以接受你的所有小脾气";osw.write("我可以接受你的所有小脾气.kkkkk");osw.write("我可以带你去吃很多的好东西.lllll");System.out.println("写出完毕");osw.close();}
}

InputStreamReader

package IO;import java.io.*;/*** 使用转换流读取文本数据*/
public class ISRDemo {public static void main(String[] args) throws IOException {FileInputStream fis= new FileInputStream("osw.txt");InputStreamReader isr= new InputStreamReader(fis,"UTF-8");/*字符流的read()int read()读取一个字符,是以int型返回,因此该int值的2进制“低16位”有效如果返回的int值是-1则表示读取到了末尾*/int d;while ((d=isr.read())!=-1) {System.out.print((char) d);}}
}

9、缓冲字符流----BufferedReader 和 BufferedWriter 和 缓冲字符输出流PrintWrite

缓冲字符流

  • 缓冲字符流是一对高级流,在流连接中的作用的提高读写文本数据的效率,并且

  • 可以安行读写字符串

  • java.io.BufferedReader 和 BufferedWriter *

  • 实际开发中缓冲字符输出流我们更常用的是PrintWrite,具有自动行刷新功能

  • 的缓冲字符输出流,其内部总是连接BufferedWriter作为缓冲加速使用

package IO;import java.io.IOException;
import java.io.PrintWriter;/*** 缓冲字符流* 缓冲字符流是一对高级流,在流连接中的作用的提高读写文本数据的效率,并且* 可以安行读写字符串* java.io.BufferedReader 和 BufferedWriter** 实际开发中缓冲字符输出流我们更常用的是PrintWrite,具有自动行刷新功能* 的缓冲字符输出流,其内部总是连接BufferedWriter作为缓冲加速使用*/
public class PWDemo1 {public static void main(String[] args) throws IOException {/*PrintWriter提供了对文件操作的构造方法:PrintWriter(String path)PrintWriter()*///向文件中写入字符串PrintWriter pw = new PrintWriter("pw.txt");pw.println("唧唧复唧唧.");pw.println("木兰当户织");pw.println("不闻机抒声");pw.println("但问女叹息");pw.println("问女何所思");pw.println("问女何所忆");pw.println("女亦无所思");pw.println("女亦无所忆");pw.println("昨夜见军帖");pw.println("可汗大点兵");pw.println("军书十二卷");pw.println("卷卷有爷名");pw.println("阿爷无大儿");pw.println("木兰无长兄");pw.println("愿为市鞍马");pw.println("从此替爷征");System.out.println("写出完毕");pw.close();}
}

在流连接中使用PW

package IO;import java.io.*;/*** 在流连接中使用PW*/
public class PWDemo2 {public static void main(String[] args) throws IOException {//低级流,文件输出流,作用: 向文件中写入字节数据FileOutputStream fos= new FileOutputStream("pw2.txt");//高级流,转换输出流,作用:1、衔接其他字符流与字节流 2、将写出的字符转换为字节OutputStreamWriter osw= new OutputStreamWriter(fos,"UTF-8");//高级流,作用:块写文本数据加速BufferedWriter bw= new BufferedWriter(osw);//高级流,作用: 按行写出字符串,并且可以自动行刷新PrintWriter pw= new PrintWriter(bw);pw.write("窗前明月光.");pw.write("疑是地上霜.");pw.write("举头望明月.");pw.write("低头思故乡.");System.out.println("写出完毕!");pw.close();}
}

--实现简易记事本工具

  • 程序启动后,要求用户输入一个文件名,然后对该文件写操作.

  • 之后用户输入的没一行字符串都能按行写入到该文件中.

  • 当用户单独输入exit时程序退出

package IO;import java.io.*;
import java.util.Scanner;/*** 实现简易记事本工具* 程序启动后,要求用户输入一个文件名,然后对该文件写操作.* 之后用户输入的没一行字符串都能按行写入到该文件中.* 当用户单独输入exit时程序退出*/
public class Test2 {public static void main(String[] args) throws IOException {Scanner cin = new Scanner(System.in);System.out.print("请输入文件名:");String fileName = cin.nextLine();FileOutputStream fos = new FileOutputStream(fileName,true);OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");BufferedWriter bw = new BufferedWriter(osw);/*在流连接中创建PrintWriter时可以再传入一个boolean型的参数如果这个值为true,则当前PrintWriter就具有了自动行刷新功能.即: 每当我们调用println方法后会自动flush*/PrintWriter pw = new PrintWriter(bw,true);  //true,打开自动行刷新功能System.out.print("请开始输入内容,单独输出exit时退出: ");while (true){String line = cin.nextLine();if ("exit".equals(line)){break;}pw.println(line);
//            pw.flush();}System.out.println("写入完毕");pw.close();}
}

10、使用缓冲字符输入流按行读取文本数据

  • String readLine()
  • 返回一行字符串(读取到换行符,并将换行符之前的内容返回)
  • 如果返回值为null,则表示读取到了末尾
package IO;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;/*** 使用缓冲字符输入流按行读取文本数据*/
public class BRDemo {public static void main(String[] args) throws IOException {FileInputStream fis =new FileInputStream("Test01/src/test/java/IO/BRDemo.java");InputStreamReader isr = new InputStreamReader(fis);BufferedReader br = new BufferedReader(isr);/*String readLine()返回一行字符串(读取到换行符,并将换行符之前的内容返回)如果返回值为null,则表示读取到了末尾*/String line;
//        if ((line = br.readLine()) != null){
//            System.out.println(line);
//        }while(true){line = br.readLine();if (line == null)break;System.out.println(line);}br.close();}
}

11、总结

7、异常处理机制

1、异常处理机制中的try-catch

语法:

try{

可能出现错误的代码片段

}catch(XXXException e){

捕获try中出现的XXXException后的处理代码

package Exception;/*** 异常处理机制中的try-catch* 语法:* try{*     可能出现错误的代码片段* }catch(XXXException e){*     捕获try中出现的XXXException后的处理代码* }*/
public class TryCatchDemo {public static void main(String[] args) {System.out.println("程序开始了...");/*当JVM执行程序的过程中出现了某个异常时,就是实例化对应的异常,并将执行过程设置其中,然后将该异常抛出.*/try {//String str = null;//String str = "a";String str = "abc";System.out.println(str.length());System.out.println(str.charAt(1));System.out.println(Integer.parseInt(str));/*try 语句块中出错代码以下的内容都不执行*/System.out.println("!!!!!!!!!!!!!");}catch (NullPointerException e){e.printStackTrace();System.out.println("出现空指针异常,并解决!");//catch可以定义多个,针对不同异常有不同处理方式时,可以分别捕获}catch (StringIndexOutOfBoundsException e){e.printStackTrace();System.out.println("下标越界,正在解决!");}catch (Exception e){System.out.println("出错");}System.out.println("程序结束了...");}}

2、异常处理机制在IO中的应用

package Exception;import java.io.FileOutputStream;
import java.io.IOException;/*** 异常处理机制在IO中的应用*/
public class FinallyDemo2 {public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream("fos.dat");fos.write(1);} catch (IOException e) {e.printStackTrace();} finally {try {if (fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}}
}

3、JDK 7 之后推出了一个新的特性:AutoCloseabe

  • 使得我们可以用更精简的语法在异常处理机制中完成IO操作.
package Exception;import java.io.FileOutputStream;
import java.io.IOException;/*** JDK 7 之后推出了一个新的特性:AutoCloseabe* 使得我们可以用更精简的语法在异常处理机制中完成IO操作.*/
public class AutoCloseableDemo {public static void main(String[] args) {try (/*只有实现了AutoCloseable 接口的类才能在这里声明变量,并且最终会被编译器改为在 finally 中将其关闭*/FileOutputStream fos = new FileOutputStream("fos.dat");){fos.write(1);}catch (IOException e){e.printStackTrace();}}
}

4、finally块

finally是异常处理机制的最后一块,它可以直接跟在try块后或者最后一个catch块之后

  • finally 可以保证只要程序执行到try语句块中,无论try中的代码是否出现了异常,

  • finally 都必定执行,所以通常我们将释放资源这类操作放在 finally 中,比如 IO 操作后的关闭

/*** finally块* finally是异常处理机制的最后一块,它可以直接跟在try块后或者最后一个catch块之后* finally 可以保证只要程序执行到try语句块中,无论try中的代码是否出现了异常,* finally 都必定执行,所以通常我们将释放资源这类操作放在 finally 中,比如 IO 操作后的关闭*/
public class FinallyDemo {public static void main(String[] args) {System.out.println("程序开始了...");try{String str = "null";System.out.println(str.length());return ;}catch (Exception e){e.printStackTrace();System.out.println("有错误!");}finally {System.out.println("finally中代码执行了!");}System.out.println("程序结束了...");}
}

5、finally 常见面试题

  • 请分别说明 final,finalize,finally?

  • finalize 是Object中定义的方法,该方法被 GC 调用,当GC即将释放一个对象

  • 时会调用该方法,调用后该对象被释放,因此该方法是一个对象生命周期中的最后一个方法

package Exception;/*** finally 常见面试题** 请分别说明 final,finalize,finally?** finalize 是Object中定义的方法,该方法被 GC 调用,当GC即将释放一个对象* 时会调用该方法,调用后该对象被释放,因此该方法是一个对象生命周期中的最后一个方法***/
public class FinallyDemo3 {public static void main(String[] args) {System.out.println(test('0'+","+test(null)+","+test("")));}public static int test(String str){try {return str.charAt(0)-'0';}catch (NullPointerException e){return 1;}catch (Exception e){return 2;}finally {return 3;}}
}

8、多线程

1、多线程

  • 多线程可以并发执行多个代码片段,使得代码有机会”同时运行“。

2、线程的创建有两种方式:

  • 1、继承Thread并重写run方法

  • 2、实现Runnable接口单独定义线程任务

2.1、第一种创建线程的方式的优点在于:

 结构简单,利于匿名内部类的创建

缺点有两个:

  • 1、继承Thread,由于java是单继承的,这导致如果继承了Thread就无法再

  • 继承其他类来复用代码,实际开发中很不方便

  • 2、定义线程的同时重写了run方法来定义线程要执行的任务,这导致线程与

  • 线程要执行的任务存在必然的绑定关系,不利于线程的重用

package Thread;/*** 多线程* 多线程可以并发执行多个代码片段,使得代码有机会”同时运行“。*** 线程的创建有两种方式:* 1、继承Thread并重写run方法* 2、*/
public class ThreadDemo1{public static void main(String[] args) {Thread t1 = new MyThread1();Thread t2 = new MyThread2();/*启动线程要调用start方法,而不是直接调用run方法。当start方法调用后线程会纳入到线程调度器中,一旦获取到了时间片,run方法会自动被执行*/t1.start();t2.start();}
}/*** 第一种创建线程的方式的优点在于:结构简单,利于匿名内部类的创建* 缺点有两个:* 1、继承Thread,由于java是单继承的,这导致如果继承了Thread就无法再*    继承其他类来复用代码,实际开发中很不方便* 2、定义线程的同时重写了run方法来定义线程要执行的任务,这导致线程与*    线程要执行的任务存在必然的绑定关系,不利于线程的重用*/
class MyThread1 extends Thread{@Overridepublic void run() {for (int i=0;i<1000;i++){System.out.println("查水表的...");}}
}
class MyThread2 extends Thread{@Overridepublic void run() {for (int i=0;i<1000;i++){System.out.println("做头发的...");}}
}

第二种创建方式

package Thread;/*** 第二种创建线程的方式* 实现Runnable接口单独定义线程任务*/
public class ThreadDemo2 {public static void main(String[] args) {//单独定义线程任务Runnable r1 = new MyRunnable1();Runnable r2 = new MyRunnable2();//创建线程Thread t1 = new Thread(r1);Thread t2 = new Thread(r2);t1.start();t2.start();}
}
class MyRunnable1 implements Runnable{@Overridepublic void run() {for (int i=0;i<10000;i++){System.out.println("Hello!lulu...");}}
}
class MyRunnable2 implements Runnable{@Overridepublic void run() {for (int i=0;i<100000;i++){System.out.println("Baybay....");}}
}

3、java中所有的代码都是靠线程运行的,main方法也不例外。运行mian方法的线程

  • 是java进程创建的,并且该线程的名字叫做”main“,一般我们称它为"主线程"

  • 我们自己创建的线程如果没有特别指定的名字时,默认名字的格式为:Thread-x

  • x是一个数字,从0开始 *

  • Thread提供了一个静态方法:

  • static Thread currentThread()

  • 该方法可以获取运行这个方法的线程

package Thread;/*** java中所有的代码都是靠线程运行的,main方法也不例外。运行mian方法的线程* 是java进程创建的,并且该线程的名字叫做”main“,一般我们称它为"主线程"* 我们自己创建的线程如果没有特别指定的名字时,默认名字的格式为:Thread-x* x是一个数字,从0开始** Thread提供了一个静态方法:* static Thread currentThread()* 该方法可以获取运行这个方法的线程**/
public class CurrentThreadDemo {public static void main(String[] args) {/*Thread提供的静态方法:static Thread currentThread()该方法可以获取运行这个方法的线程*/Thread main = Thread.currentThread();//获取运行main方法的线程//创建一条线程与主线程并发Thread t = new Thread(){public void run(){Thread t = Thread.currentThread();//获取t线程自己System.out.println("自定义线程: "+t);dosome();//t线程调用dosome方法System.out.println("自定义线程结束了!");}};t.start();System.out.println("主线程: "+main);dosome();//让主线程调用dosome方法System.out.println("主线程结束了!");}public static void dosome(){//获取运行的dsome方法的线程Thread t = Thread.currentThread();for(int i=0;i<1000;i++) {System.out.println(t+":正在执行dosome方法 "+i);}}
}

4、线程提供了一组获取自身相关信息的方法

package Thread;/*** 线程提供了一组获取自身相关信息的方法*/
public class ThreadInfoDemo {public static void main(String[] args) {//以主线程为例Thread main = Thread.currentThread();//获取线程的名字String name = main.getName();System.out.println("线程的名字: "+name);//获取线程的唯一标识long id = main.getId();System.out.println("线程的ID: "+id);//获取线程的优先级,默认值为5.取值是在1-10之间的整数int priority = main.getPriority();System.out.println("优先级: "+priority);//线程是否活着boolean isAlive = main.isAlive();//线程是否为守护线程boolean isDaemon = main.isDaemon();//线程是否被中断了boolean isInterrupted = main.isInterrupted();System.out.println("isAlive:"+isAlive);System.out.println("isDaemon:"+isDaemon);System.out.println("isInterrupted:"+isInterrupted);}
}

5、线程的优先级

线程有10个优先级,分别用整数1-10表示。其中1为最低优先级,10为最高优先级。5为

默认值。优先级越高的线程获取CPU时间片的次数越多。

线程start后就会纳入到线程调度器程序中统一管理,线程无法主动索取时间片,只能被动

被分配,因此可以通过调整线程的优先级可以最大程度的改善获取时间片的几率。

void setPriority(int priority)

package Thread;/*** 线程的优先级* 线程有10个优先级,分别用整数1-10表示。其中1为最低优先级,10为最高优先级。5为* 默认值。优先级越高的线程获取CPU时间片的次数越多。** 线程start后就会纳入到线程调度器程序中统一管理,线程无法主动索取时间片,只能被动* 被分配,因此可以通过调整线程的优先级可以最大程度的改善获取时间片的几率。** void setPriority(int priority)**/
public class PriorityDemo {public static void main(String[] args) {Thread max = new Thread(){public void run(){for (int i=0;i<10000;i++){System.out.println("max");}}};Thread min = new Thread(){public void run(){for (int i=0;i<10000;i++){System.out.println("min");}}};Thread norm = new Thread(){public void run(){for (int i=0;i<10000;i++){System.out.println("nor");}}};min.setPriority(Thread.MIN_PRIORITY);max.setPriority(Thread.MAX_PRIORITY);min.start();norm.start();max.start();}
}

6、static void sleep(long ms) 该方法可以让运行这个方法的线程处于阻塞状态指定毫秒,超时后线程会自动

线程提供了一个静态方法:

static void sleep(long ms)

该方法可以让运行这个方法的线程处于阻塞状态指定毫秒,超时后线程会自动

回到 RUNNABLE 状态再次开始并发运行

package Thread;import java.util.Scanner;/*** 线程提供了一个静态方法:* static void sleep(long ms)* 该方法可以让运行这个方法的线程处于阻塞状态指定毫秒,超时后线程会自动* 回到 RUNNABLE 状态再次开始并发运行*/
public class SleepDemo {public static void main(String[] args) {System.out.println("程序开始了!");/*倒计时程序,程序启动后要求输入一个数字,然后从该数字开始每秒递减并输出,到0时输出时间到*/Scanner cin = new Scanner(System.in);System.out.print("请输入一个倒计时时间: ");int num = cin.nextInt();try {for (int i=num;i>0;i--) {System.out.println("倒计时: " + i);Thread.sleep(1000); //程序卡了1秒}} catch (InterruptedException e) {e.printStackTrace();}System.out.println("时间到!");System.out.println("程序结束了!");}
}

7、interrput()--该方法会抛出中断异常并打断阻塞状态

 当一个线程调用sleep方法进入阻塞的过程中,此时该线程的interrput()方法被调用时,该方法会抛出中断异常并打断阻塞状态

package Thread;/*** 当一个线程调用sleep方法进入阻塞的过程中,此时该线程的interrput()方法* 被调用时,该方法会抛出中断异常并打断阻塞状态*/
public class SleepDemo2 {public static void main(String[] args) {Thread lin = new Thread(){@Overridepublic void run() {System.out.println("林: 刚美完容,睡一会吧...");try {Thread.sleep(1000000);} catch (InterruptedException e) {System.out.println("林: 干嘛呢!干嘛呢!干嘛呢!都破了相了");}System.out.println("醒了!");}};Thread huang = new Thread(){@Overridepublic void run() {System.out.println("黄: 大锤80!小锤40!开始砸墙!");for (int i=0;i<5;i++){System.out.println("黄: 80!");try {Thread.sleep(1000);} catch (InterruptedException e) {}}System.out.println("咣当!");System.out.println("搞定!");lin.interrupt();}};lin.start();huang.start();}
}

8、守护线程

守护线程

  • 也称为后台线程,它是通过普通线程调用setDaemon(true)设置而来的。

  • 因此创建时与普通线程无异。但是在结束时机上有一点不同:进程结束时。

  • 进程的结束:

  • 当一个java进程中的所有普通线程都结束时,进程就会结束,此时它会强制杀死所有还在运行的守护线程

  • GC就是守护线程上执行的。

  • 当我们运行的某个任务不关心它什么时候结束,只要我们主要的任务都执行

  • 完毕后它可以跟着结束,那么这类任务就适合放在守护线程上执行

package Thread;/*** 守护线程* 也称为后台线程,它是通过普通线程调用setDaemon(true)设置而来的。* 因此创建时与普通线程无异。但是在结束时机上有一点不同:进程结束时。* 进程的结束:* 当一个java进程中的所有普通线程都结束时,进程就会结束,此时它会强制* 杀死所有还在运行的守护线程** GC就是守护线程上执行的。* 当我们运行的某个任务不关心它什么时候结束,只要我们主要的任务都执行* 完毕后它可以跟着结束,那么这类任务就适合放在守护线程上执行*/
public class DaemonThreadDemo {public static void main(String[] args) {Thread rose = new Thread(){@Overridepublic void run() {for (int i=0;i<5;i++){System.out.println("rose: let me go!");try {Thread.sleep(1000);} catch (InterruptedException e) {}}System.out.println("啊啊啊啊啊啊啊啊啊~~~~~");System.out.println("噗通~~~~");}};Thread jack = new Thread(){@Overridepublic void run() {while (true){System.out.println("jack: you jump,i jump!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};rose.start();/*设置守护线程的工作必须在线程启动前进行,否则会抛出异常*/jack.setDaemon(true);jack.start();/*如果主线程还活着,那么此时rose结束时,由于进程发现还有普通线程活着(主线程还活着)就不会结束,因此就不会杀死所以还在运行的守护线程。*/while (true);//System.out.println("main执行完了!");}
}

9、join()方法---用来协调线程的同步运行

线程定义的方法:

  • void join()---该方法用来协调线程的同步运行,它允许一条线程在当前join方法所属的线程上等待(阻塞),直到join方法所属线程执行完毕方可继续执行

  • 同步运行:多个线程执行时存在了先后顺序,有序进行

  • 异步运行:多个线程各执行各的,互不干涉。多线程本身就是异步运行的线程定义的方法:

package Thread;/*** 线程定义的方法:* void join()* 该方法用来协调线程的同步运行,它允许一条线程在当前join方法所属的线程* 上等待(阻塞),直到join方法所属线程执行完毕方可继续执行** 同步运行:多个线程执行时存在了先后顺序,有序进行* 异步运行:多个线程各执行各的,互不干涉。多线程本身就是异步运行的*/
public class JoinDemo {//标记图片是否下载完毕private static boolean isFinish = false;public static void main(String[] args) {/*当一个方法的局部内部类中需要引用这个方法的其他局部变量时,要求该变量必须被声明为final的*///  final boolean isFinish = false;Thread download = new Thread(){@Overridepublic void run() {System.out.println("down: 开始下载图片...");for (int i=1;i<=100;i++){System.out.println("down:"+i+"%");try {Thread.sleep(50);} catch (InterruptedException e) {}}System.out.println("down:图片下载完毕!");isFinish = true;  //表示图片下载完毕了}};Thread show = new Thread(){@Overridepublic void run() {System.out.println("show: 开始显示文字...");try {Thread.sleep(3000);} catch (InterruptedException e) {}System.out.println("show: 文字显示完毕!");//将show线程阻塞,直到download执行完毕(将图片下载完毕)System.out.println("show: 等待download下载图片...");try {download.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("show: 等待download下载完毕!");System.out.println("show: 开始显示图片...");if(!isFinish){throw new RuntimeException("图片加载失败!");}System.out.println("图片显示完毕!");}};download.start();show.start();}
}

10、多线程并发安全问题----synchronized(同步锁)

多线程并发安全问题

  • 当多个线程并发操作统一临界资源,由于线程切换时间不确定,导致操作该资源过的过程执行顺序混乱,从而出现错误

  • 临界资源:操作该资源的完整过程同时只能被单个线程进行

synchronized:

  • 当一个方法使用关键字synchronized修饰后,该方法称为“同步法”,此时这个方法不能同时被多个线程执行 将多个线程并发操作的过程改为同步有先后顺序的执行可以有效的解决,多线程的并发安全问题.

package Thread;/*** 多线程并发安全问题* 当多个线程并发操作统一临界资源,由于线程切换时间不确定,导致操作该资源过* 的过程执行顺序混乱,从而出现错误* 临界资源:操作该资源的完整过程同时只能被单个线程进行*/
public class SyncDemo {public static void main(String[] args) {Table table = new Table();Thread t1 = new Thread(){@Overridepublic void run() {while (true){int bean = table.getBean();Thread.yield();System.out.println(getName()+":"+bean);}}};Thread t2 = new Thread(){@Overridepublic void run() {while (true){int bean = table.getBean();Thread.yield();System.out.println(getName()+":"+bean);}}};t1.start();t2.start();}
}
class Table{//桌子上有20个豆子private int beans = 20;/*当一个方法使用关键字synchronized修饰后,该方法称为“同步法”此时这个方法不能同时被多个线程执行将多个线程并发操作的过程改为同步有先后顺序的执行可以有效的解决多线程的并发安全问题.*/public synchronized int getBean() {if (beans ==0){throw new RuntimeException("没有豆子了!");}//主动在这里放弃CPU时间片,模拟线程执行到这里就没有时间了Thread.yield();return beans--;}
}

10.2、同步块----synchronized(同步监视器对象){需要同步执行的代码片段}

同步块

语法:

synchronized(同步监视器对象){ ​ 需要同步执行的代码片段

}

同步块可以更精准的锁定需要同步执行的代码片段,有效的缩小排队范围可以在保证并发安全的前提下提高并发效率

package Thread;/*** 同步块* 语法:* synchronized(同步监视器对象){*     需要同步执行的代码片段* }** 同步块可以更精准的锁定需要同步执行的代码片段,有效的缩小排队范围可以在保证并发安全* 的前提下提高并发效率*/
public class SyncDemo2 {public static void main(String[] args) {Shop shop = new Shop();Thread t1 = new Thread(){@Overridepublic void run() {shop.buy();}};Thread t2 = new Thread(){@Overridepublic void run() {shop.buy();}};t1.start();t2.start();}
}
class Shop{/*成员方法上直接使用synchronized时,同步监视器对象就是当前方法所属对象,即: 方法内看到的this*///public synchronized void buy()public void buy(){try {Thread t = Thread.currentThread();System.out.println(t.getName()+" :正在挑衣服");Thread.sleep(5000);/*同步块在使用时要求指定同步监视器对象,该对象可以是java中任何引用类型的实例,只要保证一点即可:多个需要同步执行该代码片段的线程看到的这个对象必须是同一个*/synchronized (this){System.out.println(t.getName()+" :正在试衣服");Thread.sleep(5000);}System.out.println(t.getName()+" :结账离开");}catch (InterruptedException e) {e.printStackTrace();}}
}

10.3、静态方法上使用synchronized---那么该方法一定具有同步效果

静态方法上使用synchronized时,同步监视器对象为当前类的类对象

即:Class的实例

JVM中每个被加载的类都有且只有一个类对象与之对应,静态方法上指定的锁 对象就是这个类对象,后期会学习java反射机制,在哪里会介绍。

指定类对象作为同步监视器对象时写法为:类名.class

package Thread;/*** 静态方法上如果使用synchronized,那么该方法一定具有同步效果*/
public class SyncDemo3 {public static void main(String[] args) {Boo b1 = new Boo();Boo b2 = new Boo();Thread t1 = new Thread(){@Overridepublic void run() {b1.dosome();}};Thread t2 = new Thread(){@Overridepublic void run() {b2.dosome();}};t1.start();t2.start();}
}
class Boo{/*静态方法上使用synchronized时,同步监视器对象为当前类的类对象即:Class的实例JVM中每个被加载的类都有且只有一个类对象与之对应,静态方法上指定的锁对象就是这个类对象,后期会学习java反射机制,在哪里会介绍。指定类对象作为同步监视器对象时写法为:类名.class*///public synchronized static void dosome(){public static void dosome(){synchronized (Boo.class){Thread t = Thread.currentThread();System.out.println(t.getName()+":正在执行dosome方法....");try {Thread.sleep(5000);} catch (InterruptedException e) {}System.out.println(t.getName()+":执行dosome方法完");}}
}

10.4、互斥锁

当使用synchronized锁定多个代码片段,并且指定的锁对象相同时,这些

代码片段之间就是互斥的。多个线程不能同时执行这些代码片段

package Thread;/*** 互斥锁* 当使用synchronized锁定多个代码片段,并且指定的锁对象相同时,这些* 代码片段之间就是互斥的。多个线程不能同时执行这些代码片段*/
public class SyncDemo4 {public static void main(String[] args) {Foo foo = new Foo();Thread t1 = new Thread(){@Overridepublic void run() {foo.methodA();}};Thread t2 = new Thread(){@Overridepublic void run() {foo.methodB();}};t1.start();t2.start();}
}
class Foo{public synchronized void methodA(){Thread t = Thread.currentThread();try {System.out.println(t.getName()+" 正在执行A方法...");Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getName()+" A方法执行完毕!");}public synchronized void methodB(){Thread t = Thread.currentThread();try {System.out.println(t.getName()+" 正在执行B方法...");Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getName()+" B方法执行完毕!");}
}

10.5、死锁

死锁的产生:

两个线程各自持有一个锁对象的同时等待对方先释放锁对象,此时会出现僵持状态。这个现象就是死锁。

package thread;/*** 死锁* 死锁的产生:* 两个线程各自持有一个锁的同时等待对方先释放锁,这时会形成一种僵持的* 状态。这个现象就称为死锁。*/
public class DeadLockDemo {//筷子public static Object chopsticks = new Object();//勺public static Object spoon = new Object();public static void main(String[] args) {//北方人Thread np = new Thread(){public void run(){System.out.println("北方人开始吃饭");System.out.println("北方人去拿筷子...");synchronized (chopsticks){System.out.println("北方人拿起筷子吃饭...");try {Thread.sleep(5000);} catch (InterruptedException e) {}System.out.println("北方人吃完饭了,去拿勺");synchronized (spoon){System.out.println("北方人拿起了勺喝汤...");try {Thread.sleep(5000);} catch (InterruptedException e) {}System.out.println("北方人喝完了汤");}System.out.println("北方人放下了勺");}System.out.println("北方人放下了筷子,吃饭完毕");}};Thread sp = new Thread(){public void run(){System.out.println("南方人开始吃饭");System.out.println("南方人去拿勺...");synchronized (spoon){System.out.println("南方人拿起勺喝汤...");try {Thread.sleep(5000);} catch (InterruptedException e) {}System.out.println("南方人喝完汤了,去拿筷子");synchronized (chopsticks){System.out.println("南方人拿起了筷子吃饭...");try {Thread.sleep(5000);} catch (InterruptedException e) {}System.out.println("南方人吃完饭了");}System.out.println("南方人放下了筷子");}System.out.println("南方人放下了勺,吃饭完毕");}};np.start();sp.start();}
}

9、网络编程---Socket

在一个Socket中同时包含了远程服务器的IP地址和端口信息,以及客户本地的IP地址和端口信息。此外,从Socket对象中还可以获得输出流和输入流,分别用于向服务器发送数据,以及接受从服务端发来的数据。以下方法用于获取Socket的有关信息。

Socket socket=new Socket();socket.getInetAddress();//获得远程服务器的IP地址socket.getPort();//获得远程服务器的端口socket.getLocalAddress();//获得客户本地的端口socket.getInputStream();//获得输入流。如果Socket还没有连接//或者已经关闭,或者已经通过shutdownInput()//方法关闭输入流,那么此方法会抛出IOExceptionsocket.getOutputStream();//获得输出流如果Socket还没有连接//或者已经关闭,或者已经通过shutdownOutput()//方法关闭输出流,那么此方法会抛出IOException

如下例子用于访问网页v.qq.com/zt/tqzt/2817466.shtml。该网页位于一个主机名(也叫域名)为v.qq.com的远程服务器上,它监听80端口。在HTTPClient类中,先建立了一个连接到该HTTP服务器的Socket对象,然后发送符合HTTP协议的请求,接着接受从HTTP服务器发回的响应结果。HTTP协议简介

package 获取Socket的信息;import java.io.*;
import java.net.Socket;
import java.util.Scanner;/*** HTTPClient类用于访问网页www.baidu.com。现在已经使用安全的http协议即HTTPS了,* 该网页位于一个主机名(也叫域名)为“www.baidu.com”的远程HTTP服务器上* HTTPS监听443端口,HTTP监听80端口,在HTTPClient类中,先建立了一个* 连接到该服务器的Socket对象,然后发送符合HTTP协的请求,接着接受从HTTP服务器上* 发回的响应结果。*/public class HTTPClient {String host="www.baidu.com";//String host="www.javathinker.net";int port=80;Socket socket;public  void crteateSocket() throws IOException {socket=new Socket("v.qq.com",80);}public void communicate() {//StringBuffer sb=new StringBuffer("GET "+"/zt/tqzt/2817466.shtml"+" HTTP/1.1\r\n");StringBuffer sb=new StringBuffer("GET http://v.qq.com/ HTTP/1.1\r\n");sb.append("Host:v.qq.com\r\n");sb.append("Connection: keep-alive\r\n");sb.append("Upgrade-Insecure-Requests: 1\r\n\r\n");try {//发出HTTP请求OutputStream socketOut=socket.getOutputStream();socketOut.write(sb.toString().getBytes());socket.shutdownOutput();//关闭输出流//接受响应结果InputStream socketInput=socket.getInputStream();//把接收到的字节写到ByteArrayOutputStream中,它具有一个容量自动增长的缓冲区ByteArrayOutputStream buffer=new ByteArrayOutputStream();/*byte[] buff=new byte[1024];int len=1;while ((len=socketInput.read(buff))!=-1){//如果返回-1,则表示读到了输入流到了结尾buffer.write(buff,0,len);}System.out.println(new String(buffer.toByteArray()));*//*** 值得注意的是,如果接受的网页数据量很大,先把这些数据全部保存在ByteArrayOutputStream的缓存中不是明智的做法,因为这些数据* 会占用大量的内存。更有效的方法是利用scanner来读取网页数据:/Scanner scannerSocket=new Scanner(socket.getInputStream());String data;while (scannerSocket.hasNextLine()){data=scannerSocket.nextLine();System.out.println(data);}/*BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));String data;while ((data=br.readLine())!=null){System.out.println(data);}*/} catch (IOException e) {e.printStackTrace();}finally {/*关闭socket,当客户与服务器通信结束,应该及时关闭socket以释放Socket所占用的各种资源。Socket的close()方法负责关闭Socket当一个socket对象被关闭,就不能再通过他的输入流和输出流进行i/o操作,否则会抛出IOException,为了确保关闭Socket的操作总是被执行,强烈建议把这个操作放在finally代码块中。*/if (socket!=null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}public static void main(String[] args) throws IOException {HTTPClient cient=new HTTPClient();cient.crteateSocket();cient.communicate();}}

10、java集合---Collection

1、Collection-----List、Set

java集合框架

  • java.util.Collection接口,所以集合的顶级接口,里面规定了集合所必须具备的相关功能

  • 集合与数组一样,可以保存一组元素,并且对于元素的操作都封装成了方法

  • 集合有多种实现类,实现了不同的数据结构,实际开发中我们可以结合实际需求选取合适的数据结构来存储元素

  • Collection下面有两个常见的子接口:

    java.util.List:线性表,特点: 可以存放重复元素,并且有序

    java.util.Set:不可重复集,即: 不能存放重复元素

  • 元素是否重复是依靠元素本身的equals比较来判定的,即:Set集合不能存放在 两个元素equals比较为true的情况

package Collections;import java.util.ArrayList;
import java.util.Collection;/*** java集合框架* java.util.Collection接口,所以集合的顶级接口,里面规定了集合所必须具备的相关功能* 集合与数组一样,可以保存一组元素,并且对于元素的操作都封装成了方法** 集合有多种实现类,实现了不同的数据结构,实际开发中我们可以结合实际需求选取合适* 的数据结构来存储元素** Collection下面有两个常见的子接口:* java.util.List:线性表,特点: 可以存放重复元素,并且有序* java.util.Set:不可重复集,即: 不能存放重复元素* 元素是否重复是依靠元素本身的equals比较来判定的,即:Set集合不能存放在* 两个元素equals比较为true的情况* */
public class CollectionDemo1 {public static void main(String[] args) {Collection c = new ArrayList();/*boolean add(E e)将给定元素添加到集合中去,如果成功添加则返回true`*/c.add("唧唧复唧唧");c.add("木兰当户织");c.add("不闻机杼声");c.add("但问女叹息");System.out.println(c);/*int size()返回当前集合的元素个数*/int size = c.size();System.out.println("size: "+size);/*boolean isEmpty()判断当前集合是否为空集(不含有元素).当集合的size为0时,返回true*/boolean isEmety = c.isEmpty();System.out.println("是否为空集: "+isEmety);//清空集合c.clear();System.out.println("size: "+size);System.out.println("是否为空集: "+isEmety);}
}

2、集合中与元素定义的方法相关的操作

1、boolean contains(Object o)---判断当前集合是否包含给定元素

2、boolean remove(Object o)---删除当前集合与equals比较为true的元素

package Collections;import java.util.ArrayList;
import java.util.Collection;/*** 集合中与元素定义的方法相关的操作*/
public class CollectionDemo2 {public static void main(String[] args) {Collection c = new ArrayList();c.add(new Point(1,2));c.add(new Point(3,4));c.add(new Point(5,6));c.add(new Point(7,8));c.add(new Point(9,0));/*集合重写了toString方法,格式如下:[元素1.toString,元素2.toString,...]因此如果集合存放的自定义的元素,那么为了有更好的输出集合效果,元素应当重写toString方法*/System.out.println(c);Point p = new Point(1,2);System.out.println("p: "+p);/*boolean contains(Object o)判断当前集合是否包含给定元素。判断的依据时给定的元素是否与集合中存放的元素存在equals比较为true的,存在则认为包含*/boolean contains = c.contains(p);System.out.println("包含:"+contains);/*boolean remove(Object o)删除当前集合中与给定元素equals比较为true的元素,成功删除则返回true对于List集合而言,如果存在重复元素,则仅删除一次.*/c.remove(p);System.out.println(c);}
}

3、boolean addAll(Collection c)--求并集

4、boolean containsAll(Collection c)--求是否为真子集

5、removeAll()---删除当前集合中与给定集合的共有元素

package Collections;import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;/*** 集合间的操作*/
public class CollectionDemo4 {public static void main(String[] args) {/*Set:不可以存放相同元素List:可以存放相同的元素*/Collection c1 = new HashSet();c1.add("Java");c1.add("C++");c1.add(".net");System.out.println("c1: "+c1);Collection c2 = new ArrayList();c2.add("android");c2.add("ios");c2.add("Java");System.out.println("c2: "+c2);/*boolean addAll(Collection c)将给定集合中的所有元素添加到当前集合中,添加后当前集合发生了改变就返回true*///c1.addAll(c2);c2.addAll(c1);System.out.println("c1: "+c1);System.out.println("c2: "+c2);Collection c3 = new ArrayList();c3.add("android");c3.add("C++");System.out.println("c3: "+c3);/*boolean containsAll(Collection c)判断当前集合是否包含给定集合中的所有元素*/boolean contains = c2.containsAll(c3);System.out.println("contains: "+contains);/*删除当前集合中与给定集合的共有元素。*/c2.removeAll(c3);System.out.println("c2: " + c2);}
}

6、集合的遍历-----迭代器(Iterator)

-----hastNext()

-----增强型for循环

集合的遍历

Collection 提供了统一的遍历集合元素的操作: 迭代器

Iterator iterator()

该方法会返回一个用于遍历当前集合元素的迭代器

java.util.Iterator接口

该接口时迭代器接口,规定了迭代器遍历集合的对应操作,所有集合都实现了

一个用于遍历自身元素的迭代器实现类 迭代器遍历集合遵循的步骤:问,取,删。其中删除元素不是必要操作

  • boolean hastNext()---通过迭代器判断集合是否还有"下一个"元素可供遍历

  • E next()---获取"下一个"元素,第一次调用就是获取第一个,第二次调用就是获取第二个,以此类推,调用前一定确定hastNext 为 true

  • void remove()---删除通过next方法获取的元素

package Collections;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*** 集合的遍历* Collection 提供了统一的遍历集合元素的操作: 迭代器**Iterator iterator()* 该方法会返回一个用于遍历当前集合元素的迭代器** java.util.Iterator接口* 该接口时迭代器接口,规定了迭代器遍历集合的对应操作,所有集合都实现了* 一个用于遍历自身元素的迭代器实现类*迭代器遍历集合遵循的步骤:问,取,删。其中删除元素不是必要操作*/
public class IteratorDemo {public static void main(String[] args) {Collection c1 = new ArrayList();c1.add("one");c1.add("#");c1.add("two");c1.add("#");c1.add("three");c1.add("#");c1.add("four");c1.add("#");c1.add("five");System.out.println(c1);Iterator iterator = c1.iterator();/*boolean hasNext()通过迭代器判断集合是否还有"下一个"元素可供遍历第一次调用时判断的就是集合第一个元素E next()获取”下一个“元素,第一次调用就是获取第一个,第二次调用就是获取第二个,以此类推,调用前一定确定hasNext为truevoid remove()删除通过next方法获取的元素*/while (iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);if ("#".equals(obj)){//  c1.remove(obj);iterator.remove();  //迭代器自带的方法删除元素}}System.out.println(c1);}
}

增强型for循环----for(元素类型 变量名 :集合|数组){}

JDK5推出时,推出了一个新的特性: 增强型for循环,也称为新循环

它使得我们可以使用相同的语法遍历集合或数组

语法:

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

}

package Collections;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;/*** JDK5推出时,推出了一个新的特性: 增强型for循环,也称为新循环* 它使得我们可以使用相同的语法遍历集合或数组* 语法:* for(元素类型 变量名 : 集合|数组){** }*/
public class NewForDemo {public static void main(String[] args) {/*JDK5 推出时推出另一个特性:泛型泛型也称为参数化类型,它允许我们在使用一个类时,指定该类中方法参数的类型或方法方法返回值的类型或属性的类型等,使得我们使用这个类时更加灵活方便使用这个类时更加灵活方便泛型被广泛的应用在集合中,用来约束集合中的元素类型,对于有泛型的类在使用时如果不指定泛型的实际类型,则默认为原型Object*/Collection<String> c = new ArrayList();c.add("Java");c.add("PHP");c.add("Python");c.add("C#");c.add(".net");System.out.println(c);//迭代器也可以指定泛型,告知迭代器遍历集合的元素类型Iterator<String> it = c.iterator();//泛型要与集合指定的一致while (it.hasNext()){//E next() : 该方法返回时以泛型指定的类型返回,因此无需在造型String str = it.next();System.out.println(str);}System.out.println(c);//新循环就是迭代器,编译后会改为上面的迭代器遍历方式for (String str : c){   //集合指定泛型,可直接用元素实际类型//String str = (String)obj;System.out.println(str);}String[] array = {"one","two","three","four","five"};System.out.println(Arrays.toString(array));for (String str : array){System.out.println(str);}}
}

3、List集合

---ArrayList:内部使用数组实现,查询性能更好

---LinkedList:内部使用链表实现,增删性能更好

 List集合
* java.util.List接口,继承自Collection
* List集合可以存放重复元素,并且有序,提供了一套可以通过下标操作元素的方法
* 常用实现类:
* java.util.ArrayList:内部使用数组实现,查询性能更好
* java.util.LinkedList:内部使用链表实现,增删性能更好

package Collections;import java.util.*;/*** List集合* java.util.List接口,继承自Collection* List集合可以存放重复元素,并且有序,提供了一套可以通过下标操作元素的方法* 常用实现类:* java.util.ArrayList:内部使用数组实现,查询性能更好* java.util.LinkedList:内部使用链表实现,增删性能更好**/
public class ListDemo1 {public static void main(String[] args) {List<String> list = new ArrayList();list.add("one");list.add("two");list.add("three");list.add("four");list.add("five");System.out.println(list);/*E get(int index)获取指定下标对应的元素*/String str = list.get(2);System.out.println(str);//list支持普通的for循环遍历for (int i=0;i<list.size();i++){str = list.get(i);System.out.println(str);}/*E set(int index,E e)将给定元素设置到指定位置,返回值为该位置原有元素此操作为替换元素*///[one,two,six,four,five]String old = list.set(2,"six");System.out.println(list);System.out.println("old: "+old);//将集合反转//[five,four,six,two,one]//Collections.reverse(list);   //Collections 类提供的方法,集合反转for (int i=0;i<list.size()/2;i++){  //0,1,2String s = list.get(i); //one,two,sixSystem.out.println(s);s = list.set(list.size()-1-i,s);//five->one four->two six->six---[one,two,six,one,two]System.out.println(s);list.set(i,s);  //one->five two->fourSystem.out.println(list);//[five,four,six,two,one]}System.out.println(list);}
}

1、List提供了一对重载的add,remove方法

--void add(int index,E e)--将给定元素插入到指定位置

--E remove(int index)---删除并返回给定位置上的元素

package Collections;import java.util.ArrayList;
import java.util.List;/*** List提供了一对重载的add,remove方法*/
public class ListDemo2 {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("one");list.add("two");list.add("three");list.add("four");list.add("five");System.out.println(list);/*void add(int index,E e)将给定元素插入到指定位置*/list.add(3,"six");System.out.println(list);/*E remove(int index)删除并返回给定位置上的元素*/String old = list.remove(2);System.out.println(list);System.out.println(old);}
}

2、List subList(int start,int end)--获取当前集合中指定范围内的子集

package Collections;import java.util.ArrayList;
import java.util.List;/*** List subList(int start,int end)* 获取当前集合中指定范围内的子集*/
public class ListDemo3 {public static void main(String[] args) {/*如果泛型指定需要是基本类型时,要指定对应的包装类。泛型只能是引用类型*/List<Integer> list = new ArrayList<>();for (int i=0;i<10;i++){list.add(i);}System.out.println(list);//获取子集2-7List<Integer> subList = list.subList(2,8);System.out.println(subList);/*当我们使用subList获取一个集合的子集后,对该子集的元素操作就是对原集合对应的操作!*///[20,30,40,50,60,70]for (int i=0;i<subList.size();i++){int num = subList.get(i);num = num * 10; //10,20,30,40,50,60,70,80,90subList.set(i,num);//1->10,2->20....}System.out.println(subList);/*将集合中2-8删除*/list.subList(2,9).clear();System.out.println(list);}
}

3、集合转换为数组---toArray

集合转换为数组

Collection 提供了一个方法:toArray,可以将当前集合转化为一个数组

T[] toArray(T... array) 该方法要求传入一个数组,如果该数组可用(长度>=size)则直接将 当前集合所有元素存入该数组后将其返回,如果数组不可用(长度不足) 则会根据传入的数组类型自动创建一个与集合size等长的数组并将 集合元素存入后返回

package Collections;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;/*** 集合转换为数组* Collection 提供了一个方法:toArray,可以将当前集合转化为一个数组*/
public class CollectionToArrayDemo {public static void main(String[] args) {Collection<String> c = new ArrayList<>();c.add("one");c.add("two");c.add("three");c.add("four");System.out.println(c);/*T[] toArray(T... array)该方法要求传入一个数组,如果该数组可用(长度>=size)则直接将当前集合所有元素存入该数组后将其返回,如果数组不可用(长度不足)则会根据传入的数组类型自动创建一个与集合size等长的数组并将集合元素存入后返回*/String[] array = c.toArray(new String[c.size()]);System.out.println(Arrays.toString(array));}
}

4、数组转换为List集合---asList

数组转换为List集合

数组的工具类Arrays提供了一个静态方法:asList,可以将一个数组转换为一个List集合

package Collections;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 数组转换为List集合* 数组的工具类Arrays提供了一个静态方法:asList,可以将一个数组转换为* 一个List集合*/
public class ArrayToListDemo {public static void main(String[] args) {String[] array = {"a","b","c","d"};System.out.println("array: "+ Arrays.toString(array));List<String> list = Arrays.asList(array);System.out.println("list: " + list);/*对数组转换的List进行操作就是对原数组对应的操作*/list.set(1,"six");/*由于数组是定长的,因此该集合会影响元素个数的操作都是不支持的操作,会抛出异常:UnsupportedOperationException*///list.add("seven");System.out.println("list: " + list);System.out.println("array: "+ Arrays.toString(array));/*所有集合都支持一个参数为Collection的构造结构方法,作用是在创建当前集合的同时包含给定集合中的所有元素*/List<String> list2 = new ArrayList<>(list);//list2.addAll(list);System.out.println("list2: "+list2);list2.add("seven");System.out.println("list2: "+list2);}
}

5、变长参数

package Collections;import java.util.Arrays;/*** JDK5 时推出的另一个特性:变长参数* 一个方法中只能声明一个变长参数,并且必须是最后一个参数*/
public class ArgDemo {public static void main(String[] args) {dosome(1,"a");dosome(2,"a","b");dosome(3,"a","b","c","d");}public static void dosome(int i,String... s){/*变长参数在方法中实际上就是一个数组。给变成参数传入了几个实参,该数组长度与实参个数一致*/System.out.println(s.length);System.out.println("s: "+ Arrays.toString(s));}
}

6、自然排序---sort

java.util.Collections 是集合的工具类,里面提供了很多静态方法帮助我们

操作集合,其中sort方法可以对List集合进行自然排序(从小到大)

package Collections;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;/*** java.util.Collections 是集合的工具类,里面提供了很多静态方法帮助我们* 操作集合,其中sort方法可以对List集合进行自然排序(从小到大)*/
public class SortListDemo {public static void main(String[] args) {List<Integer> list = new ArrayList<>();Random random = new Random();for (int i=0;i<10;i++){int num = random.nextInt(100);list.add(num);}System.out.println(list);Collections.sort(list);System.out.println(list);}
}

7、排序自定义类型元素---Comparable

Collections.sort(List list) 该方法在排序集合时要求集合元素类型必须实现接口:Comparable 该接口定义了一个抽象方法:comparaTo,用来定义实例之间的比较 大小规则:

因此只有实现了这个接口的元素才可以比较大小从而进行排序。

实际开发中如果我们发现sort方法排序List集合时出现上述问题, 不要让元素实现该接口,因为这个操作具有侵入性 侵入性: 当我们使用一个API时,调用该方法时要求我们为其修改其他额外代码, 这个行为就是侵入性,侵入性不利于程序的后期维护,应当尽量避免

Comparator接口是比较器接口,其中定义了抽象方法compare用于定义 两个元素的比较规则,

该方法的返回值要遵循的原则为:

当返回值>0时,表示o1>o2

当返回值<0时,表示o1<o2

当返回值=0时,表示o1=o2

package Collections;import java.util.*;/*** 排序自定义类型元素*/
public class SortListDemo2 {public static void main(String[] args) {List<Point> list = new ArrayList<>();list.add(new Point(3,4));list.add(new Point(9,8));list.add(new Point(13,15));list.add(new Point(5,1));list.add(new Point(2,3));list.add(new Point(1,1));System.out.println(list);/*Collections.sort(List list)该方法在排序集合时要求集合元素类型必须实现接口:Comparable该接口定义了一个抽象方法:comparaTo,用来定义实例之间的比较大小规则:因此只有实现了这个接口的元素才可以比较大小从而进行排序。实际开发中如果我们发现sort方法排序List集合时出现上述问题,不要让元素实现该接口,因为这个操作具有侵入性侵入性: 当我们使用一个API时,调用该方法时要求我们为其修改其他额外代码,这个行为就是侵入性,侵入性不利于程序的后期维护,应当尽量避免*///Collections.sort(list);/*Comparator接口是比较器接口,其中定义了抽象方法compare用于定义两个元素的比较规则,该方法的返回值要遵循的原则为:当返回值>0时,表示o1>o2当返回值<0时,表示o1<o2当返回值=0时,表示o1=o2*/Collections.sort(list, new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {int len1 = o1.getX()*o1.getX()+o1.getY()+o1.getY();int len2 = o2.getX()*o2.getX()+o2.getY()+o2.getY();return len1-len2;
//                if(len1>len2){
//                    //正序排序
//                    return -1;
//                }else if(o1.getX() == o2.getX()){
//                    return  0;
//                }else {
//                    //倒序排序
//                    return 1;
//                }}});System.out.println(list);for (Point p : list){System.out.println(p);}}
}

8、队列---java.util.Queue

java.util.Queue接口。队列

Queue继承自Collection

队列可以保存一组元素,但是存取元素必须遵循先进先出原则: FIFO

First Input First Output

常用实现类:LinkedList

1、E poll()--出队操作,获取并删除队首元素

2、E peek()--引用队首元素,获取队首元素后不做出队操作

package Collections;import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;/*** java.util.Queue接口。队列* Queue继承自Collection* 队列可以保存一组元素,但是存取元素必须遵循先进先出原则: FIFO* First Input First Output* 常用实现类:LinkedList*/
public class QueueDemo {public static void main(String[] args) {Queue<String> queue = new LinkedList();/*boolean offer(E e)入队操作,将元素添加到队列末尾。*/queue.offer("one");queue.offer("two");queue.offer("three");queue.offer("four");queue.offer("five");System.out.println(queue);/*E poll()出队操作,获取并删除队首元素*/String s = queue.poll();System.out.println(s);System.out.println(queue);/*E peek()引用队首元素,获取队首元素后不做出队操作*/s = queue.peek();System.out.println(s);/*由于队列是集合的实现类,因此可以使用迭代器(新循环)来遍历并且遍历不影响元素在队列中的存在*/for (String str : queue){System.out.println(str);}System.out.println("-------------");// 使用poll方法遍历(一次性的)while(queue.size()>0){String e = queue.poll();System.out.println(e);}System.out.println(queue);}
}

9、双端队列---java.util.Dequq

双端队列 java.util.Deque

Deque继承自Queue()

双端队列是队列两端都可以做出入对操作的队列

常用实现类: LinkedList

package Collections;import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;/*** 双端队列 java.util.Deque* Deque继承自Queue* 双端队列是队列两端都可以做出入对操作的队列* 常用实现类: LinkedList*/
public class DequDemo {public static void main(String[] args) {Deque<String> deque = new LinkedList<>();deque.offer("one");deque.offer("two");deque.offer("three");deque.offer("four");deque.offer("five");System.out.println(deque);//offerFirst 从队首方向入队deque.offerFirst("six");System.out.println(deque);//offerLast 从对尾方向入队deque.offerLast("seven");System.out.println(deque);//队首方向出队String str = deque.pollFirst();System.out.println(str);System.out.println(deque);//队尾方向出队str = deque.pollLast();System.out.println(str);System.out.println(deque);}
}

10、栈结构----方法(pop和push)

栈结构

栈可以保存一组元素,但是存取元素必须遵循先进后出的原则

双端队列如果只调用从同一侧出队操作就形成了栈结构,因此双端队列

也为栈结构提供了经典的方法:push和 pop

package Collections;import java.util.Deque;
import java.util.LinkedList;/*** 栈结构* 栈可以保存一组元素,但是存取元素必须遵循先进后出的原则* 双端队列如果只调用从同一侧出队操作就形成了栈结构,因此双端队列* 也为栈结构提供了经典的方法:push和 pop*/
public class StackDemo {public static void main(String[] args) {Deque<String> stack = new LinkedList<>();stack.push("one");stack.push("two");stack.push("three");stack.push("four");stack.push("five");System.out.println(stack);String str = stack.pop();System.out.println(str);System.out.println(stack);for (String s : stack){System.out.println(s);}System.out.println(stack);while (stack.size()>0){String s = stack.pop();System.out.println(s);}System.out.println(stack);}
}

11、并发安全的集合

并发安全的集合

Collections提供了将当前集合转化为并发安全集合的方法,在多线程并发操作集合时应当使用并发安全的集合

ArrayList,LinkedList,HashSet都不是并发安全的集合

  • JDK8之后,java推出了一种新的遍历集合的方法 Collection中添加了forEach方法,可以通过lambda表达式 形式遍历集合元素。由于该方法是集合自身方法,因此可以和集合自身其他操作(比如增删改查)互斥.因此在多线程操作集合时我们首先要求集合要使用并发安全的集合,并且遍历操作采用forEach进行

package Collections;import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;/*** 并发安全的集合* Collections提供了将当前集合转化为并发安全集合的方法,在多线程* 并发操作集合时应当使用并发安全的集合** ArrayList,LinkedList,HashSet都不是并发安全的集合*/
public class SyncCollectionDemo {public static void main(String[] args) {List<String> list = new LinkedList<>();list.add("one");list.add("two");list.add("three");list.add("four");list.add("five");System.out.println(list);//将给定的List集合转化为一个线程安全的List集合list = Collections.synchronizedList(list);System.out.println(list);/*JDK8之后,java推出了一种新的遍历集合的方法Collection中添加了forEach方法,可以通过lambda表达式形式遍历集合元素。由于该方法是集合自身方法,因此可以和集合自身其他操作(比如增删改查)互斥.因此在多线程操作集合时我们首先要求集合要使用并发安全的集合,并且遍历操作采用forEach进行*/
//        list.forEach(new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });//list.forEach(s-> System.out.println(s));list.forEach(System.out::println);}
}

11、Map

java.util.Map 接口,查找表

  • Map体现的结构时一个多行两列的表格,其中左列称为key,右列称为value

  • Map总是根据key获取value,并且要求key不允许重复

  • java.util.HashMap:最常用的Map实现类,称为散列表或哈希表,是当今查询速度最快的数据结构。

  • 使用散列算法实现的Map

  • Map的泛型需要指定两个,分别对key和value指定类型

  • Map的泛型需要指定两个,分别对key和value指定类型

V put(K k,V v)方法:

  • 将给定的一组键值对存入到Map中.由于Map中的key不允许重复,如果给定的key不重复则存入后返回值为null 如果给定的key值时重复的,则是替换value操作,将新的value存入后返回的是这个key原来对应的value。 key是否重复是依靠key自身的equals方法比较的结果。

V get(K k)方法

  • 根据给定的key获取对应的value,如果给定的key在Map中不存在则返回值为null

package map;import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;/*** java.util.Map 接口,查找表* Map体现的结构时一个多行两列的表格,其中左列称为key,右列称为value* Map总是根据key获取value,并且要求key不允许重复** java.util.HashMap:最常用的Map实现类,称为散列表或哈希表,是当今查询速度最快的数据结构。* 使用散列算法实现的Map*/
public class MapDemo {public static void main(String[] args) {/*Map的泛型需要指定两个,分别对key和value指定类型*/Map<String,Integer> map  = new HashMap();/*V put(K k,V v)将给定的一组键值对存入到Map中.由于Map中的key不允许重复,如果给定的key不重复则存入后返回值为null如果给定的key值时重复的,则是替换value操作,将新的value存入后返回的是这个key原来对应的value。key是否重复是依靠key自身的equals方法比较的结果。*/map.put("语文",59);map.put("数学",60);map.put("英语",63);map.put("生物",65);map.put("体育",46);System.out.println(map);//替换valueint value = map.put("英语",66);System.out.println(map);System.out.println("value: "+value);/*V get(K k)根据给定的key获取对应的value,如果给定的key在Map中不存在则返回值为null*/value = map.get("数学");System.out.println("数学: "+value);value = map.get("体育");System.out.println("体育: "+value);int size = map.size();System.out.println("size: "+size);/*V remove(K k)从Map中删除给定的key所对应的这组键值对,返回值为这个key对应的value*/value = map.remove("英语");System.out.println(map);System.out.println("value: "+value);/*boolean containsKey(K k)判断当前Map是否包含给定的keyboolean containsValue(V v)判断当前Map是否包含给定的value*/boolean ck = map.containsKey("语文");System.out.println("包含value: "+ck);boolean cv = map.containsValue("63");System.out.println("包含value: "+cv);}
}

2、Map的遍历

Map的遍历。Map支持三种遍历方式:

  • 1、遍历所有的key

  • 2、遍历所有的Value

  • 3、以键值对方式

2.1)遍历所有的key

  • Set<K> KeySet() 将当前Map中所有的Key以一个Set集合形式返回

2.2)遍历每一组键值对

  • Set<Entry> entrySet() 将当前Map中每一组键值对以一个Entry实例表示并最终以Set集合返回 java.util.Map.Entry 它的每一个实例表示Map中的一组键值对

2.3)遍历所有的value

  • Collection<V> values() 将当前Map中所有的value以一个集合形式返回

package map;import java.util.*;/*** Map的遍历。Map支持三种遍历方式:* 1、遍历所有的key* 2、遍历所有的Value* 3、以键值对方式*/
public class MapDemo2 {public static void main(String[] args) {Map<String,Integer> map = new HashMap<>();map.put("语文",99);map.put("数学",90);map.put("英语",93);map.put("生物",95);map.put("体育",96);System.out.println(map);/*遍历所有的keySet<K> KeySet()将当前Map中所有的Key以一个Set集合形式返回*/Set<String> keySet = map.keySet();keySet.forEach(System.out::println);/*遍历每一组键值对Set<Entry> entrySet()将当前Map中每一组键值对以一个Entry实例表示并最终以Set集合返回java.util.Map.Entry 它的每一个实例表示Map中的一组键值对*/Set<Map.Entry<String,Integer>> entrySet = map.entrySet();entrySet.forEach(e-> System.out.println(e.getKey()+" : "+e.getValue()));//Map在JDK8之后也提供了forEach方法直接遍历每一组键值对map.forEach((k,v)-> System.out.println(k+" : "+v));/*Iterator it = map.entrySet().iterator();while(it.hasNext()){Map.Entry entry = (Map.Entry) it.next();System.out.println("headname: "+entry.getKey());System.out.println("headkey: "+entry.getValue());}*//*遍历所有的valueCollection<V> values()将当前Map中所有的value以一个集合形式返回*/Collection<Integer> values = map.values();values.forEach(v-> System.out.println(v));}
}

12、Java反射

1、java反射机制

  • 反射是java的动态机制,它将原来写程序时进行的实例化操作以及操作属性,调用

  • 方法从编码期间确定转移到在程序运行期间确定.这大大的提高了代码的灵活度.

  • 但是反射带来了更多的系统开销和较慢的运行效率,因此仅在必要地方使用而不是过度的依赖反射

  • 使用反射机制操作一个类时,第一步就是获取该类的类对象 Class的实例: JVM中每个被加载的类有且只有一个Class实例与之对应, 这个Class的实例称为这个类的"类对象".通过类对象我们可以 在程序运行期间获取到该类的一切信息(类名,有那些方法,属性,构造器等等) 从而进行对应的操作. 获取一个类的类对象有三种方式: 1:类名.class 例如: Class cls = String.class; Class cls = int.class; 这种方式比较直接,但是缺点是硬编码获取一个类的类对象,不灵活. 注:基本类型获取类对象的方式只有这一种

    2:Class.forName(String className) 例如: Class cls = Class.forName("java.lang.String");

    3:类加载器ClassLoader

package reflect;/*** 使用当前类测试反射机制*/
public class Person {private String name = "张三";private int age = 18;public Person(){}public Person(String name){this.name = name;}public Person(String name,int age){this.name = name;this.age = age;}public void sayHello(){System.out.println("Person:大家好!");}public void sayHi(){System.out.println("Person:嗨!");}public void playGame(){System.out.println("Person: 一起打游戏啊!");}public void say(String name,String info){System.out.println("我是"+name+","+info);}public void say(String name,int sum){for (int i=0;i<sum;i++){System.out.println("我是"+name);}}private void hehe(){System.out.println("我是Person的私有方法...");}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}}
package reflect;import java.lang.reflect.Method;
import java.util.Scanner;/*** java反射机制* 反射是java的动态机制,它将原来写程序时进行的实例化操作以及操作属性,调用* 方法从编码期间确定转移到在程序运行期间确定.这大大的提高了代码的灵活度.* 但是反射带来了更多的系统开销和较慢的运行效率,因此仅在必要地方使用而不是过度的依赖反射*/
public class ReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {/*使用反射机制操作一个类时,第一步就是获取该类的类对象Class的实例:JVM中每个被加载的类有且只有一个Class实例与之对应,这个Class的实例称为这个类的"类对象".通过类对象我们可以在程序运行期间获取到该类的一切信息(类名,有那些方法,属性,构造器等等)从而进行对应的操作.获取一个类的类对象有三种方式:1:类名.class例如:Class cls = String.class;Class cls = int.class;这种方式比较直接,但是缺点是硬编码获取一个类的类对象,不灵活.注:基本类型获取类对象的方式只有这一种2:Class.forName(String className)例如:Class cls = Class.forName("java.lang.String");3:类加载器ClassLoader*///获取String的类对象//Class cls = String.class;// Class cls = Class.forName("java.lang.String");/*java.lang.String,java.util.ArrayListjava.io.FileInputStreamreflect.Person*/Scanner cin = new Scanner(System.in);System.out.println("请输入一个类名: ");String name = cin.nextLine();Class cls = Class.forName(name);//获取该类的万全限定名(包名.类名)String className = cls.getName();System.out.println("类名: "+className);//仅获取类名className = cls.getSimpleName();System.out.println("类名: "+className);/*通过类对象获取该类所有的公开方法*/Method[] methods = cls.getMethods();System.out.println(className+"类有:"+methods.length+"个方法");for (Method m : methods){System.out.println(m.getName());}}
}

2、使用反射进行实例化操作:

package reflect;import java.util.Scanner;/*** 使用反射进行实例化操作*/
public class ReflectDemo2 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//        Person p = new Person();
//        System.out.println(p);//1:获取类对象
//       Class cls = Class.forName("reflect.Person");Scanner cin = new Scanner(System.in);System.out.println("请输入要实例化的类名: ");String className = cin.nextLine();Class cls = Class.forName(className);//类对象提供了快速实例化方法(仅限无参构造器)//返回值以Object形式返回.具体类型要看Class表示的是那个类/*Object o = cls.newInstance();System.out.println(o);*/Person obj = (Person)cls.newInstance();obj.sayHello();}
}

3、使用指定的构造器进行实例化操作

package reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;/*** 使用指定的构造器进行实例化操作*/
public class ReflectDemo3 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class cls = Class.forName("reflect.Person");System.out.println(cls.getConstructors());Constructor c = cls.getConstructor(String.class);//Person(String name)Object obj = c.newInstance("王武");System.out.println(obj);//Person(String name,int age)Constructor c2 = cls.getConstructor(String.class,int.class);obj = c2.newInstance("赵六",50);System.out.println(obj);Person p = (Person)cls.newInstance();p.playGame();}
}

4、使用反射机制调用方法

package reflect;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;/*** 使用反射机制调用方法*/
public class ReflectDemo4 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//        //实例化
//        Class cls = Class.forName("reflect.Person");
//        Object obj =  cls.newInstance();//new Person
//
//        //获取方法
//        Method m = cls.getMethod("sayHello");
//        //第一个参数为该方法的所属对象
//        m.invoke(obj);  //p.sayHello()Scanner cin = new Scanner(System.in);System.out.println("请输入类名: ");String className = cin.nextLine();System.out.println("请输入方法名: ");String methodName = cin.nextLine();Class cls = Class.forName(className);Object obj = cls.newInstance();Method m = cls.getMethod(methodName);m.invoke(obj);}
}

5、使用反射机制访问类的私有成员

  • 注意:此操作会破坏类的封装性.

package reflect;import java.lang.reflect.Method;/*** 使用反射机制访问类的私有成员** 注意:此操作会破坏类的封装性*/
public class ReflectDemo5 {public static void main(String[] args) throws Exception {Class cls = Class.forName("reflect.Person");Object obj = cls.newInstance();System.out.println(obj);//say(String,String)Method m = cls.getMethod("say", String.class, String.class);m.invoke(obj,"凡凡","人称小钢炮");//say(String name,int num)Method m2 = cls.getMethod("say", String.class, int.class);m2.invoke(obj,"怪怪",5);}
}

6、调用私有方法

package reflect;import java.lang.reflect.Method;/*** 调用私有方法*/
public class ReflectDemo6 {public static void main(String[] args) throws Exception {ReflectDemo6 ref = new ReflectDemo6();ref.fun("Person","hehe");
//        Class cls = Class.forName("reflect.Person");
//        Object obj = cls.newInstance();
//
//        /*
//            getDeclaredMethod是获取本类自己定义的方法(含私有方法)
//         */
//        Method m = cls.getDeclaredMethod("hehe");
//        m.setAccessible(true);  //强行设置为可访问
//        m.invoke(obj);}public void fun(String className,String methodName) throws Exception{Class cls = Class.forName("reflect."+className);Object obj = cls.newInstance();Method m = cls.getDeclaredMethod(methodName);m.setAccessible(true);m.invoke(obj);}
}

7、自动调用

package reflect;public class Student {private String name = "张小三";private int age = 10;private String gender = "男";public void study(){System.out.println("学生:好好学习,天天向上!");}public void sayHello(){System.out.println("大家好,我是学生:"+name);}public void play(){System.out.println("学生:一起做游戏~");}
}
package reflect;import java.lang.reflect.Method;/*** 自动调用*/
public class Test {public static void main(String[] args) throws Exception {//自动调用Student类中名字里含有s的方法(本类方法,不含超类继承的)Class cls = Class.forName("reflect.Student");Object obj = cls.newInstance();System.out.println(obj);Method[] methods = cls.getDeclaredMethods();  //获取所有的方法System.out.println(methods);for (Method m : methods){System.out.println(m.getName()+",参数个数:"+m.getParameterCount());if (m.getName().contains("s")&&m.getParameterCount()==0){   //方法含有s且参数个数为0m.invoke(obj);}}}
}
package reflect;import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Calendar;/*** 自动调用reflect包中所有的类,并自动调用他们本类定义中的* 含有"s"的无参构造方法*/
public class Test2 {public static void main(String[] args) throws Exception{/*找到和Test2.class在同一目录中文件注意!!不是和Test2.java源码所在同一目录中!IDEA将源码编译后都放在了项目目录下的target/classes下了*///System.out.println(Test2.class.getResource("./test.txt"));/*通过Test2.class.getClassLoader()类加载器开始寻找资源时,此时相对路径就是当前项目所有类编译后的字节码文件同一所在的目录,就是当前类的包的上一级.例如当前类Test2包定义为:package reflect;那么这里的路径就是reflect所在的目录例如Test2的包路径为:packet com.webserver.core;那么这里的路径就是com所在的目录*///System.out.println(Test2.class.getClassLoader().getResource("./reflect/test.txt"));URL url =  Test2.class.getClassLoader().getResource("reflect");   //定位到reflect目录下File dir = new File(url.toURI());File[] subs = dir.listFiles(e->e.getName().endsWith(".class")   //选取所有的class文件);for (File file : subs){String fileName = file.getName();int index = fileName.lastIndexOf(".");fileName = fileName.substring(0,index);//System.out.println(fileName);Class cls = Class.forName("reflect."+fileName);Object obj = cls.newInstance();//System.out.println(obj);//System.out.println(cls);Method[] methods = cls.getDeclaredMethods();//System.out.println(methods);
//            System.out.println(methods);for (Method m : methods){if (m.getName().contains("s")&&m.getParameterCount()==0){m.invoke(obj);}}}}
}

Java Api知识点相关推荐

  1. java基础知识点_「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !

    " 本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指 ...

  2. java api 设计_Java API设计实践

    使你的API在模块化和非模块化Java环境中都可用 在优锐课的java学习分享中,对微服务有了更深层次的新概念.关于API设计实践一点就通了. 介绍 了解设计Java API时应应用的一些API设计实 ...

  3. Java 面试知识点解析(七)——Web篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  4. Java 面试知识点解析(五)——网络协议篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  5. Java 面试知识点解析(二)——高并发编程篇

    前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...

  6. Java四大知识点讲解,初学者必看

    自学Java的初学者先弄清这些Java的基本概念也是必不可少的,死记硬背肯定是不行的,重在理解,理解它们之间的区别与联系,分别有哪些应用.想想这些代码中用到了哪些知识点.不要一味地照着书本敲代码.而不 ...

  7. HBase应用笔记:通过Java Api与HBase交互(转自 Taobao QA Team)

    http://blog.sina.com.cn/s/blog_66474b1601017hvx.html http://www.cnblogs.com/eprsoft/archive/2012/10/ ...

  8. java基础案例教程前4章知识点_java学习记录4 Java基础知识点

    java学习记录4 Java基础知识点 1. 注释 单行注释 使用"//"开头,后面是注释的内容 一般在要注释的语句的上面加注释 多行注释 以"/*"开头,以& ...

  9. java基础知识点整理一

    java基础知识点整理一 引言 '''突然发觉任何一门语言的基础知识部分,都比较杂一些.如果个人经过梳理之后,知识体系系统化,可以让基础更加牢靠一些.但是还是会有一些遗忘.所以,我想把一些比较重要但是 ...

最新文章

  1. 前端碎碎念 之 nextTick, setTimeout 以及 setImmediate 三者的执行顺序
  2. 贝叶斯网络结构学习之K2算法(基于FullBNT-1.0.4的MATLAB实现)
  3. HDU 1425 sort(堆排序)
  4. java工程前面有个红色感叹号
  5. Keepalived实现LVS的高可用全解析
  6. LeetCode:跳跃游戏【55】
  7. python绘制饼图双层_如何在python中绘制双变量数据的饼图?
  8. 数据结构笔记(二十二)--已知先序中序求树
  9. android向web提交数据,中文乱码
  10. 微信如何html动图文件,微信里的gif动态图片如何导出保存出来?看完本文你就知道了...
  11. html中的颜色代码详解及图示
  12. PRD 算法 Golang 实现
  13. OSPF的6种LSA
  14. IDV和IDV的发展简史
  15. Ros yocs_velocity_smoother 保姆级部署教程
  16. bootstrap 让文字显示在响应式图片上
  17. 林深时见鹿,海蓝时见鲸
  18. 如何获取淘宝/天猫店铺的所有商品 API数据
  19. Java筑基——反射(1):基本类周边信息获取
  20. 内存单通道和双通道是什么意思

热门文章

  1. 02数据存入数据库-视频网站-实践-scrapy框架-python
  2. 粪菌移植到底谁在起作用?
  3. 在线RSA加密解密,RSA2加密解密(SHA256WithRSA)
  4. C#之自动提交表单登录QQ空间...
  5. spark:计算订单中所有商品是否属于套包
  6. 熊伟康 计算机学院,为“博出位”成人穿童装 网上晒照片惹争议
  7. 客运综合管理系统项目—报班统计(车辆调度报班)
  8. 【爬虫】【Python】自动下载网络视频代码
  9. 通过PS把普通照片变成高大上的电影海报大片
  10. 用友U8CO接口开发方式之映射(二)