javaSE高级部分:

1 多线程:

创建多线程的方式:
1 继承Thread类

​ 步骤:

​ 1 创建一个继承于Thread类的子类

​ 2 重写Thread类的run(),将线程需要执行的操作声明在此方法中

​ 3 创建Thread类的子类的对象,并通过此对象调用start()

​ 问题一:不能直接调用run()启动线程,需要调用start()

​ 问题二:若要启动一个新的线程,不能让已经start的线程去执行,可以创建一个新的线程对象去调用start()

2 实现Runnable接口

​ 步骤:

​ 1 创建一个实现Runnable接口的类

​ 2 实现类去实现Runnable接口的抽象方法run()

​ 3 创建实现类的对象,并将此对象作为形参传到Thread类的构造器中创建Thread类的对象

​ 4 通过Thread类的对象调用start()

​ 1、2两种创建方式的对比:

​ 1 开发中优先选用实现Runnable接口的方式创建多线程

​ 2 原因:实现Runnable接口的方式没有单继承的局限性,并且更适合处理多个线程有共享数据的情况

​ 3 二者关系:Thread类也实现了Runnable接口,两种方式都需要重写run(),将线程需要执行的操作声明在其中

3 实现Callable接口 —jdk5.0新增
步骤:
*     1  创建一个实现Callable的实现类
*     2  实现call()方法,将此线程需要执行的操作声明在call()中
*     3  创建Callable接口实现类的对象
*     4  将Callable接口实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask对象
*     5  将FutureTask对象作为参数传递到Thread类的构造器中创建Thread类的对象并调用start()
*     6  可以获取Callable中call方法的返回值
* 如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程强大?
*     1  call()方法可以有返回值
*     2  call()可以抛出异常被外面捕获
*     3  Callable支持泛型
*     4  需要借助FutureTask类,   例如获取返回结果 ---> futureTask.get()
* Future接口:
*     1  可以对Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。
*     2  FutureTask是Future接口的唯一实现类
*     3  FutureTask同时实现了Runnable、Future接口。它既可以作为Runnable接口被线程执行,
*      也可以作为Future得到Callable的返回值代码演示:public static void main(String[] args) {MyThread1 m = new MyThread1();FutureTask<Integer> futureTask = new FutureTask(m);new Thread(futureTask).start();try {// 如果对call()方法的返回值不敢兴趣就不需要调用get(),  get()方法的目的只是为了获取call()方法的返回值// get()方法的返回值即为FutureTask构造器参数Callable实现类重写的call()方法的返回值Integer sum = futureTask.get();System.out.println(sum);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}
4 使用线程池
* 创建多线程的方式四:  使用线程池
*
* 使用线程池的优点:
*    1 提高响应速度 (减少了创建新线程的时间)
*    2 降低资源消耗 (重复利用线程池中的线程,不需要每次都创建)
*    3 便于线程的管理
*       corePoorSize:核心池的大小
*       maximumPoolSize:最大线程数
*       keepAliveTime:线程没有任务时最多保持多长时间后会终止
* 步骤:// 1 提供指定线程数量的线程池ThreadPoolExecutor service = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);// 2 设置线程池的属性
//        service.setCorePoolSize(15);// 3 执行指定的线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象service.execute(new MyThread2());   // 适合用于Runnable
//        service.submit();  适合用于Callableservice.execute(new MyThread3());service.shutdown();  // 4  关闭线程池
Thread类中的常用方法:

​ 1 start():启动当前线程,并调用当前线程的run()

​ 2 run():通常需要重写Thread类中的此方法,将当前线程需要执行的操作声明在此方法中

​ 3 currentThread():Thread类中的静态方法,用来获取执行当前代码的线程

​ 4 getName()/setName():获取/设置当前线程名称

​ 5 yield():Thread类的静态方法,释放当前cpu执行权

​ 6 join():在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b完全执行完之后线程a才开始执行

​ 7 stop():不推荐使用,已经过时。当执行此方法时,强制结束当前线程

​ 8 sleep():Thread类的静态方法,使当前线程睡眠指定的毫秒数,在睡眠中,当前线程处于阻塞状态

​ 9 isAlive():判断当前线程是否存活

​ 10 线程优先级的设置:

​ 1> Thread类的静态属性:

​ MAX_PRIORITY:10

​ MIN_PRIORITY:1

​ NORM_PRIORITY:5 (默认的优先级)

​ 2> 获取和设置当前线程的优先级:

​ getPriority():获取当前线程的优先级

​ setPriority():设置当前线程的优先级

解决线程安全问题的方式一:同步代码块

​ 1 synchronized(同步监视器){

​ // 需要被同步的代码(即多个线程共同操作共享数据的代码)--------------->不能包含多了,也不能包含少了

​ }

​ 2 说明:

​ 1 操作共享数据的代码即为需要被同步的代码

​ 2 共享数据:多个线程共同操作的变量,例如例题的ticket

​ 3 同步监视器(锁):任何一个类的对象都可以充当锁,但多个线程必须要共用一把锁

​ 3 同步的利弊:

​ 1 使用同步的方式解决了线程的安全问题 ----------------->优点

​ 2 操作同步的代码时,只能有一个线程参与,其他线程等待,相当于一个单线程的过程 ----------------->局限性

解决线程安全问题的方式二: 同步方法

​ 1 使用方法: 在需要被同步的方法的返回值前加synchronized

​ 2 同步方法:

​ 1 同步方法仍然涉及到同步监视器,只是不需要我们显式的声明

​ 2 非静态的同步方法,同步监视器是this

​ 3 静态的同步方法,同步监视器是当前类本身

解决线程安全问题的方式三: Lock锁

​ synchronized和Lock的对比

​ 1 Lock是显式锁(需要手动的开启和关闭锁,不要忘记关闭锁),synchronized是隐式锁,出了作用域自动释放锁

​ 2 Lock只有代码块锁,synchronized有代码块锁和方法锁

​ 3 使用Lock锁,JVM花费更少的时间调度线程,性能更好,有更好的扩展性(提供了更多的子类)

​ 4 使用的优先顺序: Lock > 同步代码块 > 同步方法

线程通信:

​ 1 线程通信中涉及到的三个方法:

​ 1 wait():一旦执行此方法,当前线程就会进入阻塞状态,并释放锁

​ 2 notify():一旦执行此方法,就会唤醒正在wait的一个线程(注意是一个),如果有多个线程被wait,则唤醒优先级最高的

​ 3 notifyAll():一旦执行此方法,就会唤醒所有被wait的线程

​ 2 补充说明:

​ 1 wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中

​ 2 wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的锁,否则会出现异常

​ 3 wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中的

sleep()和wait()的异同?

​ 1 相同点:一旦执行,都会使当前线程进入阻塞状态

​ 2 不同点:

​ 1 两个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait()

​ 2 调用的要求不同:sleep()可以在任何场景下使用,wait()方法必须使用在同步代码块或同步方法中

​ 3 关于是否释放锁:如果两个方法都声明在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁

单例模式懒汉式写法(并解决了线程的安全问题)
public class Bank {private static Bank instance = null;private Bank(){}public static Bank getInstance(){if(instance == null){synchronized (Bank.class){if(instance == null){instance = new Bank();}}}return instance;}
}

2 java常用类

String类的使用

​ 1 String:字符串,使用 " " 引起来表示

​ 2 String类声明为final的,不可以被继承

​ 3 String类实现了Serializable接口,表示字符串是支持序列化的

​ 4 String类实现了Comparable接口,表示String类的对象可以比较大小

​ 5 String内部定义了final修饰的 char[] value ,用于存储字符串数据

​ 6 String代表不可变的字符序列, 简称:不可变性

​ 体现:1 当对字符串重新赋值时,需要重新指定内存区域复制,不能使用原有的value赋值

​ 2 当对现有的字符串进行连接操作时,也需要重新制定内存区域赋值,不能使用原有value赋值

​ 3 当调用String类的replace()方法修改指定字符或字符串时,也需要重新指定内存区域,不能使用原有value

​ 理解:只要对一个字符串对象进行任何的操作都需要重新创建,原有的字符串不能变!!!

​ 7 通过字面量的(区别于new的方式)给一个字符串赋值,此时的字符串声明在字符串常量池中

​ 8 字符串常量池中是不会存储相同内容(用重写过的equals()方法比较的)的字符串

String类的实例化方式:

​ 1 通过字面量的方式直接定义

​ 2 通过 new + 构造器 的方式

​ 3 面试题:String s = new String(“abc”),用此方法创建String类的对象,在内存中共创建了几个对象呢?

​ 两个,一个是new 的String对象保存在堆空间中,另一个是char[]类型的对象,对应着常量池中的数据:“abc”,如果字符

​ 串常量池中已经有"abc",则只需要创建一个String类型的对象,因为字符串常量池中不会存储相同内容的字符串,如果有就直

​ 接用现成的

@Test
// String不同拼接操作的对比
/*** 总结:*    1 常量与常量的拼接结果依然在常量池,并且常量池中不会存在相同内容的常量*    2 字符串拼接过程中只要有一个是变量,那么拼接的结果就在堆中,相当于new了一个字符串对象在堆空间中*    3 如果拼接的结果调用intern()方法,其返回值就在字符串常量池中找。**/
public void test3(){String s1 = "Cookie";String s2 = "Rookie";String s3 = "Cookie" + "Rookie";String s4 = s1 + "Rookie";String s5 = s1 + s2;String s6 = "Cookie" + s2;String s7 = s6.intern();String s8 = "CookieRookie";System.out.println(s3 == s8); //tureSystem.out.println(s3 == s4); //falseSystem.out.println(s3 == s5); //falseSystem.out.println(s4 == s5); //falseSystem.out.println(s4 == s6); //falseSystem.out.println(s5 == s6); //falseSystem.out.println(s5 == s7); //falseSystem.out.println(s6 == s7); //falseSystem.out.println(s3 == s7); //tureSystem.out.println(s8 == s7); //ture}
String类和其他结构之间的转换:

​ 1 String与基本数据类型、包装类之间的转换:

​ String----->基本数据类型、包装类:调用包装类的静态方法:parse xxx(str)

​ 基本数据类型、包装类----->String:调用String重载的静态方法valueOf(xxx)

​ 2 String与char[]之间的转换:

​ String------->char[]:调用String类的toCharArray()方法

​ char[]------->String:调用String类的构造器

​ 3 String与字节数组byte[]之间的替换:

​ String------->byte[]:调用String类的getBytes(),也就是编码的过程

​ byte[]------->String:调用String类的构造器,也就是解码的过程

​ 4 对于编码和解码的理解(编码集了解部分请看下文)

​ 编码:字符串(我们能看懂的那些字符)---->字节(底层的那些数字):看得懂的---->看不懂的二进制数

​ 解码:编码的逆过程 字节----->字符串:看不懂的二进制数------>看得懂的

​ 说明:解码时要求解码使用的字符集必须和编码使用的字符集一致,否则会出现乱码问题。

String类的常用方法:

​ 1 System.out.println(s1.length()); // 获取s1字符串的长度,底层为char[] 的长度

​ 2 System.out.println(s1.charAt(0)); // 获取指定索引处的字符

​ 3 System.out.println(s1.isEmpty()); // 判断s1是否为空

​ 4 System.out.println(s1.toLowerCase()); // 将s1字符串对象的内容全部转换为小写

​ 5 System.out.println(s1.toUpperCase()); // 将s1字符串对象的内容全部转换为大写

​ 6 String s3 = s2.trim(); // 去掉字符串开头和结尾的空格,中间的空格不变。

​ 7 System.out.println(s1.equalsIgnoreCase(s2)); // 比较s1和s2字符串的内容,忽略大小写

​ 8 String s4 = s3.concat(“def”); // 将指定字符串连接到此字符串的结尾,相当于"+"

​ 9 System.out.println(s5.compareTo(s6)); // 比较两个字符串的大小 a为97,b为98,c为99,此方法涉及到字符串排序

​ 10 String s8 = s7.substring(2); // 获取指定区间内的字符串内容,一个参数时终止索引到结尾

​ 11 String s9 = s7.substring(2, 4); // 获取指定区间内的字符串内容,两个参数时左闭右开。

​ 12 boolean b1 = s1.endsWith(“rld”); // 判断此字符串是否以指定的后缀结束

​ 13 boolean b2 = s1.startsWith(“hel”);// 判断此字符串是否以指定的前缀开始

​ 14 boolean b3 = s1.startsWith(“ll”, 2);// 判断此字符串从指定索引开始的子字符串是否以指定的前缀开始的

​ 15 System.out.println(s1.contains(s2)); // 判断此字符串中是否包含指定的字符串

​ 16 System.out.println(s1.indexOf(“Wo”)); // 返回指定字符串在此字符串中第一此出现处的索引值,如果没有出现返回-1

​ 17 System.out.println(s1.indexOf(“lo”,5)); // 返回指定字符串在此字符串中第一此出现处的索引值,从指定索引位置开始查

​ 找,如果没有出现返回-1

​ 18 System.out.println(s3.lastIndexOf(“or”)); // 返回指定字符串在此字符串中第一此出现处的索引值,从结尾反向查找,

​ 如果没有出现返回-1,索引值依然是从前往后数。

/*** 什么情况下 indexOf(str) 和 lastIndexOf(str)返回值相同?* 1 指定字符串中只存在唯一的一个str* 2 指定字符串中不存在str*/

​ 19 String s2 = s1.replace(‘o’, ‘a’);// 将原有字符串的字符替换为指定字符,替换所有

​ 20 String s3 = s1.replace(“He”, “aa”); // 使用指定的字面值替换原有字符串的字面值,形参相当于字符串,替换所有

​ 21 String s4 = s1.replaceFirst(“lo”, “ao”); // 将原有字符串的子字符串替换为指定字符串,只替换第一处

​ 22 boolean matches = str.matches("\d+"); // 判断原有的字符串是否匹配指定的正则表达式

​ 23 String str2 = str1.replaceAll("\d+", “,”).replaceAll("^,|,$", “”);// 将原有字符串满足指定正则表达式或指定字符串的部分

​ 替换为指定的字符串

​ 24 String[] split = str3.split("\."); // 根据指定的正则表达式或字符串将原有字符串进行拆分,返回一个String数组,形参为

​ 正则表达式或字符串

StringBuffer和StringBuilder的使用:
/*** 关于StringBuffer和StringBuilder的使用:* String、StringBuffer、StringBuilder三者的异同?* 相同点:*     三者底层都是使用char[]数组存储* 不同点:*     String:不可变的字符序列*     StringBuffer:可变的字符序列,线程安全,效率低。*     StringBuilder:可变的字符序列,线程不安全,效率高。** 源码分析:*     String s = new String(); // new char[0];*     String s1 = new String("abc");  // new char[]{'a','b','c'};**     StringBuffer sb = new StringBuffer(); // new char[16]; 相当于底层创建了一个长度是16的数组*     sb.append('a');  // value[0] = 'a';*     sb.append('b');  // value[1] = 'b';**     StringBuffer sb1 = new StringBuffer("abc");  // char[] value = new char["abc".length()+16]{'a','b','c'};** 问题1:System.out.println(sb1.length());  // 3* 问题2:底层数组的扩容问题:*       如果需要添加的数据底层数组装不下了,那么就需要扩容底层的数组。*       在默认的情况下,新的数组扩容到原来的  2倍+2 ,同时将原有数组的元素复制到新的数组中。*       在开发中建议大家使用的构造器:StringBuffer(int capacity) 或 StringBuilder(int capacity),*       在参数中指定底层创建的数组的长度,避免数组的扩容问题,使效率变高。* String,StringBuffer,StringBuilder三者效率的对比:*       StringBuilder > StringBuffer > String* String,StringBuffer,StringBuilder三者之间的转换:*       String---->StringBuffer:*             1 通过构造器的方式: new StringBuffer(str);*       StringBuffer---->String:*             1 通过构造器的方式: new String(sb);*             2 调用StringBuffer的toString(): sb.toString();*/
StringBuffer的常用方法(StringBuilder的方法和它一模一样)

1 sb.append(1); // 提供了很多重载的append()方法,用于进行字符串拼接

2 sb.delete(5,10); // 删除指定范围内的内容

3 sb.replace(2,3,“qaq”); // 将指定范围内的字符串替换为指定的字符串

4 sb.insert(2,“xuge”); // 在指定位置插入 xxx , 提供了很多重载的方法

5 sb.reverse(); // 将当前字符串逆转

6 System.out.println(sb.indexOf(“q”)); // 返回指定字符串在当前字符串第一次出现的位置的索引值

7 System.out.println(sb.substring(2,6)); // 返回当前字符串在指定范围内的子字符串

8 System.out.println(“当前字符串的长度为”+sb.length()); // 返回当前字符串的长度

9 System.out.println(sb.charAt(2)); // 获取指定索引位置的字符

10 sb.setCharAt(2,’@’); // 将指定位置的字符修改为指定字符

总结StringBuffer中最常用方法(StringBuilder一样)
/*** StringBuffer常用方法:*     总结:*       1 增:append(xxx)*       2 删:delete(int start,int end)*       3 改:setCharAt(int n,char ch) 或 replace(int start,int end,String str)*       4 查:charAt(int n)*       5 插:insert(int index,xxx)*       6 长度: length()*       7 遍历字符:for() + charAt()  或 toString() 主要看字符串的内容*/
jdk8之前日期和时间API测试
/*** jdk 8 之前日期和时间API测试**    获取当前时间戳:System.currentTimeMillis() 调用System类中的静态方法**    java.util.Date:*       1 两个构造器的使用:*           new Date(): 空参构造器,创建一个对应当前时间的Date对象*           new Date(162842143343l): 创建一个指定毫秒数的Date对象*       2 两个方法的使用:*           toString():显示当前的年月日时分秒*           getTime(): 返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差*    java.sql.Date:*       1 对应着数据库中的日期类型*       2 如何实例化:*           new java.sql.Date(162842143343l): 创建一个指定毫秒数的java.sql.Date对象*       3 两个方法的使用:*             toString():显示当前创建的java.sql.Date对象对应的年月日*             getTime(): 返回当前创建的java.sql.Date对象与1970年1月1日0时0分0秒之间以毫秒为单位的时间差* 如何将java.util.Date转换为java.sql.Date?*         Date date = new Date();*         Date date1 = new java.sql.Date(date.getTime());*         System.out.println(date1);*/
/*** Calendar日历类(抽象类)的使用:注意此时日历类是可变的*      1 实例化:*         1 创建其子类的对象:new GregorianCalendar();*         2 调用其静态方法:getInstance();  推荐使用*      2 常用方法:*         1 get()*         2 set()*         3 add()*         4 getTime()*         5 setTime()*/日历类中的方法:int days = instance.get(Calendar.DAY_OF_MONTH); // 获取这个月的第几天System.out.println("现在是这个周的第"+instance.get(Calendar.DAY_OF_WEEK)+"天"); // 获取这个周的第几天System.out.println("现在是这个年的第"+instance.get(Calendar.DAY_OF_YEAR)+"天"); // 获取这个年的第几天instance.set(Calendar.DAY_OF_MONTH,19);  // 修改Calendar对象的某个指定属性instance.add(Calendar.DAY_OF_MONTH,3); // 在Calendar对象的指定属性上加上指定数Date date = instance.getTime();  // 日历类转换为Date  注意此时日历类的对象是修改之后的instance.setTime(date); // 将指定时间的Date类转换为对应时间日历类
/*** SimpleDateFormat总结:用于对日期进行格式化和解析*      格式化:*        日期(java.util.Date)------>字符串:sdf.format(Date date);*      解析:*        字符串------>日期(java.util.Date): sdf.parse(String str);*/
jdk8之后新日期时间API的使用
/*** LocalDate、LocalTime、LocalDateTime的使用:*      1 LocalDateTime使用频率最高*      2 跟Calendar类相似* Calendar类和Date类面临的问题是:*      1 可变性:像日期和时间这样的类应该是不可变的。*      2 偏移性: Date中的年份是从1900年开始,月份是从0开始。*      3 格式化: 格式化只对Date有用,对Calendar没用。*      4 他们的线程都不是安全的,不能处理闰秒等。*/
public class LocalDateTimeTest {public static void main(String[] args) {// 如何实例化? 使用三个类的静态方法now()/of()// 创建对应当前时间的对象  LocalDate.now();System.out.println("创建对应当前时间的对象");LocalDate localDate = LocalDate.now();LocalTime localTime = LocalTime.now();LocalDateTime localDateTime = LocalDateTime.now();System.out.println(localDate);System.out.println(localTime);System.out.println(localDateTime);System.out.println("*********************************");// 创建指定时间的对象,没有偏移量  LocalDateTime.of(2019, 1, 1, 13, 6, 56);System.out.println("创建指定时间的对象,没有偏移量");LocalDateTime localDateTime1 = LocalDateTime.of(2019, 1, 1, 13, 6, 56);System.out.println(localDateTime1);System.out.println("*********************************");// 获取相关的属性  getXxx()System.out.println("获取相关的属性");int dayOfMonth = localDateTime.getDayOfMonth();DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();int monthValue = localDateTime.getMonthValue();Month month = localDateTime.getMonth();System.out.println(dayOfMonth);System.out.println(dayOfWeek);System.out.println(monthValue);System.out.println(month);System.out.println("*********************************");// 设置相关的属性,体现不可变性   withXxx()System.out.println("设置相关的属性");LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(25);System.out.println("修改之前:"+localDateTime);System.out.println("修改之后:"+localDateTime2);System.out.println("*********************************");// 添加  体现不可变性LocalDateTime localDateTime3 = localDateTime.plusDays(10);System.out.println("添加之前:"+localDateTime);System.out.println("添加之后:"+localDateTime3);}
}
/*** DateTimeFormatter的使用:*     1 格式化或解析日期/时间,类似属于SimpleDateFormat*     2 如何实例化?*        1> 预定义的标准格式:*        2> 本地化相关的格式:*        3> 自定义格式(使用最多):调用静态方法ofPattern("yyyy-MM-dd HH:mm:ss");*/
public class DateTimeFormatterTest {public static void main(String[] args) {// 重点: 自定义的方式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // hh表示12小时制,HH表示24小时// 格式化操作String format = formatter.format(LocalDateTime.now());System.out.println(format);// 解析操作TemporalAccessor parse = formatter.parse("2021-08-09 10:10:49");System.out.println(parse);}
}
/*** Instant类的使用:*    是时间线上的一个瞬时点,可以被用来记录应用程序的事件时间戳,类似于java.util.Date。*    1 如何实例化?*       1> 调用Instant类的静态方法:Instant.now();  获取本初子午线对应的标准Instant时间对象*       2> 调用Instant类的静态方法:Instant.ofEpochMilli(1628473189103l);  根据指定的毫秒数创建对应时间的Instant对象*/
public class InstantTest {public static void main(String[] args) {// now(): 获取本初子午线对应的标准时间对象Instant now = Instant.now();  // 当前对象是对应伦敦的本初子午线的时间/0时区System.out.println(now);// 添加时间的偏移量OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));System.out.println(offsetDateTime);// 获取对应的毫秒数   1970/1/1long l = now.toEpochMilli();System.out.println(l);// 根据指定的毫秒数创建对应时间的Instant对象Instant instant = Instant.ofEpochMilli(1628473189103l);System.out.println(instant);}}
BigDecimal和BigInteger的使用:

1 实例化的时候尽量使用传入参数为String的构造器(为了使浮点数的表示更加精准)

2 常用方法: 1 加法:add() b1.add(b2)

​ 2 减法:subtract() b1.subtract(b2)

​ 3 乘法:multiply() b1.multiply(b2)

​ 4 除法:divide() b1.divide(b2)

​ 5 绝对值:abs() b1.abs()

Math类的使用:

常用方法:

​ 1 static int max(int x,int y):返回x和y中的最大值,提供了很多重载的方法

​ 2 static int min(int x,int y):返回x和y中的最小值,提供了很多重载的方法

​ 3 static double exp(double a):返回e的a次幂

​ 4 static double pow(double a,double b):返回a的b次幂

​ 5 static double sqrt(double a):返回a的平方根

​ 6 static double cbrt(double a):返回a的立方根

​ 7 static double log(double a):返回a的自然对数,即lna的值

​ 8 static double log10(double a):返回以10为底a的对数,即lga

Comparable接口和Comparacor接口:
/*** java中的对象正常情况只能进行 == 和 != 不能使用 >   <* 在开发中需要对多个对象进行排序,就是需要比较对象的大小。* 如何实现呢?   使用一下两个接口的任何一个: Comparable  Comparator* Comparable接口的使用举例:*     1 像String、包装类等实现了Comparable接口,重写了CompareTo(obj)方法,给出了比较两个对象的方式。*     2 像String、包装类重写compareTo(obj)方法后,进行了从小到大的排列。*     3 重写compareTo(obj)规则:*         如果当前对象this大于形参对象obj时,返回正整数。*         如果当前对象this小于形参对象obj时,返回负整数。*         如果当前对象this等于形参对象obj时,返回0。*     4 对于自定义类如果需要排序,可以让自定义类实现Comparable接口,重写CompareTo(obj)方法。* Comparator接口使用背景:*     1 当元素的类型没有实现Comparable接口而又不方便修改代码,或者实现了Comparable接口的排序规则*     不适合当前的操作,那么就可以考虑使用 Comparator 接口进行排序。*     2 重写compare(Object o1,Object o2)方法规则:*         如果o1 > o2,返回正整数。*         如果o1 = o2,返回0。*         如果o1 < o2,返回负整数。* Comparable接口和Comparator接口使用的对比:*     1 Comparable接口的方式一旦写定,保证Comparable接口实现类的对象在任何位置都可以比较大小。*     2 Comparator接口的方式属于临时性的比较。*/

3 枚举类和注解

/*** 枚举类的使用:*    1 枚举类的理解:类的对象只有有限个,确定的数量,我们称此类为枚举类*    2 当需要定义一组常量时,强烈建议使用枚举类*    3 如果枚举类中只有一个对象,则可以作为单例模式的实现方式。* 如何定义枚举类:*    1 jdk5.0之前自定义枚举类*    2 jdk5.0之后可以使用enum关键字定义枚举类* Enum类中的常用方法:*    1 values():返回当前枚举类类型的对象数组,该方法可以很方便的遍历枚举类对象。*    2 valueOf(String str):返回与形参字符串相对应的枚举类对象,注意形参字符串一定要是枚举类对象之中存在的。*    3 toString():如果没有重写此方法,返回当前枚举类对象所对应的常量名称。* 使用enum关键字定义的枚举类实现接口的情况:*    1 实现接口,在枚举类中实现接口中的抽象方法。*    2 让枚举类的每个对象分别实现接口中的抽象方法。*/
自定义枚举类:
public class EnumTest {public static void main(String[] args) {System.out.println(season.SPRING);System.out.println(season.SUMMER);System.out.println(season.AUTUMN);System.out.println(season.WINTER);}
}//自定义枚举类
class season {private final String seasonName;private final String seasonDesc;// 1 构造器私有化private season(String seasonName,String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}// 2 提供有限数量的对象public static final season SPRING = new season("春天","天街小雨润如酥");public static final season SUMMER = new season("夏天","映日荷花别样红");public static final season AUTUMN = new season("秋天","无边落木萧萧下");public static final season WINTER = new season("冬天","千树万树梨花开");public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}@Overridepublic String toString() {return "season{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}}
使用enum关键字定义枚举类:

使用enum关键字定义的枚举类默认继承java.lang.Enum类,不是java.lang.Object类

public class EnumTest2 {public static void main(String[] args) {System.out.println(season1.SPRING);System.out.println(season1.values()[1]);season1 winter = season1.valueOf("WINTER");System.out.println(winter);season1.SUMMER.show();System.out.println("**************************");season1.SPRING.show();}
}
interface demo {void show();
}
enum season1 implements demo{// 1 提供当前枚举类的对象,多个对象之间用","隔开,最后一个对象用";"结尾SPRING("春天","天街小雨润如酥"){@Overridepublic void show() {System.out.println("春天的花开");}},SUMMER("夏天","映日荷花别样红"){@Overridepublic void show() {System.out.println("夏天夏天悄悄过去");}},AUTUMN("秋天","无边落木萧萧下"){@Overridepublic void show() {System.out.println("你听啊秋末的落叶");}},WINTER("冬天","千树万树梨花开"){@Overridepublic void show() {System.out.println("漫天大雪飘零做你的嫁衣");}};//2 声明Season1对象的属性,private final 修饰private final String seasonName;private final String seasonDesc;//3 私有化构造器,并给对象的属性赋值private season1(String seasonName,String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}@Overridepublic String toString() {return "season1{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}//    @Override
//    public void show() {//        System.out.println("这是"+seasonName);
//    }
}

Enum类的主要方法:

​ 1 values():返回枚举类型的对象数组,该方法可以便捷的遍历所有枚举值

​ 2 valueOf(String str):可以把一个字符串转换为对应的枚举类对象,注意字符串必须是枚举类对象的名称,否则会出现异常

​ 3 toString():返回当前枚举类对象的常量名称,如果没有重写toString()的话

注解的使用:
/*** 注解(Annotation)的使用:*     1 理解注解:*        1 jdk5.0新增。*        2 注解是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取并执行相应的处理,通过使用注解,程序员可以*        在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。*        3 在javaEE中注解占据了非常重要的角色。*     2 注解的实例:*        1 生成文档相关的注解。*        2 在编译时进行格式检查(jdk内置的三个基本注解)*            1 @Override:限定重写父类方法,该注解只能用于方法。*            2 @Deprecated:表示修饰的元素(类、方法等)已过时。*            3 @SuppressWarnings:抑制编译器警告。*        3 跟踪代码的依赖性,代替配置文件的功能。*     3 自定义注解:*        1 注解声明为@interface*        2 内部定义的成员变量通常用value表示*        3 可以指定成员变量的默认值,使用default定义*        4 如果自定义注解没有成员变量,那么表明此注解是一个标识作用*        5 如果自定义注解有成员变量,在使用注解时需要指明成员变量的值*        6 自定义注解必须搭配注解的信息处理流程(使用反射)才有意义*        7 自定义注解通常都会指明2个元注解: @Retention   @Target*     4 jdk提供的4种元注解:*        1 @Retention:指定所修饰的注解的生命周期:SOURCE\CLASS(默认)\RUNTIME,*        只有声明为RUNTIME生命周期的注解才可以通过反射获取到。*        2 @Target:用于指定此注解可以修饰哪些元素(类、方法、属性等)。*        3 @Documented:表示所修饰的注解在被javadoc解析时保留下来。*        4 @Inherited:被它修饰的注解将具有继承性。*     5 通过反射获取注解的信息:以后再说 - -。*     6 jdk8中注解的新特性:*        1 可重复注解的使用:*            1 在MyAnnotation上声明@Repeatable,成员变量值为MyAnnotations.class。*            2 MyAnnotation的@Target、@Retention等元注解与MyAnnotations全部相同。*        2 类型注解:*            1 ElementType.TYPE_PARAMETER:表示该注解能写在任何类型变量的声明语句中,(如泛型声明,不能写在异常类型前)*            2 ElementType.TYPE_USE:表示该注解能写在使用类型的任何语句中。(可以写在异常类型前面)*/
自定义注解的使用:
/*** 自定义注解*/
// 设置自定义注解的生命周期
@Retention(RUNTIME)
// 设置自定义注解可以修饰的元素
@Target({METHOD,TYPE,TYPE_PARAMETER,TYPE_USE})
// 设置此注解具有继承性
@Inherited
// 可重复注解
@Repeatable(MyAnnotations.class)
public @interface MyAnnotation {String value();
}
// 设置自定义注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
// 设置自定义注解可以修饰的元素
@Target({ElementType.METHOD,ElementType.TYPE})
// 设置此注解具有继承性
@Inherited
// 可重复注解
public @interface MyAnnotations {MyAnnotation[] value() default "hello";
}
@MyAnnotation
@MyAnnotation("hi")
public class ZhuJieTest {public static void main(String[] args) throws @MyAnnotation("hi") RuntimeException {Annotation[] annotations = MyAnnotation.class.getAnnotations();for(Annotation annotation:annotations){System.out.println(annotation);}}
}
class demo<@MyAnnotation("hello") T> {}

4 集合框架

Collection接口:

1 单列集合,用来存储一个一个的对象,和Map接口不同

2 在Collection接口实现类的对象中添加数据obj时,要求obj对象所在的类重写equals()

3 Collection接口的常用方法:

* Collection接口的常用方法:
*    add(Obj obj):向集合对象中添加一个元素。
*    addAll(Collection c):将形参集合c中的元素全部添加到当前的集合中。
*    size():获取当前集合对象的长度。
*    clear():清空集合中的所有数据。
*    isEmpty():判断当前集合中是否有元素。
*    remove(Object obj):移除形参中指定的元素,在判断时会调用obj对象所在类的equals()。返回值是boolean类型。
*    removeAll(Collection c):移除形参集合中的所有元素,在判断时会调用c集合中对象所在类的equals()。返回值是boolean类型。
*    contains(Object obj):判断集合中是否包含指定的对象。 在判断时会调用obj对象所在类的equals()。
*    containsAll(Collection c):判断形参集合中的所有数据是否都存在于当前的集合中。
*    retainAll(Collection c):求当前集合和形参集合中的元素的交集,直接把当前集合修改成交集。
*    equals(Collection c):判断当前集合对象和形参中集合对象数据是否相同,在判断时会调用形参集合中的对象所在类的equals()。
*                     如果两个集合是ArrayList则需要考虑顺序,因为ArrayList是一个有序的集合。
*    hashCode():返回当前对象的哈希值。此方法定义在java.lang.Object类中。
*    toArray():将当前集合转换为数组。
*         数组----->集合:Arrays.asList(new String[]{"AA","BB"}),调用Arrays类的静态方法。
*    iterator():返回Iterator接口的实例,用于遍历集合元素。
*/
List接口详解:
/*** List接口框架详解:** List接口:存储有序的,可重复的数据。和Set接口相对。------->动态的数组* List接口下的ArrayList、LinkedList和vector三个实现类:*     1 ArrayList:作为List接口的主要实现类,线程不安全,效率高,底层使用Object[]数组存储。*     2 LinkedList:对于频繁的插入、删除操作,效率比ArrayList高,底层使用双向链表存储。*     3 Vector:作为List接口的最古老的实现类,线程安全,效率低,底层使用Object[]数组存储。* ArrayList的源码分析:*     jdk7:*        ArrayList list = new ArrayList(); // 底层创建了一个长度为10的Object[] elementData。*        list.add(123); // elementData[0] = new Integer(123)*        list.add(11); // 表示当前添加的元素是第11个元素,如果此次操作导致底层的数组的容量不够,则需要*        默认的情况下扩容为原来容量的1.5倍,同时将原有数组里的数组复制到新的数组中。*        总结:建议开发的时候选用带参数的构造器,ArrayList list = new ArrayList(int capacity);*        防止底层的数组扩容,使效率降低。*     jdk8:*        ArrayList list = new ArrayList(); // 底层Object[] elementData初始化为{},并没有创建长度*        为10的数组。*        list.add(123); // 第一次调用add()时,底层才创建长度为10的数组, elementData[0] = new Integer(123)*        ......*        后续的添加和扩容的操作与jdk7一样。*        总结:jdk7中的ArrayList的对象的创建类似单例模式的饿汉式,jdk8中的ArrayList的对象的创建类似单例模式的懒汉式,*        延迟了数组的创建,节省了内存。* LinkedList的源码分析:*     LinkedList list = new LinkedList(); // 内部声明了Node类型的first和last属性.*     list.add(); // 将123封装到Node类的对象中,创建了Node对象。*     其中Node类定义为如下格式:  体现了LinkedList双向链表的说法。*         private static class Node<E> {*         E item;*         LinkedList.Node<E> next;*         LinkedList.Node<E> prev;**         Node(LinkedList.Node<E> var1, E var2, LinkedList.Node<E> var3) {*             this.item = var2;*             this.next = var3;*             this.prev = var1;*         }*     }* Vector的源码分析:jdk7和jdk8通过Vector()的构造器创建对象时,底层都创建了长度为10的数组,在扩容方面默认扩容为原来的*         2倍。* ArrayList、LinkedList、Vector三者的异同?*      同:三者都实现了List接口,存储数据的特点相同:有序、可重复的数据。*      异:请见上文 -.-。* List接口相较于Collection接口多出的方法:*      void add(int index,Object ele):在指定的位置index上插入ele元素。*      boolean addAll(int index,Collection ele):从指定的位置index将集合ele中所有元素添加进来。*      Object get(int index):获取指定位置index上的元素。*      int indexOf(Object obj):返回元素obj在当前集合首次出现的位置。*      int lastIndexOf(Object obj):返回元素obj在当前集合末次出现的位置。*      Object remove(int index):移除指定index位置的元素,并将此元素返回。*      Object set(int index,Object ele):将指定位置index上的元素设置为ele。*      List subList(int start,int end):相似于String的substring(int start,int end),返回从索引start到end位置的*      子集合。* 总结:List接口的常用方法:*      增:add()*      删:remove(int index) 或 remove(Object obj)*      改:set(int index,int Object)*      查:get(int index)*      插:add(int index,Object obj)*      长度:size()*/
Set接口详解:
/*** Set接口详解:** Set接口:存储无序的、不可重复的数据(类比高中讲的集合)。* Set接口中没有定义新的方法,使用的都是Collection接口中的方法。* Set接口下的HashSet、LinkedHashSet、TreeSet三个实现类:*      HashSet:作为Set接口的最主要实现类,线程不安全,可以存储null值。采用数组+链表的方式存储数据。*           LinkedHashSet:HashSet的子类,遍历其内部的数据时,可以按照添加的顺序遍历。对于频繁的*           遍历操作LinkedHashSet的查找效率高于HashSet。*      TreeSet:可以按照添加的元素的指定属性进行排序。* 理解无序性、不可重复性:(以HashSet为例)*      无序性:不等于随机性,存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据元素的哈希值计算出*      在底层数组的索引位置进行添加。*      不可重复性:保证添加的元素在根据equals()比较时,返回false,即相同的元素只能有一个。* 添加元素的过程:(以HashSet为例)*      当我们向HashSet中添加元素a时,首先调用元素a的hashCode()方法,计算出元素a的哈希值,然后通过某种*      特定的算法计算出其在HashSet底层数组中的存储位置(即索引位置),判断此位置上是否已经有元素存在。*          如果此位置没有其他的元素存在,则元素a直接添加成功。  -----情况1*          如果此位置上已经存在元素b(或以链表的形式已经存在多个元素),则比较元素a和b的哈希值:*             如果哈希值不同,则元素a添加成功。-----情况2*             如果哈希值相同,则调用元素a的equals()方法:*                如果结果为true,元素a添加失败。*                如果结果为false,元素a添加成功。-----情况3*      对于添加成功的情况2和情况3,元素a与该位置上已经存在的元素以链表的形式存储。*      jdk7:元素a放到数组中,指向原来的元素。*      jdk8:原来的元素放在数组中,指向元素a。*      总结:七上八下。HashSet的底层采用数组+链表的结构。* 要求:向Set中添加数据,其所在的类一定要重写equals()和hashCode(),并且重写的equals()和hashCode()尽可能的保持*      一致性:相等的对象必须要有相等的散列码(哈希值)。* LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了2个引用,记录当前数据的前一个数据和后一个数据。* 优点:对于频繁的遍历操作LinkedHashSet的查找效率高于HashSet。** TreeSet的使用:*      1 向TreeSet中添加的数据要求是相同类的对象。TreeSet用于排序。在TreeSet中不会存储相同的数据。*      2 两种排序方式:自然排序(实现Comparable接口)  和  定制排序(实现Comparator接口)。*      3 在自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()。*      4 在定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()。*      5 TreeSet的空参构造器默认自然排序,可以在构造器参数中指定定制排序。*      6 TreeSet底层使用红黑树实现存储。**/
Iterator迭代器的使用:
/*** Iterator迭代器的使用,用来遍历容器(集合或数组)* Iterator中的常用方法:*     hasNext():判断游标下是否还有元素存在。*     next():将游标下移一位并返回此时游标对应的元素。* 增强for循环中底层使用的就是迭代器。*/
Map接口及其实现类:
/**   -----Map:双列数据,存储key-value,类似于高中的函数:y=f(x)。*        -----HashMap:作为Map接口的最主要实现类,线程不安全,效率高,可以存储null的key和value*            -----LinkedHashMap:保证在遍历map元素时可以按照添加的顺序遍历,因为在原有HashMap底层结构上*            添加了一对指针,指向前一个和后一个元素,对于频繁的遍历操作,执行效率高于HashMap。*        -----TreeMap:保证按照添加的元素进行排序,实现排序遍历,此时考虑元素的key的自然排序和定制排序。底层*        使用红黑树。*        -----Hashtable:作为Map接口最古老的实现类,线程安全,效率低,key和value不可以是null*            -----Properties: 常用来处理配置文件,key和value都是String类型。* HashMap底层:*      数组+链表(jdk7):*          HashMap map = new HashMap(); // 在实例化后,底层创建了一个长度是16的一维数组Entry[] table。*          ...可能已经执行过多次put操作....*          map.put(key1,value1); // 首先调用key1所在类的hashCode()计算出哈希值,用此哈希值经过某种算法得到*          在Entry数组中的存放位置。*          如果此位置上数据为空,此时key1-value1(entry)添加成功。*          如果此位置上数据不为空(此位置上存在一个或多个数据),比较key1和已经存在的一个数据或多个数据的哈希值。*             如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1(entry)添加成功。*             如果key1的哈希值与已经存在的某一个数据(key2-value2)的哈希值相同,继续比较,调用key1所在类的equals(key2)。*                如果返回false:此时key1-value1(entry)添加成功。*                如果返回true:使用value1替换value2。*          补充:关于情况2和情况3,此时此时key1-value1(entry)和原来的数据在数组中以链表的形式存储。*          在不断的添加过程中,会涉及到底层数组的扩容(当元素个数超出临界值并且当前元素直接存放的位置非空时才扩容),默认情况扩         容为原来的2倍,并将原有数据复制过来,返回一个新数组。*      数组+链表+红黑树(jdk8)*          jdk8相较于jdk7底层实现方面的不同:*              1 new HashMap():在底层没有创建一个长度为16的数组。*              2 jdk8中底层的数组是Node[],不是Entry[]。*              3 首次调用put()时,底层才创建长度为16的数组。*              4 jdk7底层结构只有数组+链表,jdk8中底层结构:数组+链表+红黑树,当数组的某一个索引位置上的元素以链表的形式存储的个数 > 8,*              并且当前数组的长度 > 64 时,此时此索引位置上的所有数据改为使用红黑树存储,不再以链表存储。使用红黑树使查找的效率变高。*              5 HashMap源码中的相关属性:*                 1 DEFAULT_INITIAL_CAPACITY: HashMap底层数组的默认容量。 16*                 2 DEFAULT_LOAD_FACTOR: HashMap的默认加载因子。  0.75f*                 3 threshold: 扩容的临界值,=容量*加载因子 => 12。*                 4 TREEIFY_THRESHOLD: Bucket中链表长度大于该默认值,转换为红黑树存储。 8*                 5 MIN_TREEIFY_CAPACITY: 桶中的Node被树化时最小的hash表容量。  64** 面试题:*     1 HashMap的底层实现原理?*     2 HashMap和Hashtable的异同?*     3 CurrentHashMap(分布式锁)与Hashtable的异同?* Map中结构的理解:*     1 Map中的key:无序的,不可重复,使用Set存储所有的key。key所在的类需要重写equals()和hashCode()。*     2 Map中的value:无序的,可重复,使用Collection存储所有的value。value所在类需要重写equals()。*     3 一个键值对key-value构成一个Entry对象。*     4 Map中的Entry:无序的,不可重复,使用Set存储所有的Entry对象。* Map中的常用方法:*     1 Object put(Object key,Object value): 添加或修改。*     2 void putAll(Map m): 将m中所有数据添加到当前map对象中。*     3 Object remove(Object key): 移除指定key的元素,并返回此元素的value值。*     4 void clear(): 清空当前map所有数据。*     5 Object get(Object key): 获取指定key对应的value值。*     6 boolean containsKey(Object key): 判断当前map对象是否包含指定的key。*     7 boolean containsValue(Object value): 判断当前map对象是否包含指定的value。*     8 int size(): 返回map对象中元素的个数。*     9 boolean isEmpty(): 判断当前map对象中元素是否为空。*     10 equals(obj): 判断当前map对象与参数obj是否相等。*     11 Set keySet(): 得到所有的key,(用于遍历所有的value值)。*     12 Collection values(): 得到所有的value集合(用于遍历所有的value值)。*     13 Set entrySet(): 得到所有key-value构成的Set集合。** Properties处理属性文件:用来处理配置文件**/

5 泛型和File

泛型的使用:

1 泛型类中的泛型在实例化的时候指定,或者子类在继承父类的时候指明具体的泛型,那么此时子类就不再是泛型类

2 泛型类中的泛型声明在属性或方法上时,不能用static修饰,因为泛型类中的泛型在实例化的时候指定

2 泛型方法中的泛型在调用次方法的时候指明具体的泛型

泛型通配符的使用:? (?就表示不确定)

例如类A是类B的父类,G 和 G 是没有关系的,二者共同的父类是:G<?>

使用通配符后数据读取和写入的要求:

1 写入: 对于List<?>,就不能向其内部添加数据,但可以添加null,因为null可以给任何引用数据类型变量赋值

2 读取: 允许读取数据,读取的数据类型为Object,不确定是什么类,但一定是Object类

有限制条件的通配符:

1 <? extends A> : <= ,G<? extends A>可以作为G和G的父类,其中B是A的子类

2 <? super A> : >= ,G<? super A>可以作为G和G的父类,其中B是A的父类

File类的使用:
/*** File类的使用:*   1 如何实例化?*       File(String filePath)*       File(String parentPath,String childPath)*       File(File parentFile,String childPath)*   2 相对路径:相较于当前module下,如果使用单元测试方法,相对路径是当前module下,main方法相对路径是当前工程下。*     绝对路径:包含盘符在内的文件或文件目录*   3 路径分隔符:*       File.separator   (File类的静态属性,分隔符)*   4 File类的理解:*       1 File类的一个对象代表一个文件或一个文件目录(文件夹)。*       2 File类声明在java.io包下。*       3 File类涉及到文件或文件目录的创建、删除、重命名、获取修改时间、获取文件大小等方法,并未涉及到文件的读取和写入操作,*       读取和写入操作必须使用IO流实现。*       4 后续File类的对象常常会作为参数传递到流的构造器中,指明读取和写入的"终点"。*   5 File类的常用方法:*       1 public String getAbsolutePath():获取文件的绝对路径*       2 public String getPath():获取文件路径*       3 public String getName():获取文件的名称*       4 public String getParent():获取上层文件目录的路径,如果没有上层文件目录,返回null*       5 public long length():获取文件的长度(即字节数),不能获取文件目录的长度,会返回0*       6 public long lastModified():获取最后一次修改的时间,返回毫秒数*       7 public String[] list():获取指定文件目录下的所有文件或者文件目录的名称数组*       8 public File[] listFiles():获取指定文件目录下的所有文件或文件目录的File数组*       9 public boolean renameTo(File dest):把文件重命名为指定的路径*         例如: file1.renameTo(file2):要想保证返回true,需要file1在硬盘中存在,file2在硬盘中不存在。相当于将file1移动*         file2的位置,并将file1的文件名称改为file2的文件名称。*       10 public boolean isDirectory():判断是否为文件目录*       11 public boolean isFile():判断是否是文件*       12 public boolean isExit():判断是否存在*       13 public boolean canRead():判断是否可读*       14 public boolean canWrite():判断是否可写*       15 public boolean isHidden():判断是否隐藏*       16 public boolean createNewFile():创建文件,若文件存在则不创建*       17 public boolean mkdir():创建文件目录,如果此文件目录存在,就不创建,如果此文件目录的上层目录不存在,也不创建*       18 public boolean mkdirs():创建文件目录,如果此文件目录的上层目录不存在,则一并创建*       19 public boolean delete():删除文件或文件夹*          注意:java中的删除不走回收站,你连反悔的机会都没有。*/

6 IO流

/*** IO流的分类:*   根据操作数据单位的不同:字符流、字节流。*   根据数据的流向不同:输入流、输出流。*   根据操作的对象的不同:节点流、处理流。* 流的体系结构:*   抽象基类                 节点流(文件流)                                        缓冲流(处理流的一种)*   InputStream            FileInputStream(read(byte[] buffer))     BufferedInputStream(read(byte[]buffer))*   OutputStream           FileOutputStream(write(byte[] buffer,0,len))   BufferedOutputStream(write(byte[] buffer,0,len)/flush())*   Reader                 FileReader(read(char[] cbuf))                      BufferedReader(read(char[] cbuf)/readLine())*   Writer                 FileWriter(write(char[] cubf,0,len))               BufferedWriter(write(char[] cubf,0,len)/flush())**/
FileReader和FileWriter:
public class FileReaderWriter {/*** 说明:*    1 read()的理解:返回读入的一个字符,如果达到文件末尾返回-1。*    2 异常的处理:为了保证流最终一定可以执行关闭操作,需要使用try-catch-finally处理。*    3 读入的文件一定要存在,否则会出现FileNotFoundException。*/@Test// 使用FileReader实现文件读取操作,一个一个字符读取。  (1.0版本)public void testFileReader1(){FileReader fr = null;try {// 1 实例化File类的对象,指明需要操作的文件File file = new File("helloReader.txt");
//        System.out.println(file.getAbsolutePath());// 2 提供具体的流fr = new FileReader(file);// 3 数据的读入操作int data;while ((data = fr.read()) != -1){System.out.print((char) data);}} catch (IOException e) {e.printStackTrace();} finally {// 关闭流try {if(fr != null) {fr.close();}} catch (IOException e) {e.printStackTrace();}}}@Test// 使用FileReader实现文件读取操作,使用char[]读取,读取速度更快。  (2.0版本)public void testFileReader2(){FileReader fr = null;try {File file = new File("helloReader.txt");fr = new FileReader(file);// 读入操作char[] cbuf = new char[5];int len;while ((len = fr.read(cbuf)) != -1){//            for(int i=0;i<len;i++){//                System.out.print(cbuf[i]);//            }String str = new String(cbuf,0,len);System.out.print(str);}} catch (IOException e) {e.printStackTrace();} finally {try {if(fr != null)fr.close();} catch (IOException e) {e.printStackTrace();}}}@Test/*** 从内存中写出数据到硬盘上:*    1 输出操作对应的File可以是不存在的,不会出现异常。*    2 如果File对应的硬盘中的文件不存在,在输出的过程中,自动创建此文件。*    3 File对应硬盘中的文件存在:*         1 如果流使用的构造器是FileWriter(file,false)/FileWriter(file):对原有的文件进行覆盖。*         2 如果流使用的构造器是FileWriter(file,true):不会对原有的文件进行覆盖,而是直接追加到原有文件末尾。*/public void testFileWriter() {FileWriter fw = null;try {File file = new File("helloWriter.txt");fw = new FileWriter(file);fw.write("春天的花开带走冬天的阴霾,\n");fw.write("夏天夏天悄悄过去,\n");fw.write("你听啊秋末的落叶,\n");fw.write("半生风雪吹不散花落时节的眼泪。");} catch (IOException e) {e.printStackTrace();} finally {try {if(fw != null)fw.close();} catch (IOException e) {e.printStackTrace();}}}@Test// 使用Reader和Writer实现文本文件的复制操作public void testReaderWriter(){FileReader fr = null;FileWriter fw = null;try {// 不能使用字符流处理字节的数据,否则打不开。File source = new File("readerCopy.txt");File dest = new File("writerCopy.txt");fr = new FileReader(source);fw = new FileWriter(dest);int len;char[] cubf = new char[10];while ((len = fr.read(cubf)) != -1){fw.write(cubf,0,len);}} catch (IOException e) {e.printStackTrace();} finally {// 最后不要忘记关闭流try {if(fr != null)fr.close();} catch (IOException e) {e.printStackTrace();}try {if(fw != null)fw.close();} catch (IOException e) {e.printStackTrace();}}}
}
FileInputStream和FileOutputStream:
/*** 字节流测试:*    1 对于文本文件(.txt/.java/c/cpp),使用字符流处理。*    2 对于非文本文件(.jpg/.mp3/.mp4/.avi/.doc/.ppt)使用字节流处理。*    3 使用字节流处理文本文件时,如果文本中有中文,输出到控制条会出现乱码问题,但是可以进行复制操作。*    4 使用字符流处理非文本文件时,例如复制,会出现复制的文件打不开的问题。*/
public class FileInputOutputStream {@Test/*** 使用字节流实现对图片的复制操作*/public void testInputOutputStreamCopy(){FileInputStream fis = null;FileOutputStream fos = null;try {File src = new File("srcDog.jpg");File dest = new File("destDog.jpg");fis = new FileInputStream(src);fos = new FileOutputStream(dest);byte[] bbuf = new byte[1024];int len;while ((len = fis.read(bbuf)) != -1){fos.write(bbuf,0,len);}} catch (IOException e) {e.printStackTrace();} finally {// 关闭流try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}}// 实现指定路径文件的复制,从形参传入public void CopyFile(String srcFile,String destFile){FileInputStream fis = null;FileOutputStream fos = null;try {File src = new File(srcFile);File dest = new File(destFile);fis = new FileInputStream(src);fos = new FileOutputStream(dest);byte[] bbuf = new byte[1024];int len;while ((len = fis.read(bbuf)) != -1){fos.write(bbuf,0,len);}} catch (IOException e) {e.printStackTrace();} finally {// 关闭流try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}}@Testpublic void testCopyFile(){  // 花费时间:6033String srcFile = "D:\\视频\\伪装者 TV版\\伪装者 TV版 01_超清.kux";String destFile = "D:\\视频\\伪装者 TV版\\伪装者 TV版 01_超清_复制版.kux";long start = System.currentTimeMillis();CopyFile(srcFile,destFile);long end = System.currentTimeMillis();System.out.println("复制所花费的时间为"+(end-start)+"毫秒");}@Test// 对图片的加密操作public void letSecret(){FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream("srcDog.jpg");fos = new FileOutputStream("srcDogSecret.jpg");int len;byte[] buffer = new byte[20];while ((len = fis.read(buffer)) != -1){//                错误的写法,增强for循环是把数组中的元素重新赋给一个变量b,^运算改变的是变量b的值,并没有改变数组元素的值。
//                for(byte b:buffer){//                    b = (byte) (b ^ 5);
//                }// 对写出的图片进行加密操作for(int i =0;i<len;i++){buffer[i] = (byte) (buffer[i] ^ 5);}fos.write(buffer,0,len);}} catch (IOException e) {e.printStackTrace();} finally {try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}}@Test// 对图片的解密操作public void letNotSecret(){FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream("srcDogSecret.jpg");fos = new FileOutputStream("srcDogNotSecret.jpg");int len;byte[] buffer = new byte[20];while ((len = fis.read(buffer)) != -1){// 对写出的图片进行加密操作for(int i =0;i<len;i++){buffer[i] = (byte) (buffer[i] ^ 5);}fos.write(buffer,0,len);}} catch (IOException e) {e.printStackTrace();} finally {try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {System.out.println(97^2);}}
BufferedReader和BufferedWriter:
/***  使用缓冲流实现对文本文件的复制*/
public class BufferedReaderWriter {@Testpublic void copyFile(){BufferedReader br = null;BufferedWriter bw = null;try {br = new BufferedReader(new FileReader("readerCopy.txt"));bw = new BufferedWriter(new FileWriter("writerCopyBuffered.txt"));
//            方式一:
//            char [] buffer = new char[20];
//            int len;
//            while ((len = br.read(buffer)) != -1){//                bw.write(buffer,0,len);
//            }
//            方式二: 缓冲流BufferedReader可以每次读一行String data;while ((data = br.readLine()) != null){// 注意readLine()方法不会读出换行符,需要手动换行// 方式一:
//                bw.write(data+"\n");// 方式二:bw.write(data);bw.newLine();   // 换行}} catch (IOException e) {e.printStackTrace();} finally {try {if(br != null)br.close();} catch (IOException e) {e.printStackTrace();}try {if(bw != null)bw.close();} catch (IOException e) {e.printStackTrace();}}}
}
BufferedInputStream和BufferedOutputStream:
/*** 处理流之一:缓冲流的使用*    作用:提高文件的读取、写入速度。*    提高读写速度的原因:缓冲流的内部提供了一个缓冲区。*    关闭流时先关外层流,再关内层流,但是外层关了之后内层自动关,就别费事了。*    处理流就是嵌套在已有流的基础上。*/
public class BufferedInputOutputStream {// 使用缓冲流实现对非文本文件的复制// 实现指定路径文件的复制,从形参传入public void CopyFile(String srcFile,String destFile){BufferedInputStream bis = null;BufferedOutputStream bos = null;try {File src = new File(srcFile);File dest = new File(destFile);bis = new BufferedInputStream(new FileInputStream(src));bos = new BufferedOutputStream(new FileOutputStream(dest));byte[] bbuf = new byte[1024];int len;while ((len = bis.read(bbuf)) != -1){bos.write(bbuf,0,len);}} catch (IOException e) {e.printStackTrace();} finally {// 关闭流try {if(bis != null)bis.close();} catch (IOException e) {e.printStackTrace();}try {if(bos != null)bos.close();} catch (IOException e) {e.printStackTrace();}}}@Testpublic void testCopyFile(){   // 花费时间:1721String srcFile = "D:\\视频\\伪装者 TV版\\伪装者 TV版 01_超清.kux";String destFile = "D:\\视频\\伪装者 TV版\\伪装者 TV版 01_超清_复制版.kux";long start = System.currentTimeMillis();CopyFile(srcFile,destFile);long end = System.currentTimeMillis();System.out.println("复制所花费的时间为"+(end-start)+"毫秒");}}
InputStreamReader和OutputStreamWriter的使用:
/*** 处理流二: 转换流的使用*    1 转换流,属于字符流*        InputStreamReader:将一个字节输入流转换为字符输入流*        OutputStreamWriter:将一个字符输出流转换为字节输出流*    2 作用:提供字节流与字符流之间的转换*    3 解码:字节、字节数组------>字符、字符数组*      编码:字符、字符数组------>字节、字节数组*    4 字符集:(了解)*        1 ASCII: 美国标准信息交换码,用一个字节的7位就可以表示*        2 ISO8859-1: 拉丁码表、欧洲码表,使用一个字节的8位表示*        3 GB2312: 中国的中文编码表。最多2个字节编码所有的字符*        4 GBK: 中国的中文编码表升级,融合了更多的中文文字符号,最多2个字节编码*        5 Unicode: 国际标准码,融合了人类目前使用的所有字符,为每个字符分配唯一的字符码*        6 UTF-8: 变长的编码方式,可用1-4个字节表示一个字符*        7 ANSI编码: 通常指平台的默认编码,例如英文操作系统是ISO-8859-1,中文系统是GBK*/
public class InputOutputStreamReaderWriter {@Test// 使用字节流读取文本中数据到控制台上,这里使用转换流将字节输入流转换为字符输入流public void readText() {InputStreamReader isr = null;try {isr = new InputStreamReader(new FileInputStream("readerCopy.txt"),"utf-8");int len;char[] cubf = new char[20];while ((len = isr.read(cubf)) != -1) {String str = new String(cubf,0,len);System.out.print(str);}} catch (IOException e) {e.printStackTrace();} finally {try {if(isr != null)isr.close();} catch (IOException e) {e.printStackTrace();}}}@Test// 使用转换流将读取的文件使用GBK编码集写入到一个新的文件中public void copyTest(){InputStreamReader isr = null;OutputStreamWriter osw = null;try {isr = new InputStreamReader(new FileInputStream("readerCopy.txt"),"utf-8");osw = new OutputStreamWriter(new FileOutputStream("writerCopyZhuanHuanLiu.txt"),"gbk");int len;char[] cbuf = new char[20];while ((len = isr.read(cbuf)) != -1){osw.write(cbuf,0,len);}} catch (IOException e) {e.printStackTrace();} finally {try {if(isr != null)isr.close();} catch (IOException e) {e.printStackTrace();}try {if(osw != null)osw.close();} catch (IOException e) {e.printStackTrace();}}}}
其他处理流的使用:
/*** 其他流的使用:*    1 标准的输入、输出流:*    2 打印流的使用:*        1 两个打印流:PrintStream、PrintWriter*        2 构造器:new PrintStream(new FileOutputStream(String path),true) // 创建打印输出流,设置位自动刷新(写入*        换行符或字节 '\n' 时会自动刷新输出缓冲区)*        3 System.setOut(ps) // 把标准输出流的终点改为指定文件*    3 数据流的使用:*        1 两个数据流: DataInputStream   DataOutputStream*        2 作用: 用于读取和写出基本数据类型的变量或字符串*        3 从文件读取数据的时候要按写的顺序读取,否则读出来的数据会乱*/
public class OtherStream {// 从键盘输入字符串,转换为大写,如果输入e或exit则退出程序public static void main(String[] args) {BufferedReader br = null;try {System.out.println("请输入字符串,输入e或exit退出程序");br = new BufferedReader(new InputStreamReader(System.in));String str;while ((str = br.readLine()) != null){if("e".equals(str) || "exit".equals(str)){System.out.println("成功退出程序!");break;}System.out.println(str.toUpperCase());}} catch (IOException e) {e.printStackTrace();}finally {try {if(br != null)br.close();} catch (IOException e) {e.printStackTrace();}}}@Test// 使用打印流输出ASCII字符到指定文件中public void printStreamTest(){PrintStream ps = null;try {// 创建打印流ps = new PrintStream(new FileOutputStream("printStream.txt"),true);if(ps != null){System.setOut(ps);}for(int i = 0; i <= 255; i++){System.out.print((char)i);if(i %30 == 0){System.out.println();}}} catch (Exception e) {e.printStackTrace();} finally {if(ps != null)ps.close();}}@Test// 练习:将内存中的字符串、基本数据类型的变量写入到文件中public void dataStreamWriteTest(){DataOutputStream dos = null;try {dos = new DataOutputStream(new FileOutputStream("dataStream.txt"));dos.writeUTF("旭哥我爱你");dos.writeBoolean(true);dos.writeInt(20);dos.writeDouble(1.23);} catch (IOException e) {e.printStackTrace();} finally {if(dos != null){try {dos.close();} catch (IOException e) {e.printStackTrace();}}}}@Test// 练习:将文件中的基本数据类型、字符串读到内存中输出public void dataStreamRead(){DataInputStream dis = null;try {dis = new DataInputStream(new FileInputStream("dataStream.txt"));System.out.println(dis.readUTF());System.out.println(dis.readBoolean());System.out.println(dis.readInt());System.out.println(dis.readDouble());} catch (IOException e) {e.printStackTrace();} finally {try {if(dis != null)dis.close();} catch (IOException e) {e.printStackTrace();}}}}
相对路径在IDEA中和Eclipse中的区别?

​ idea:如果使用单元测试方法,相对路径基于当前的Module

​ 如果使用main()方法测试,相对路径基于当前的Project

​ Eclipse:不论是单元测试方法还是main()方法,相对路径都基于当前的Projcet

处理流—对象流的使用:

1 ObjectInputStream和ObjectOutputStream:用于存储和读取基本数据类型数据或对象的处理流,它的强大之处就是可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来。

2 序列化:用ObjectOutputStream保存基本数据类型或对象的机制

3 反序列化:用ObjectInputStream读取基本数据类型或对象的机制

4 ObjectOutputStream和ObjectInputStream不能序列化static或transient修饰的成员变量

5 序列化机制:对象序列化机制允许把java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流,就可以恢复成原来的java对象

String类对象的序列化操作:
@Test
// 使用ObjectOutputStream将String类的对象序列化,持久化到硬盘中的文件中
public void test1(){ObjectOutputStream oos = null;try {oos = new ObjectOutputStream(new FileOutputStream("对象流测试.txt"));String s = "我爱北京天安门";oos.writeObject(s);} catch (IOException e) {e.printStackTrace();} finally {try {if(oos != null)oos.close();} catch (IOException e) {e.printStackTrace();}}
}
String类对象的反序列化操作:
@Test
// 将硬盘中的文件反序列化,还原为java中String类的对象
public void test2(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("对象流测试.txt"));String str = (String) ois.readObject();System.out.println(str);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {try {if(ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}
}
自定义Cat类:
public class Cat implements Serializable {private static final long serialVersionUID = 25485424157415L;  // 必须写的一个全局静态常量private String name;private Integer age;private transient String color;   // 表示该变量不可以被序列化private Integer id;public Cat() {}public Cat(String name, Integer age, String color) {this.name = name;this.age = age;this.color = color;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +", color='" + color + '\'' +", id=" + id +'}';}
}
自定义Cat类对象的序列化操作:
@Test
// 使用ObjectOutputStream将自定义类Cat的对象序列化,持久化到硬盘中的文件中
public void test3(){ObjectOutputStream oos = null;try {oos = new ObjectOutputStream(new FileOutputStream("对象流测试--自定义类.txt"));Cat cat = new Cat("杨桃",2,"蓝色");oos.writeObject(cat);} catch (IOException e) {e.printStackTrace();} finally {try {if(oos != null)oos.close();} catch (IOException e) {e.printStackTrace();}}
}
自定义类Cat类对象的反序列化操作:
@Test
// 使用ObjectInputStream把硬盘文件反序列化,还原回java对象
public void test4(){ObjectInputStream ois = null;try {ois = new ObjectInputStream(new FileInputStream("对象流测试--自定义类.txt"));Cat cat = (Cat) ois.readObject();System.out.println(cat);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {try {if(ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}
}
Cat类中需要满足以下条件,才可以被序列化:

1 需要实现接口:Serializable

2 当前类需要提供一个long类型的全局静态常量:SerialVersionUID (必须写,为当前类作一个标记,为了还原时能够找到相对应的类,如果不写会出现异常,找不到序列化时对应的类)

3 除了当前Cat类需要实现Serializable接口之外,还需要保证其内部的所有属性也是可序列化的(默认情况下基本数据类型可以被序列化)

RandomAccessFile(随机存取文件流)的使用:

1 RandomAccessFile直接继承于java.lang.Object类,实现了DataInput,DataOutput接口

2 RandomAccessFile既可以作为一个输入流,也可以作为一个输出流

3 如果RandomAccessFile作为输出流时,写出到的文件不存在,则在执行过程中自动创建,如果写出的文件存在,则会对原有的文件内容进行覆盖(默认情况下从头开始覆盖)

使用RandomAccessFile实现对图片文件的复制操作:
@Test
// 使用RandomAccessFile实现对图片文件的复制操作
public void test1(){RandomAccessFile rafRead = null;RandomAccessFile rafWrite = null;try {rafRead = new RandomAccessFile("RandomAccessFileSrc.png","r");rafWrite = new RandomAccessFile("RandomAccessFileDest.png","rw");byte[] buffer = new byte[20];int len;while ((len = rafRead.read(buffer)) != -1){rafWrite.write(buffer,0,len);}} catch (IOException e) {e.printStackTrace();} finally {try {if(rafRead != null)rafRead.close();} catch (IOException e) {e.printStackTrace();}try {if(rafWrite != null)rafWrite.close();} catch (IOException e) {e.printStackTrace();}}
}
使用 “xyz” 替换文本文件的三个字符:
@Test
// 使用 "xyz" 替换文本文件的三个字符
public void test2(){RandomAccessFile raf = null;try {raf = new RandomAccessFile("RandomAccessFile文本测试.txt","rw");raf.write("xyz".getBytes());} catch (IOException e) {e.printStackTrace();} finally {try {if(raf != null)raf.close();} catch (IOException e) {e.printStackTrace();}}
}
使用RandomAccessFile对文本文件进行插入操作:
@Test
// 使用RandomAccessFile对文本文件进行插入操作
public void test3(){RandomAccessFile rafRead = null;RandomAccessFile rafWrite = null;try {rafRead = new RandomAccessFile("RandomAccessFile文本测试.txt","r");rafWrite = new RandomAccessFile("RandomAccessFile文本测试.txt","rw");// 实例化StringBuilder时指定底层数组的长度,防止扩容StringBuilder sb = new StringBuilder((int) new File("RandomAccessFile文本测试.txt").length());String str;rafRead.seek(3);// 使用StingBuilder把索引 3 之后的数据缓存起来while ((str = rafRead.readLine()) != null){sb.append(str);}rafWrite.seek(3);rafWrite.writeBytes("xyz");rafWrite.writeBytes(sb.toString());} catch (IOException e) {e.printStackTrace();} finally {try {if(rafRead != null)rafRead.close();} catch (IOException e) {e.printStackTrace();}try {if(rafWrite != null)rafWrite.close();} catch (IOException e) {e.printStackTrace();}}
}

7 IO流与网络编程(通过网络进行数据传输)

网络编程中有两个主要的问题:

1 如何精确的定位网络上的一台或多台主机,定位到主机上特定的应用

2 找到主机后如何进行可靠高效的数据传输

网络编程中的两个要素:

1 对应问题1:IP和端口号

2 对应问题2:提供网络通信协议,TCP/IP参考模型(应用层,传输层,网络层,物理+数据链路层),每一层有具体的协议

通信要素一:IP和端口号

1 IP:唯一表示Internet上的计算机(通信实体)

2 在Java中使用InetAddress类表示IP

3 IP的分类: IPv4 和 IPv6 ; 万维网 和 局域网

4 域名:www.baidu.com www.vip.com www.atguigu.com

5 本地回路地址:127.0.0.1 对应着 localhost

6 如何实例化InetAddress:(InetAddress对象格式是: 域名/IP地址)

​ 1 getByName(String host) : 获取指定IP,参数可以是域名

​ 2 getLocalHost() : 获取本机IP

7 InetAddress类的常用方法:

​ 1 getHostName() : 获取域名

​ 2 getHostAddress() : 获取IP地址

8 端口号的理解:

​ 1 端口号:对应正在计算机上运行的进程

​ 2 要求:不同的进程拥有不同的端口号

​ 3 范围:被规定为一个 16 位 的整数 : 0-65535

9 端口号与IP地址的组合得出一个网络套接字:Socket

InetAddress类和常用方法测试:
public static void main(String[] args) throws UnknownHostException {InetAddress inet = InetAddress.getByName("www.baidu.com");System.out.println(inet.toString());    // InetAddress对象格式是: 域名/IP地址System.out.println(inet.getHostName());   // 获取域名System.out.println(inet.getHostAddress());  // 获取IP地址System.out.println("*******************************");InetAddress localHost = InetAddress.getLocalHost();     // 获取本机的IPSystem.out.println(localHost);InetAddress inet2 = InetAddress.getByName("127.0.0.1");  // 获取本机IPSystem.out.println(inet2);System.out.println(inet2.getHostAddress());  // 获取本机IP地址System.out.println("*******************************");InetAddress inet3 = InetAddress.getByName("14.215.177.38");System.out.println(inet3);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQ3MpR5q-1638260550224)(C:\Users\huawei123\AppData\Roaming\Typora\typora-user-images\image-20210901102506975.png)]

通信要素二:网络通信协议

传输层两个重要协议:TCP协议 (打电话) UDP协议(发短信、信息)

实现TCP的网络编程1

例题一:客户端将信息发送给服务器,服务器将信息显示在控制台上

客户端代码步骤:

1 创建Socket对象,指明服务器端的IP和端口号

2 获取一个输出流,用于传输数据

3 用输出流写出数据

4 关闭资源

服务端代码步骤:

1 创建服务器端的ServerSocket,指明自己的端口号

2 调用accept()表示接受来自客户端的Socket

3 获取一个输入流

4 从输入流中读取数据

5 关闭资源

6 代码演示:

public class TCPTest1 {@Test// 客户端public void client(){OutputStream os = null;Socket socket = null;try {// 创建Socket对象,指明服务器的IP和端口号socket = new Socket(InetAddress.getLocalHost(), 9999);// 使用Socket对象获取一个输出流,用于写出数据os = socket.getOutputStream();// 用输出流写出数据os.write("你好啊,我是客户端".getBytes());} catch (IOException e) {e.printStackTrace();} finally {// 关闭资源try {if(os != null)os.close();} catch (IOException e) {e.printStackTrace();}try {if(socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}}}@Test// 服务端public void server(){ServerSocket serverSocket = null;Socket socket = null;InputStream is = null;ByteArrayOutputStream baos = null;try {// 创建服务端的ServerSocket,指明自己的端口号serverSocket = new ServerSocket(9999);// 调用accept()表示接受来自客户端的Socketsocket = serverSocket.accept();// 获取一个输入流is = socket.getInputStream();// 从输入流中读取数据byte[] buffer = new byte[5];int len;baos = new ByteArrayOutputStream();while ((len = is.read(buffer)) != -1){baos.write(buffer,0,len);}String s = baos.toString();System.out.println(s);} catch (IOException e) {e.printStackTrace();} finally {// 关闭资源try {if(baos != null)baos.close();} catch (IOException e) {e.printStackTrace();}try {if(is != null)is.close();} catch (IOException e) {e.printStackTrace();}try {if(socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}try {if(serverSocket != null)serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}

反射机制

理解类的加载过程:(Class类是带泛型的)

1 程序经过javac.exe编译命令以后,会生成一个或多个字节码文件(.class)。

2 接着我们使用java.exe对某个字节码文件进行解释运行,相当于将这些字节码文件加载到内存中,此过程就成为类的加载,加载到内存中的类,我们就称为运行时类,作为Class类的一个实例。

3 换句话说,Class的实例就对应着一个运行时类。

4 加载到内存中的运行时类,会缓存一定的时间,在此时间段内,我们可以通过不同的方式获取此运行时类。

获取Class实例的四种方式:(前三个需要掌握!!)

方式一:调用运行时类的属性 .class :Class clazz1 = Person.class;

方式二:通过运行时类的对象:Class clazz2 = person.getClass();

方式三:调用Class类的静态方法 forName(String classPath):Class clazz3 = Class.forName(“com.atguigu.java.Person”);

方式四:使用类的加载器:Class clazz3 = ReflectTest.class.getClassLoader().loadClass(“com.atguigu.java.Person”);

基本上啥都可以获取Class类的实例(枚举类、注解、外部类、内部类、基本数据类型、数组、接口、Class、void),只要数组的元素类型和维度一样,都是同一个Class类实例
使用ClassLoader加载配置文件:

注意使用类的加载器读取配置文件时,此时文件的默认的相对路径在src下,不是当前工程下。

通过反射创建运行时类的对象:

在javabean中,要求提供一个空参的构造器的原因:

​ 1 便于通过反射,创建运行时类的对象

​ 2 便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器

@Test
public void test1() throws IllegalAccessException, InstantiationException {Class<Cat> clazz = Cat.class;// 调用此方法创建对应运行时类(Cat)的对象,内部调用的是Cat类的空参构造器,所以Cat类必须提供空参的、访问权限够用(通常设为public)的构造器Cat cat = clazz.newInstance();System.out.println(cat);
}
举例体会反射的动态性:

编译时不知道创建哪个类的对象,只有在运行的时候才确定要创建哪个类的对象

/*** 举例体会反射的动态性*/
public class ReflectionTest {// 体会反射的动态性public static void main(String[] args) {Random random = new Random();ReflectionTest rt = new ReflectionTest();int num = random.nextInt(3); // 0-3String classPath;if(num == 0){classPath = "java.util.Date";}else if(num == 1){classPath = "java.lang.Object";}else {classPath = "reflect.Cat";}Object instance = null;try {instance = rt.getInstance(classPath);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println(instance);}public Object getInstance(String classPath) throws Exception {Class<?> clazz = Class.forName(classPath);return clazz.newInstance();}
}
通过反射获取运行时类内部的结构:
通过反射调用运行时类内部的结构:

反射的应用—动态代理

java8新特性

Lambda表达式的使用:

1 举例:

2 格式:

3 Lambda表达式的使用(6种情况)

理解类的加载过程:(Class类是带泛型的)

1 程序经过javac.exe编译命令以后,会生成一个或多个字节码文件(.class)。

2 接着我们使用java.exe对某个字节码文件进行解释运行,相当于将这些字节码文件加载到内存中,此过程就成为类的加载,加载到内存中的类,我们就称为运行时类,作为Class类的一个实例。

3 换句话说,Class的实例就对应着一个运行时类。

4 加载到内存中的运行时类,会缓存一定的时间,在此时间段内,我们可以通过不同的方式获取此运行时类。

获取Class实例的四种方式:(前三个需要掌握!!)

方式一:调用运行时类的属性 .class :Class clazz1 = Person.class;

方式二:通过运行时类的对象:Class clazz2 = person.getClass();

方式三:调用Class类的静态方法 forName(String classPath):Class clazz3 = Class.forName(“com.atguigu.java.Person”);

方式四:使用类的加载器:Class clazz3 = ReflectTest.class.getClassLoader().loadClass(“com.atguigu.java.Person”);

基本上啥都可以获取Class类的实例(枚举类、注解、外部类、内部类、基本数据类型、数组、接口、Class、void),只要数组的元素类型和维度一样,都是同一个Class类实例
使用ClassLoader加载配置文件:

注意使用类的加载器读取配置文件时,此时文件的默认的相对路径在src下,不是当前工程下。

通过反射创建运行时类的对象:

在javabean中,要求提供一个空参的构造器的原因:

​ 1 便于通过反射,创建运行时类的对象

​ 2 便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器

@Test
public void test1() throws IllegalAccessException, InstantiationException {Class<Cat> clazz = Cat.class;// 调用此方法创建对应运行时类(Cat)的对象,内部调用的是Cat类的空参构造器,所以Cat类必须提供空参的、访问权限够用(通常设为public)的构造器Cat cat = clazz.newInstance();System.out.println(cat);
}
举例体会反射的动态性:

编译时不知道创建哪个类的对象,只有在运行的时候才确定要创建哪个类的对象

/*** 举例体会反射的动态性*/
public class ReflectionTest {// 体会反射的动态性public static void main(String[] args) {Random random = new Random();ReflectionTest rt = new ReflectionTest();int num = random.nextInt(3); // 0-3String classPath;if(num == 0){classPath = "java.util.Date";}else if(num == 1){classPath = "java.lang.Object";}else {classPath = "reflect.Cat";}Object instance = null;try {instance = rt.getInstance(classPath);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println(instance);}public Object getInstance(String classPath) throws Exception {Class<?> clazz = Class.forName(classPath);return clazz.newInstance();}
}

JAVASE高级部分相关推荐

  1. JavaSE高级 网络编程

    JavaSE高级 网络编程 教学目标 能够辨别UDP和TCP协议特点 UDP 无连接,基于数据包,发出去就不管了,性能好,可能丢失数据. TCP有连接,基于通信管道,可靠传输. 能够说出TCP协议下两 ...

  2. JavaSE高级【吐血整理汇总】

    1. Object类.常用API 1.1 Object类 java.lang.Object 类 Object 是类层次结构的根(父)类. 每个类(Person,Student-)都使用 Object ...

  3. JavaSE高级:JVM重点内容探究

    目录 1.JVM的位置 2.JVM的体系结构 3.类加载器 4. 双亲委派机制 5.沙箱安全机制 6.Native 7.PC寄存器 8.方法区 Method Area 9.栈 10.三种JVM 11. ...

  4. 最新《海牛的Mysql+java+javase+hadoop+ETL项目》

    教程内容: 本套大数据ETL项目视频课程紧密结合企业实战,是海牛大数据首套公开的项目视频,旨在帮助大数据小白自学,理论与操作结合.快速入门,加强对大数据技术的认知和学习. 项目视频内容包括:大数据使用 ...

  5. JavaSE专栏导航

    JavaSE基础 JavaSE基础篇:方法可变参数 JavaSE基础篇:枚举 JavaSE基础篇:Arrays数组工具类 JavaSE基础篇:instanceof关键字 JavaSE基础篇:多线程 J ...

  6. Android面试宝典

    GitHub托管 https://github.com/JackChan1999/Android-Interview GitBook在线阅读 在线阅读,PDF.ePub.Mobi电子书下载 https ...

  7. 13.集合框架ListSet

    JavaSE高级 集合框架List&Set 第1章 泛型 1.1 泛型概述 集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型.当我们在取出每一个对象, ...

  8. 18.Socket网络编程

    JavaSE高级 网络编程 第一章 网络编程入门 1.1软件结构 C/S结构 :全称为Client/Server结构,是指客户端和服务器结构.常见程序有QQ.迅雷等软件. B/S结构 :全称为Brow ...

  9. 2020java面试必问,找不到工作你找我(一)

    Java 面试宝典 第一章 内容介绍 20 第二章 JavaSE 基础 21 一. Java 面向对象 21 1.面向对象都有哪些特性以及你对这些特性的理解 21 2.访问权限修饰符 public.p ...

最新文章

  1. [bzoj] 1176 Mokia || CDQ分治
  2. 商汤科技举办病理、放疗两大MICCAI国际挑战赛,推动AI医疗落地
  3. 3.6.3 无线局域网
  4. 同学录APP开题报告 2017-12-14
  5. vs.net c# 安装、注册windows service服务,判断服务是否存在,是否启动
  6. 计算机网络专业以后装网线,宽带以后都不用装了? 将会被5G取代?
  7. c语言程序设李忠成主编答案,2007—2008学年第二学期基础学院上机课程表.doc
  8. 为什么C++构造函数不能是虚函数
  9. Havel-Hakimi定理 POJ1659
  10. Springboot小区物业管理系统毕业设计源码051745
  11. CSDN论坛新手指南
  12. js调用Python函数
  13. 大家来找茬源码(微擎) -- 流量主
  14. 在企业工作一年多的几点感悟
  15. EIDROS3.9学习(一)
  16. read.html5.qq.com,如何通过第三方QQ登录网站首页
  17. 苹果备份与恢复_手机照片误删了怎么恢复?不得不说的好方法
  18. 游戏计算机电源,吃鸡一族看过来,游戏PC应配什么电源?
  19. 我去,神操作!虚拟机Ubuntu18.04居然可以安装NVIDIA + 附带安装源码与命令
  20. 不要忘了我们心中的梦

热门文章

  1. java8 steam流在当前数据对象上的操作。判断list中的属性值是否符合条件或者不为空,后赋值另一个属性的操作
  2. Android开发,实现摇一摇功能
  3. iphone X 屏幕适配
  4. iOS-使用第三方实现短信验证码功能
  5. java制作摄影建模,照片建模的拍摄要求
  6. ps把白底图片改为透明
  7. 嵌入式驱动工程师学习路线【建议收藏】
  8. 数智化转型赋能方法论与服务路径
  9. 黑产系列02-黑产画像
  10. 微信公众号上传图片功能