资源视频学习JavaSE阶段整理笔记

来源:互联网 发布:怎么开店淘宝店 编辑:程序博客网 时间:2024/06/05 16:18
1 常用DOS命令

打开控制台

win +R,然后cmd回车

常用命令

d: 回车 盘符切换

dir(directory):列出当前目录下的文件以及文件夹

cd(change directory)改变指定目录(进入指定目录)

进入      cd 目录;cd 多级目录

回退      cd..        ;返回根目录cd\

cls : (clearscreen)清屏

exit : 退出dos命令行

2 JVM<JRE<JDK

       JVM虚拟机

       JRE运行环境

       JDK开发工具包

3 JAVA文件编译流程

 

4 HelloWorld编译

       1.在你的jdk安装的bin目录下面,新建一个文本文件

2.把文件的名字改为HelloWorld,后缀名.java

3.把代码复制过去

4.按CTRL+S键保存

5.打开dos窗口,将目录切换到jdk安装目录的bin目录

6.输入编译指令:javac HelloWorld.java

7.生成HelloWorld.class文件后,输入java HelloWorld,按下回车键

代码:

public class HelloWorld {

       public static voidmain(String[] args){

              System.out.println("HelloWorld");

       }

}

5 环境变量

      

1.找到你的jdk安装目录的bin(不包含bin目录)之前的目录,复制路径

2.在我的电脑右键,选择属性

3.选择高级环境变量

4.选择环境变量

5.新建一个JAVA_HOME,将刚才复制的路径复制到里面

6.将JAVA_HOME配置到path中,采用%JAVA_HOME%

7.打开dos窗口,输入javac和java测试是否配置成功

6 注释

7 关键字

–          被Java语言赋予特定含义的单词

–      组成关键字的字母全部小写

–      常用的代码编辑器,针对关键字有特殊的颜色标记,非常直观,所以我们不需要去死记硬背,在今后的学习中重要的关键字也会不断的出来。

 

8 常量

–      字符串常量 用双引号括起来的内容(“HelloWorld”)

–      整数常量    所有整数(12,-23)

–      小数常量    所有小数(12.34)

–      字符常量    用单引号括起来的内容(‘a’,’A’,’0’)

–      布尔常量    较为特有,只有true和false

–      空常量        null(数组部分讲解)

9 变量

–     数据类型变量名//标识符 = 初始化值;

–      注意:格式是固定的,记住格式,以不变应万变

 

 

10 数据类型

      

整数型

       byte

       shortshort short short

       int

       long

浮点型

       floatfloat float float

       double

字符型

       char

布尔型

       boolean

      

10 标识符

A 作用

–     给包,类,方法,变量等起名字

B 组成规则

–     由字符,下划线_,美元符$组成

•      这里的字符采用的是unicode字符集,所以包括英文大小写字母,中文字符(不建议中文),数字字符等。

–     注意事项

–     不能以数字开头

–     不能是Java中的关键字

 

C : 命名原则:见名知意

示意代码:

    /*

    标识符:就是给包,类,方法,变量起名字的符号。

   

    组成规则:

        A:unicode字符

            数字字符,英文大小写,汉字(不建议使用汉字)

        B:下划线_

        C:美元符$

       

    注意事项

        A:不能以数字开头

        B:不能是java中的关键字

       

    常见命名规则:

        A:基本要求

            见名知意

        B:常见的命名

            a:包(其实就是文件夹,用于对类进行管理)

                全部小写,多级包用.隔开

                

            b:类

                一个单词首字母大写

                    举例:Student,Car

                多个单词每个单词的首字母大写

                    举例:HelloWorld

            c:方法和变量

                一个单词首字母小写

                    举例:age,show()

                多个单词从第二个单词开始每个单词的首字母大写

                    举例:maxAge,getAge()

*/

public class BiaoZhiFu {

    publicstatic void main(String[] args) {

        //定义变量

        //数据类型 变量名= 初始化值;

        int a= 10;

       

        //正确

        intb2 = 20;

        //错误

        //int2b = 30;

       

        //不能是java中的关键字

        //错误

        //intpublic = 40;

    }

}

11 数据类型转换

       隐式数据类型转换

       取值范围小的数据类型与取值范围大的数据类型进行运算,会先将小的数据类型提升为大的,再运算

    隐式转换

        byte,short,char-- int -- long -- float -- double

 

强制数据类型转换

   不建议

目标类型 变量名 = (目标类型) (被转换的数据);

 

12 Eclipse 基本配置

       A:行号的显示和隐藏

              显示:在代码区域的最左边的空白区域,右键 -- ShowLine Numbers即可。

              隐藏:把上面的动作再做一次。

       B:字体大小及颜色

              a:Java代码区域的字体大小和颜色:

window -- Preferences -- General --Appearance -- Colors And Fonts -- Java -- Java Edit Text Font

              b:控制台

window -- Preferences -- General --Appearance -- Colors And Fonts -- Debug -- Console font

              c:其他文件

window -- Preferences -- General --Appearance -- Colors And Fonts -- Basic -- Text Font

       C:窗体给弄乱了,怎么办?

              window-- Perspective -- Reset Perspective   

       D:控制台找不到了,怎么办?

              Window--ShowView—Console

13 Eclipse中辅助键和快捷键

内容辅助键    alt+/

main      然后alt+/

syso       然后alt+/

 

快捷键

注释

单行       选中内容,ctrl+/, 再来一次取消

多行       选中内容,ctrl+shift+/, ctrl+shift+\

格式化           ctrl+shift+f

14 Eclipse中项目的删除和导入

       A:删除项目

              选中项目 – 右键 – 删除

              从项目区域中删除

              从硬盘上删除

       B:导入项目

              在项目区域右键找到import

              找到General,展开,并找到

              Existing Projects into Workspace

              点击next,然后选择你要导入的项目

              注意:这里选择的是项目名称

15 算数运算符

•         运算符

对常量和变量进行操作的符号称为运算符

•       表达式

用运算符把常量或者变量连接起来符号java语法的式子就可以称为表达式。不同运算符连接的式子体现的是不同类型的表达式。

定义两个int类型的变量a,b,做加法(a +b)

•      常用运算符

算术运算符

                            A:什么是运算符

                           就是对常量和变量进行操作的符号。

B:算数运算符有哪些

                            * +,-,*,/,%,++,-- 

字符参与运算

其实是拿该字符对应的数值来操作

‘a’     97

‘A’     65

‘0’     48

++,--运算符:对变量做加1或者减1的操作。

++或者--既可以放在变量的后面,也可以放在变量的前面。

单独使用的时候,++或者--无论是放在变量的前面还是后面,结果是一样的。

参与操作的时候:

             如果++或者--在变量的后面,先拿变量参与操作,后变量做++或者--

    如果++或者--在变量的前面,先变量做++或者--,后拿变量参与操作

赋值运算符

  基本的赋值运算符:=

扩展的赋值运算符:+=,-=,*=,/=,%=

+=:   a+=20;相当于a = (a的数据类型)(a + 20);

 

关系运算符

       关系运算符包含以下内容:

==,!=,>,>=,<,<=

关系运算符的结果都是boolean型,也就是要么是true,要么是false。

注意事项:

关系运算符“==”不能误写成“=”。

逻辑运算符

逻辑运算符有哪些

       &,          |,            ^,           !

       &&,              ||

注意事项:

       a:逻辑运算符一般用于连接boolean类型的表达式或者值。

       b:表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子。

             算术表达式:a + b

              比较表达式:a == b(条件表达式)

 

:结论:

      &逻辑与:有false则false。

      |逻辑或:有true则true。

      ^逻辑异或:相同为false,不同为true。

      !逻辑非:非false则true,非true则false。

       特点:偶数个不改变本身。

三元运算符

A:格式

    (关系表达式)?表达式1:表达式2;

    如果条件为true,运算后的结果是表达式1;

    如果条件为false,运算后的结果是表达式2;

B:示例:

    获取两个数中大数。

    int x=3,y=4,z;

    z = (x>y)?x:y;//z变量存储的就是两个数的大数

16 键盘录入Scanner

 

       A:导包(位置放到class定义的上面)

       importjava.util.Scanner;

B:创建对象

       Scannersc = new Scanner(System.in);

C:接收数据

       intx = sc.nextInt();

键盘录入两个数据求和


 

import java.util.Scanner;

public class ScannerTest {

    public staticvoid main(String[] args) {

        // 创建对象

        Scannersc = newScanner(System.in);

 

        // 接收数据

        System.out.println("请输入第一个数据:");

        int a = sc.nextInt();

 

        System.out.println("请输入第二个数据:");

        int b = sc.nextInt();

 

        // 对数据进行求和

        int sum = a + b;

        System.out.println("sum:"+sum);

    }

}

键盘录入两个数据是否相等


import java.util.Scanner;

 

/*

 * 键盘录入两个数据,比较这两个数据是否相等

 */

public class ScannerTest2 {

    public staticvoid main(String[] args) {

        // 创建对象

        Scannersc = newScanner(System.in);

 

        // 接收数据

        System.out.println("请输入第一个数据:");

        int a = sc.nextInt();

 

        System.out.println("请输入第二个数据:");

        int b = sc.nextInt();

 


        // 比较两个数据是否相等

        // boolean flag = ((a == b) ? true : false);

        boolean flag= (a == b);

        System.out.println("flag:"+flag);

    }

}

 

键盘录入三个数据获取最大值


 

import java.util.Scanner;

 

/*

 * 键盘录入三个数据,获取这三个数据中的最大值

 */

public class ScannerTest3 {

    public staticvoid main(String[] args) {

        // 创建对象

        Scannersc = newScanner(System.in);

 

        // 接收数据

        System.out.println("请输入第一个数据:");

        int a = sc.nextInt();

 

        System.out.println("请输入第二个数据:");

        int b = sc.nextInt();

 

        System.out.println("请输入第三个数据:");

        int c = sc.nextInt();

 

        // 如何获取三个数据的最大值

        int temp =(a > b? a : b);

        int max = (temp > c ? temp : c);

 

        System.out.println("max:"+max);

    }

}

17 选择流程控制语句

1.   if语句,三种格式

第一种

if(关系表达式){

语句体;

}

第二种

             

 

if(关系表达式){

       语句体1;

}else{

语句体2;

}

 

第三种

if(关系表达式){

语句体1;

}else if(关系表达式){

语句体2;

}else if(关系表达式){

语句体3;

}.

.

.

.

else{

语句体n+1;

}

 

 

 

2.   switch语句

 

switch(表达式){

case *:

      语句体1;

       break;

case *:

       语句体2;

       break;

.

.

.

.

.

default:

       都不是的情况语句体;

       break;

}

 

 

cast穿透

如果后面没有break,那么继续往下.

 

18 循环流程控制语句

       for循环

      

 

              for(初始化语句;判断条件语句;控制条件语句){

 

              循环体语句;

 

}

 

 

求个十百……位格式

int a =num;

int ge =a%10;

int shi= a/10%10;

int bai= a/10/10%10;

.

.

.

 

 

 

 

       while循环

 

 

初始化值

while(判断条件语句){

 

循环语句体;

控制条件语句;

}

 

 

       do……while循环

初始化语句;

do{

 

循环体语句;

控制条件语句

 

}while(判断条件语句);

 

 

注意:至少执行一次循环体语句

 

 

       控制循环语句

      

break结束(跳出)当前循环.

continue跳过当前次循环句.


/*

 * 按要求分析结果,并验证

 *

 * break:输出2

 * continue:输出7

 */

public class BreakAndContinueDemo{

    public staticvoid main(String[] args) {

 

        for (intx = 1;x<= 10; x++) {

            if (x % 3== 0) {

                // 分别写breakcontinue,说说输出几次

                //break;输出3

                continue;//输出7次

            //System.out.println("我爱林青霞");//输出13次

            }

            System.out.println("我爱林青霞");

        }

 

    }

}

 

 

19 随机Random

       导包: import java.util.Random;

       创建对象: Random r = new Random();

       获取随机数: int a = r.nextInt(10);

       这个 10是[0,10) 包括0但是不包括10.

 

 

       publicclass RandomTest {

       publicstatic void main(String[] args) {

              Randomr = new Random();

              //获取随机数

              intnumber = r.nextInt(100) + 1;

              while(true){

                     //键盘录入我们要猜的数据

                     Scannersc = new Scanner(System.in);

                     System.out.println("请输入你要猜的数据(1-100):");

                     intguessNumber = sc.nextInt();

                    

                     //比较这两个数据,用if语句实现

                     if(guessNumber> number) {

                            System.out.println("你猜的数据"+guessNumber+"大了");

                     }elseif(guessNumber < number) {

                            System.out.println("你猜的数据"+guessNumber+"小了");

                     }else{

                            System.out.println("恭喜你,猜中了");

                            break;

                     }

              }

       }

}

20 数组

 

       数组的概述:

       数组是存储同一种数据类型的容器。

       数组既可以存储基本数据类型,也可以存储引用数据类型。

 

数组的定义格式:

       格式1:数据类型[] 数组名;(推荐使用)

       格式2:数据类型 数组名[];

       注意:这两种定义完成后,数组中是没有元素值的。

 

举例:

       int[]arr; 定义了一个int类型的数组,数组名是arr。

       int arr[]; 定义了一个int类型的变量,变量名是arr数组。

 

       动态初始化

       动态初始化指定数组长度,

       系统默认指定元素.

格式:数据类型[] 数组名 = new 数据类型[数组长度];

       int[]arr = new int[10];

       静态初始化

       静态初始化指定数组元素,

       数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...};

 

              举例:

                     int[] arr = new int[]{1,2,3};

 

       数据类型[] 数组名 = {元素1,元素2,元素3,...}; 

              int[] arr = {1,2,3};

      

       直接输出arr是数组地址.输出数组内容arr[索引]

 

Java当中内存分配图解

 

静态初始化内存图解

两个数组指向同一个地址

数组常见问题

       1 ArrayIndexOutOfBoundsException:角标越界异常(下标越界或者索引越界异常);

       2 NullPointerException:空指针异常;

 

数组长度:

 arr.length

 

       遍历数组

      for(int i = 0; i<arr.length;i++){

      

       arr[i];

 

       }

       数组获取最值

例如取最大值

 

       定义一个参照

       intmax = arr[0];

       //先遍历

       for(inti = 1; i<arr.length;i++){

              //对比保留最大值

              if( arr[i] > max ){

 

              max= arr[i];

}

 

       }

输出max即为最大值.

 

       二维数组

二维数组:就是元素为一维数组的数组

定义格式

数据类型[][] 数组名;

数据类型 数组名[][]; 不推荐

数据类型[] 数组名[]; 不推荐

初始化方式

动态初始化:

数据类型[][] 变量名 = new 数据类型[m][n];

m:表示这个二维数组有多少个一维数组

n:表示每一个一维数组的元素个数

静态初始化:

数据类型[][] 变量名 = new 数据类型[][]{{元素…},{元素…},{元素…}};

简化版格式:数据类型[][] 变量名 = {{元素…},{元素…},{元素…}};

 

 

遍历二维数组

int[][]arr = new int[m][n];

for(inti = 0 ; i < arr.length ; i++){

 

   for(int x = 0; x < arr[i].length ; x++){

       System.out.println(arr[i][x]);

}

}

System.out.println(换行)

 

System.out.print(无换行)

 

21 方法

 

 

       提取出具有功能的代码。

       方法:具有特定功能的代码块。

格式

工作方式

22 面向对象

  C:Java中最基本的单位是类,Java中用class描述事物也是如此

 成员变量   就是事物的属性

 成员方法   就是事物的行为

D:定义类其实就是定义类的成员(成员变量和成员方法)

 a:成员变量       和以前定义变量是一样的,只不过位置发生了改变。在类中,方法外。

 b:成员方法      和以前定义方法是一样的,只不过把static去掉,后面在详细讲解static的作用。

* 我们如何创建对象呢?

 *      格式:类名对象名 =new类名();

 * 对象如何访问成员呢?

 *      成员变量:对象名.变量名

 *      成员方法:对象名.方法名(...)

一个对象内存图

两个引用指向同一个对象内存图

 

成员变量和局部变量的区别

成员变量和局部变量的区别:

 *      A:在类中的位置不同

 *          成员变量:类中,方法外

 *          局部变量:方法中或者方法声明上(形式参数)

 *      B:在内存中的位置不同

 *          成员变量:堆内存

 *          局部变量:栈内存

 *      C:生命周期不同

 *          成员变量:随着对象的创建而存在,随着对象的消失而消失

 *          局部变量:随着方法的调用而存在,随着方法的调用完毕而消失

 *      D:初始化值的问题

 *          成员变量:有默认值

 *          局部变量:没有默认值。必须先定义,赋值,最后使用

 

private

A:把成员变量用private修饰

B:提供对应的getXxx()/setXxx()方法

 

private:

 *      是一个修饰符

 *      可以修饰成员变量,也可以修饰成员方法

 *      private修饰的成员只能在本类中被访问

针对private修饰的成员变量,我们会相应的提供getXxx()和setXxx()用于获取和设置成员变量的值,方法用public修饰

 

this

A:this:代表所在类的对象引用

方法被哪个对象调用,this就代表那个对象

B:什么时候使用this呢

局部变量和成员变量重名

 

23 面向对象构造方法

 

A:构造方法格式

a:方法名与类名相同

b:没有返回值类型,连void都没有

c:没有具体的返回值

如果你不提供构造方法,系统会给出默认构造方法

如果你提供了构造方法,系统将不再提供

构造方法也是可以重载的,重载条件和普通方法相同

 

构造方法:

 *      给对象的数据进行初始化

 *

 * 格式:

 *      方法名和类名相同

 *      没有返回值类型,连void都不能写

 *      没有具体的返回值

 *

 * 构造方法的注意事项:

 *      A:如果我们没有给出构造方法,系统将会提供一个默认的无参构造方法供我们使用。

 *      B:如果我们给出了构造方法,系统将不在提供默认的无参构造方法供我们使用。

 *        这个时候,如果我们想使用无参构造方法,就必须自己提供。

 *        推荐:自己给无参构造方法

 *      C:构造方法也是可以重载的

 *

 * 成员变量赋值:

 *      A:setXxx()方法

 *      B:带参构造方法   

 

 

学生类标准代码


/*

 * 学生类

 */

public class Student {

    //成员变量

    private String name;

    private int age;

   

    //构造方法

    public Student() {}

   

    public Student(Stringname,int age) {

        this.name = name;

        this.age = age;

    }

   

    //成员方法

    public void setName(Stringname){

        this.name = name;

    }

   

    public String getName(){

        return name;

    }

   

    public void setAge(intage){

        this.age = age;

    }

   

    public int getAge() {

        return age;

    }

}

 

 


/*

 * 学生类的测试类

 */

public class StudentDemo {

    public static void main(String[]args) {

        //无参+setXxx()

        Students = new  Student();

        s.setName("林青霞");

        s.setAge(28);

        System.out.println(s.getName()+"---"+s.getAge());

       

        //带参构造

        Students2 = new Student("林青霞",28);

        System.out.println(s2.getName()+"---"+s2.getAge());

    }

}

 

24 String类

通过JDK提供的API,查看String类的说明

A:"abc"是String类的一个实例,或者成为String类的一个对象

B:字符串字面值"abc"也可以看成是一个字符串对象

C:字符串是常量,一旦被赋值,就不能被改变

D:字符串本质是一个字符数组

‘f

 

构造方法

构造方法:

 *      String(Stringoriginal):把字符串数据封装成字符串对象

 *      String(char[]value):把字符数组的数据封装成字符串对象

 *      String(char[]value, int index, int count):把字符数组中的一部分数据封装成字符串对象

 

判断功能

/*

 * Object:是类层次结构中的根类,所有的类都直接或者间接的继承自该类。

 * 如果一个方法的形式参数是Object,那么这里我们就可以传递它的任意的子类对象。

 *

 * String类的判断功能:

 * booleanequals(Object obj):比较字符串的内容是否相同

 * booleanequalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写

 * boolean startsWith(Stringstr):判断字符串对象是否以指定的str开头

 * booleanendsWith(String str):判断字符串对象是否以指定的str结尾

 */

 

获取功能 

/*

 * String类的获取功能:

 * int length():获取字符串的长度,其实也就是字符个数

 * char charAt(intindex):获取指定索引处的字符

 * int indexOf(Stringstr):获取str在字符串对象中第一次出现的索引

 * String substring(intstart):start开始截取字符串

 * Stringsubstring(int start,int end):start开始,到end结束截取字符串。包括start,不包括end

 */

 

转换功能

/*

 * String类的转换功能:

 * char[]toCharArray():把字符串转换为字符数组

 * StringtoLowerCase():把字符串转换为小写字符串

 * StringtoUpperCase():把字符串转换为大写字符串

 *

 * 字符串的遍历:

 *     A:length()加上charAt()

 *     B:把字符串转换为字符数组,然后遍历数组

 */

 

其他功能

/*

 * 去除字符串两端空格  

 *     String trim()

 * 按照指定符号分割字符串  

 *     String[] split(String str)

 */

 

25 StringBuilder类

StringBuilder是创建一个缓冲区来进行操作.

StringBuilder:是一个可变的字符串。字符串缓冲区类。 

String和StringBuilder的区别:

  String的内容是固定的

  StringBuilder的内容是可变的

 

构造方法

    StringBuilder()

成员方法

public StringBuilder append(任意类型):添加数据,并返回自身对象

 

案例


/*

 * 添加功能

 *     public StringBuilder append(任意类型):添加数据,并返回自身对象

 * 反转功能

 *     public StringBuilder reverse()

 */

public class StringBuilderDemo {

    public static void main(String[] args) {

       //创建对象

       StringBuilder sb = new StringBuilder();

      

       //public StringBuilder append(任意类型)

       //StringBuilder sb2 =sb.append("hello");

      

       /*

       System.out.println("sb:"+sb);

       System.out.println("sb2:"+sb2);

       System.out.println(sb == sb2);//true

       */

      

       /*

       sb.append("hello");

       sb.append("world");

       sb.append(true);

       sb.append(100);

       */

      

       //链式编程

       sb.append("hello").append("world").append(true).append(100);

      

       System.out.println("sb:"+sb);

      

       //public StringBuilder reverse()

       sb.reverse();

       System.out.println("sb:"+sb);

      

    }

}

 

StringBuilder和String通过方法完成相互转换


/*

 * StringBuilderString的相互转换

 *

 * StringBuilder --String

 *     public String toString():通过toString()就可以实现把StringBuilder转成String

 *

 * String --StringBuilder

 *     StringBuilder(String str):通过构造方法就可以实现把String转成StringBuilder

 */

public class StringBuilderTest {

    public static void main(String[] args) {

       //StringBuilder -- String

       /*

       StringBuilder sb = newStringBuilder();

       sb.append("hello").append("world");

      

       String s = sb.toString();

       System.out.println(s);                                                                                                                                                            

       */

      

       //String -- StringBuilder

       String s = "helloworld";

       StringBuilder sb = new StringBuilder(s);

       System.out.println(sb);

    }

}

 

26 ArrayList集合

* 集合类的特点:

 *          长度可变。

 *

 *ArrayList<E>:

 *          大小可变数组的实现

 *

 *          <E>:是一种特殊的数据类型,泛型。

 *          怎么用呢?

 *                 在出现E的地方我们使用引用数据类型替换即可

 *                 举例:ArrayList<String>,ArrayList<Student>

 

添加元素:

 *          public boolean add(E e):添加元素

 *          public void add(int index,Eelement):在指定的索引处添加一个元素

 

ArrayList删改查方法

A:获取元素

   public E get(int index):返回指定索引处的元素

B:集合长度

     publicint size():返回集合中的元素的个数

C:删除元素

   public boolean remove(Object o):删除指定的元素,返回删除是否成功

   public E remove(int index):删除指定索引处的元素,返回被删除的元素

D:修改元素

public E set(int index,E element):修改指定索引处的元素,返回被修改的元素

 

27 IO流

IO流用来处理设备之间的数据传输

   Java对数据的操作是通过流的方式

   Java用于操作流的类都在IO包中

    流按流向分为两种:输入流,输出流

FileWriter类

    public class Copy {

    public static void main(String[] args)  throwsIOException {

       

        String read = "c.txt";

        String writer = "testcopy.txt";

       

        testcopy1(read,writer);

        testcopy2(read,writer);

        testcopy3(read,writer);

        testcopy4(read,writer);

        testcopy5(read,writer);

       

    }

 

    private static void testcopy5(String read, Stringwriter) throws IOException {

        BufferedReader br = new BufferedReader(newFileReader(read));

        BufferedWriter bw = new BufferedWriter(newFileWriter(writer));

        String line;

        while( ( line = br.readLine() ) !=null){

            bw.write(line);

            bw.newLine();

        }

        br.close();

        bw.close();

    }

 

    private static void testcopy4(String read, Stringwriter) throws IOException {

        BufferedReader br = new BufferedReader(newFileReader(read));

        BufferedWriter bw = new BufferedWriter(newFileWriter(writer));

        char[] ch = new char[1024];

        int len;

        while((len=br.read())!=-1){

            bw.write(ch, 0,len);

        }

        bw.close();

        br.close();

       

    }

 

    private static void testcopy3(String read, Stringwriter) throws IOException {

        BufferedReader br = new BufferedReader(newFileReader(read));

        BufferedWriter bw = new BufferedWriter(newFileWriter(writer));

        int ch;

        while((ch=br.read())!=-1){

            bw.write(ch);

        }

        bw.close();

        br.close();

       

    }

 

    private static void testcopy2(String read, Stringwriter) throws IOException{

        FileReader fr = new FileReader(read);

        FileWriter fw = new FileWriter(writer);

        char[] ch = new char[1024];

        int len;

        while((len=fr.read(ch))!=-1){

            fw.write(ch, 0,len);

        }

        fw.close();

        fr.close();

       

       

    }

 

    private static void testcopy1(String read, Stringwriter) throws IOException {

        FileReader fr = new FileReader(read);

        FileWriter fw = new FileWriter(writer);

       

        int ch ;

        while ((ch=fr.read())!=-1) {

            fw.write(ch);

           

        }

        fw.close();

        fr.close();

    }

}

 

 

 

28 补充

 

面相对象

       在Java中使用类来描述现实生活中的所有事物,事物的行为就是动词使用方法来描述,事物的属性就是名词使用成员变量来描述。

一个类中拥有的成员包括:

       成员变量

       构造方法

       普通方法

 

对象在内存中的位置

              对象在内存中的位置:

对象由new关键字创建,和数组一样,只要使用new关键字开辟的空间都在堆内存中。

任何事物都可以定义成类,创建这个类的对象,属于引用数据类型。

而对象的引用变量存储的值是该对象堆内存中的地址。

             

this

1.只和对象有关,和类无关 记录对象的地址

2.区分成员变量和局部变量

3.在本类中构造方法之间的调用 调用格式: this(参数列表); 注意:要求调用语句必须位于第一行。

 

A:this一般出现在类的一个方法的定义当中,代表当前对象的引用。即this记录着当前调用这个方法执行的对象地址。

B:当一个类定义好之后,如果不创建对象this是没有意义的。this只和对象有关。没有对象就没有this。

C:一个类可以有多个对象。每个对象的堆空间中都有各自的属性值,而使用this就可以区分这些成员变量的值,同时this还可以解决成员变量和局部变量同名的问题。

 

29 匿名对象(了解)

匿名对象:就是指没有名称的对象。

 

      

说明:匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。

 

上述代码结果:

出现以上问题的原因如下图所示:

 

注意:只要在程序中使用new关键字创建对象,那么在堆中都会有一个新的对象产生。

 

注意:匿名对象通常是在对象只需要访问成员一次的情况下使用

 

 

30 集合要点

       学习过的容器:变量,数组,字符串缓冲区、集合。

回顾之前都学习过哪些容器可以保存数据:

 

1)变量空间中就可以保存数据;

2)数组中可以保存多个类型相同的数据;

3)字符串缓冲区中可以保存任何的数据,最后都变为字符串类型;

4)集合只能存储引用数据类型;ArrayList。

 

              容器 存储数据

       之前学习的容器:

       变量 只能存储一个

       数组 存储多个数据 只能存储单一类型 长度不变

       字符串缓冲区  StringBuffer线程安全 效率低 StringBuilder  线程不安全 效率高

       数组

       致命缺点:不管什么数据类型,只要向缓冲区中存储以后都变为字符串

       "12"

       集合 :存储多个数据 长度可变 向集合中存储数据的时候数据类型不会改变。只能存储引用数据类型,

       不能存储基本数据类型。

       (多)

       ArrayList

31 IO流要点

    IO流对象

     FileWriter 将数据从内存中写出到文本文件中

     FileReader 从硬盘的文本文件中读取数据到内存中

     BufferedWriter 将数据从内存中写出到文本文件中, 写入换行 newLine()

     BufferedReader 从硬盘的文本文件中读取数据到内存中, 读取文本一行 readLine()

   读写

     FileWriter  写数据: 字符,字符数组,字符串

     BufferedWriter 写数据: 字符,字符数组,字符串,换行

方法:

voidwrite(char[] cbuf)  字符数组

void write(intc) 写入单个字符。

voidwrite(String str)  写入字符串。

    

     FileReader 读数据: 字符,字符数组

     BufferedReader 读数据:字符,字符数组,文本行

方法:

 int read() 读取单个字符。

 int read(char[] cbuf) 将字符读入数组。

 

字符流特点:

1.读取字符数据 文本文件 .txt .java .ini

能够使用windows系统自带的软件记事本打开并能够看得懂的文件就是文本文件

2.自带缓冲区

字符输入流: FileReader 对应缓冲区: BufferedReader  方法:readLine()

字符输出流: FileWriter 对应缓冲区: BufferedWriter  方法: newLine()

 

字节流不自带缓冲区

 

32 继承(extends)

    面相对象语言三大特征;

    封装(private)

    继承

    多态

继承:继承打破了封装性,子类是不可以使用父类中私有的成员

抽取共同的成员,组成父类,子类继承父类

 

格式:

public class 类1 extends类2{

    //代码

}

 

继承的特点

1)继承的好处:提高代码复用性。

2)Java语言支持单继承和多重继承(多层次继承),不支持多继承。

单继承:一个子类只能有一个父类。

多继承:一个子类可以有多个父类。-----(后期可实现)

 

 

不同类之间访问成员有几种方式:

1.通过对象访问

2.继承

3.静态

一。继承中的成员变量

在java中任何类中都有一个默认无参构造函数

this和super区别:

this:本类 记录对象地址 区分本类成员变量和局部变量 本类构造函数调用

super :继承。

在子类中调用父类中的成员变量:super.成员变量名

在子类中调用父类中的构造函数:super(参数列表)

在子类中调用父类中的成员函数:super.成员函数名(参数列表);

区别:super不是记录对象地址的

super 起到一个标识作用,标记着哪个空间是父类空间

 

二、继承中的成员方法(**********)

方法定义格式:

方法修饰符 方法返回值类型 方法名(参数列表)

{

       return返回值;

}

 

方法重载:同一类、方法名相同 、参数列表不同:参数类型 个数 顺序

方法重写、复写、覆盖:

1.必须有继承

2.方法返回值类型  方法名 参数列表必须相同

 

关于方法复写:函数头一模一样即可。

 

静态方法不参与方法复写.

三、继承中的构造方法(***)

 

在本类中使用this调用构造函数要求必须是第一行

使用super调用父类中的构造函数要求也必须是第一行

 

33、抽象类:就是看不懂的类。

实现接口可以不复写方法,但是子类必须复写

查找源代码快捷键:Ctrl+shift+T

alt+shift+M 抽取方法

1、子类在继承抽象类后,需要把抽象类中所有的抽象方法全部复写完成。

 

抽象类中定义所有子类的共性行为,然后由具体的子类针对自己的实际情况复写父类提供的基本行为,建立适合自己的功能体。

 

2、抽象类和一般类有什么区别?

抽象类肯定需要abstract修饰,一般类不能使用。

不管是抽象类,还是一般类,它们都是描述事物体系中的某个事物,只不过抽象类描述的一定是这个事物体系中的共性内容,抽象类不一定是最顶层的类,但一定不是最底层的类。

 

3、抽象类有没有构造函数,能不能创建对象?

有构造函数,但不能创建对象。

4、抽象类一定是父类吗?

一定是父类,一定不是顶层父类。

抽象类中通常都有抽象函数,而抽象类中的抽象函数要求必须由子类来复写(由具体的子类来实现其中的函数体)。

子类的主要作用是复写抽象类中的抽象函数。

5、抽象类可以继承其他类吗?

抽象类也是一个类,因此它必须具备类的继承特点。它可以有父类。

 

6、抽象关键字不能和哪些关键字共存?

private修饰符:表示私有的。

private :父类中私有的成员,子类是不知道的,因此使用private 和abstract关键字一起修饰函数,导致子类根本无法知道父类中有个抽象函数,同时也导致了子类不能复写父类中的方法。

static修饰符:表示静态的。(先了解)

static:如果使用static和abstract关键字一起修饰抽象函数,导致这个函数可以使用类名直接调用,而抽象函数是没有方法体的,调用这个抽象函数是没有意义的。

final修饰符:表示最终的。(先了解)

final :final修饰的函数子类是无法复写的,而abstract修饰的函数,要求子类必须复写。

 

 

抽象类何时使用:

当描述事物体系,一般在描述所有体系中最共性的内容时,通常是只知道体系的共性功能,却不能书写具体功能体,这时会使用抽象函数表示,那么这个类一定会使用抽象类表示。

34、接口(interface)

      

       类定义格式:

class 类名

{

}

接口定义格式:

interface 接口名

{

}

接口名  也是标识符的一种,定义规则和类名一模一样

举例:HelloWorld

 

1.定义格式 使用关键字 interface

2.接口和类之间的关系叫做实现 格式:class 类名 implements 接口名

class 类名

{     

       成员变量

       成员方法

       构造方法

       构造代码块

       {

      

       }

}

interface 接口名

{

       成员变量

       finalpublic static  int x=8;

       成员方法

       publicabstract void show();

 

关于成员变量和成员方法都有固定的修饰符

成员变量的固定的修饰符: public static final

成员方法的固定的修饰符:(重要性啥也不说了)

public abstract

那么也就是说接口中的方法全部是抽象方法。

 

类和接口之间的关系:

类和类之间叫做继承 使用关键字 extends  特点:支持单继承 多重继承 不支持多继承 不确定性 有函数体

接口和接口之间叫做继承使用关键字 extends 特点:支持单继承 多重继承 支持多继承 没有不确定性因为接口中的方法没有方法体,使用谁都一样

类和接口之间叫做实现  使用关键字 implements

类可以同时实现多个接口,原因:方法没有方法体,使用谁都一样

 

35、多态:就是多种表现形态。

在Java中的多态代码体现:

使用父类的引用,表示自己的子类对象。

 

java中的多态就是父类引用或者父接口指向子类或者实现类对象。

Animal a=newCat();

class Demoimplements Inter

{

}

Inter i=newDemo();

Cat c=newCat();

 

多态弊端:只能使用父类中共有的方法,不能使用子类特有的方法。

想法:前提是多态已经发生了,就想使用子类特有的方法,怎么办?

需要类型转换,将父类引用转换子类类型就可以使用了。

       Animala=new Cat(); 隐式类型转换 :小的数据类型给大的数据类型赋值 double d=3;

强制类型转换:大的数据类型给小的数据类型赋值  int i=1.2;

格式:小数据类型 变量名=(小数据类型)大的数据

 inti=(int)1.2;---->i=1

 引用数据类型的强制转换格式:小数据类型变量名=(小数据类型)大的数据

 Animal a=new Cat();

 

强制转换

if(父类引用变量名 instanceof 子类类型)

{

       子类类型 变量名=(子类类型)父类引用变量名;

}

 

 举例:Cat c=(Cat)a;

多态成员特点:

1.    多态中的成员变量特点:无论编译还是运行只看父类

2.    重要性:很重要

 多态中的非静态成员方法特点:编译看父类,运行先看子类,如果子类没有再看父类

 List list=new ArrayList();//多态

 Collection coll=newArrayList();//多态

 list.add();

36 静态(static)

static 修饰成员变量和成员函数 只能被类调用只和类有关,和对象一点毛关系没有

静态不可以使用非静态

static 修饰成员变量 类名直接访问 类一加载到方法区就开辟空间并赋值

被static关键字修饰的函数,它不需要对象调用,可以直接通过   类名.函数名(实际参数)   方式调用

 

通过类名调用static修饰的函数

 

小结:

    1、被static修饰的成员函数,称为静态成员函数。

    2、通常在访问静态函数的方式是通过类名来访问。

3、 访问静态成员函数的方式:  类名.静态函数名(参数列表)。

4、 只要一个函数被static关键字所修饰,那么这个函数就和对象没有关系了,只和类有关系。

5、 在静态函数中不能使用非静态成员变量。

1、静态函数,也称为类函数。使用类名去调用静态的函数。

        非静态的函数,也称为实例函数。使用对象名(实例名)来调用实例函数。

2、静态关键字是一个修饰符。可以修饰类中的成员函数和成员变量。不能修饰构造函数

3静态函数它是在类加载的时候,就在内存中加载完成,可以直接运行的函数。

非静态函数,它的运行必须是在类加载完成之后,通过new关键字创建出对象之后,通过对象才能调用。

4、静态函数中不能调用非静态函数。

因为静态函数在类加载完成之后通过类名可以直接调用,而这时很有可能还没有创建对象。非静态函数必须依赖于对象才能运行。

 

5、非静态函数中是可以调用静态函数的。

当非静态函数可以运行的时候,在内存中一定有个对象,既然有对象了,就说明对象所属的那个类肯定已经被加载完成了。类都加载完成了,静态函数已经准备就绪。

 

6、静态函数中不能使用this 和super关键字。

this关键字它表示的是当前调用这个函数的那个对象。而在静态函数中是没有对象的。

静态代码块:

static

{

       //给类初始化使用

}

执行时间:类加载时执行。

37 单例设计模式

保证对象唯一

单例设计模式:

       a:私有化本类中的所有构造函数

       b:在本类中创建对象

       c:提供方法让外界访问

两种

1饿汉式(常用)

 

class Single{

       1,私有化本类所有的构造方法

       privateSingle (){}

2.在本类中创建对象

       privatestatic Single s = new Single ();//静态

3.给外界提供方法访问返回的对象

       publicstatic Single getInstance (){//静态

              returns;

       }

void show(){

       syso(“show….”)

}

 

}

 

2 懒汉式(面试)//用到再加载

class Single{

       1,私有化本类所有的构造方法

       privateSingle (){}

2.在本类中创建对象

       privatestatic Single s = null;//静态

3.给外界提供方法访问返回的对象

       publicstatic Single getInstance (){//静态

              if( s == null){ //调用了方法如果S为空,那么赋值对象

       s = new Single();

}

              returns;

       }

void show(){

       syso(“show….”)

}

 

}

38 包(package)

       包就是文件夹,

作用:管理class文件

包命名规则:字母小写

公司域名倒写

jd.com

com.jd


打包使用关键字: package 包名


打包要求必须位于源文件中的第一行

 

包与包之间访问

       第一种:包名.类名

       第二种: (常用)

       导包(import)包名下类名上

       格式: import 包名.类名

39 四种访问权限修饰符

public 公共权限 权限最大 可以在本类中可以使用在同一包下不同类中也可以访问 不同包下也可以使用

protected 可以在本类中可以使用 在同一包下不同类中也可以访问 不同包下的子类访问

default 默认权限 本类中可以使用 在同一包下不同类中也可以访问

private 私有权限 最小的 他修饰的内容只能在本类中使用

public > protected > default > private

40 final修饰符

表示结束的,完成的,(其实就是完成体不可进行修改)

final 修饰类 成员变量 局部变量 成员方法

修饰的成员变量-----常量

修饰的成员方法-----不可重写

修饰的类-----------不可被继承

修饰的方法---------不能被子类重写

修饰的地址---------可以修改对象地址内的成员

小结:

    1)被final修饰的成员变量和局部变量,编译后变为常量,不能修改其值;

    2)被final修饰的成员函数,不能被子类方法重写

    3)被final修饰的类,不能被子类继承

41 内部类

 

内部类:内部的类

class 外部类

{

       class成员内部类

       {

       }

       publicvoid show()

       {

              class局部内部类

              {

              }

       }

}

内部类有两种:

按位置分:

位于外部类的成员位置:成员内部类

位于外部类的局部位置:局部内部类

 

Outer$Inner.class 这个是成员内部类的class文件名,这个文件真正的名字其实是Outer.Inner

 

匿名内部类

匿名内部类:没有名字的内部类。

格式:

 

new 父类或者父接口()

{

       //复写父类或者父接口中的方法

};

 

42 Object类

Object 类 他是所有类的父类

equals

== 和equals区别:

基本数据类型使用 ==

equals是用来比较引用数据类型,但是要求必须复写方法

toString()

Student s=new Student();

toString()

System.out.println(s.toString());

 

43 异常

异常:不正常。

 

空指针异常 NullPointerException

数组角标越界异常 ArrayIndexOutOfBoundsException

异常:

Throwable

       ErrorException

分类:

编译时异常: Exception

       编译时异常必须要处理:

              声明: throws

              publicvoid show() throws 异常类,异常类,。。。。

              {

                     throw

              }

              捕获:自己处理

              try

              {

                     可能发生异常的代码

              }

              catch(捕获的异常类 变量名)

              {

                     处理的异常代码

              }

Alt+Shift+Z抓异常

 

运行时异常: RuntimeException

也可以声明和捕获,一般捕获。

 

自定义异常:

class DemoException extendsRuntimeException

{

       构造方法

}

 

throw 和 throws 区别:

throw 是用来抛异常,用在函数体内部

throw new 异常类名();

 

throws 表示声明异常,使用在函数参数列表后面,函数体抛什么异常,那么函数头声明什么异常

声明的目的是让调用者来处理异常

 

如果捕获多个异常,那么格式如下:

              1.

              try

              {

                     可能发生异常的代码

              }

              catch(捕获的异常类 变量名)

              {

                     处理的异常代码

              }

              2.

              try

              {

                     可能发生异常的代码

              }

              catch(捕获的异常类 变量名)

              {

                     处理的异常代码

              }catch(捕获的异常类变量名)

              {

                     处理的异常代码

              }

              }catch(捕获的异常类变量名)

              {

                     处理的异常代码

              }.....

 

 

              3.try

              {

                     可能发生异常的代码

              }

              catch(捕获的异常类 变量名)

              {

                     处理的异常代码

              }finally

              {

                     必须执行的代码

              }

 

44 正则表达式

验证

正则表达式只是为了简化操作字符串的.

注意:在正则中关于次数除了{},还有几个特殊的符号:

                    *:0  1  n

                    +:1  n

                    ?:0  1

如果使用\需要转义\\

 

案例1:

需求:验证QQ号码是否合法。

  分析:

      1、第一位不能是零;

      2、QQ号码在5到12之间(包含);

3、QQ号码都是由数字组成;

说明:

1、String类中提供一个matches()函数,可以判断字符串对象是否匹配正则表达式。

 

       1)如果匹配,则返回true;

       2)如果不匹配,则返回false;

2、 [1-9]:表示字符串中第一位能够出现1~9任何一个数字;

3、 [0-9]{4,11}:表示字符串中从第2位开始后面的数字只能出现0~9之间的数字,并且最少出现4次,最多出现11次;

4、 如果满足上述条件则返回true,否则返回false

 

上述案例代码如下:

 


/*

 * 需求:验证QQ号码是否合法。

 分析:

 1、第一位不能是零;

 2QQ号码在512之间(包含);

 3QQ号码都是有数字组成;

 */

public class RegexDemo {

    public static voidmain(String[] args) {

       method_1();

    }

    // 使用正则表达式完成QQ号码的验证

    private static voidmethod_1() {

       // 定义一个字符串变量

       String QQ = "12345";

       /*

        *String类中提供一个matches()函数,可以判断字符串对象是否匹配正则表达式

        * 如果匹配,则返回true

        * 如果不匹配,则返回false

        *[1-9]:表示字符串中第一位能够出现1~9任何一个数字

        *[0-9]{4,11}:表示字符串中从第2位开始后面的数字只能出现0~9之间的数字,并且最少出现4次,最多出现11

        * 如果满足上述条件则返回true,否则返回false

        */

       boolean flag= QQ.matches("[1-9][0-9]{4,11}");

       System.out.println(flag);

    }

}

 

注意:正则表达式只能使用在字符串上。

切割

需求:使用String类中的split函数根据正则表达式规则,以数字对已知的字符串进行切割。

1)定义RegexDemo2 类;

2)在这个类中定义一个字符串str,并赋值为”sfajs12321dbfj234d23sjfk454sdjf565sdhd757hf”;

3)定义一个正则表达式规则:regex=”[0-9]+”;

4)使用定义好的字符串str调用split()函数对正则表达式进行切割;

5)遍历切割后的数组;

 


/*

 * 需求:使用String类中的split函数根据正则表达式规则,以数字对已知的字符串进行切割。

 1)定义RegexDemo2类;

 2)在这个类中定义一个字符串str,并赋值为sfljs12321dlfj234d23sjfk454sdjf565sdhd757hf”;

 3)定义一个正则表达式规则:regex=”\\d+”;

 4)使用定义好的字符串str调用split()函数对正则表达式进行切割;

 5)遍历切割后的数组;

 */

public class RegexDemo2 {

    public static voidmain(String[] args) {

       // 定义一个字符串

       String str = "sfajs12321dbfj234d23sjfk454sdjf565sdhd757hf";

       // 定义一个正则表达式,以数字对上述字符串进行切割{"sfajs","dbfj","d","sjfk"}

       String regex = "\\d+";

       String[] strs = str.split(regex);

       // 遍历数组

       for (int i = 0; i < strs.length;i++) {

           // 打印数组中的数据

           System.out.println(strs[i]);

       }

    }

}

 

 

45 基本数据类型包装类

对基本数据类型封装成对象,可以有更多功能操作

基本数据类型     : byte short int     long floatdouble char      boolean

基本数据类型包装类: Byte Short Integer Long FloatDouble Character Boolean

 

 

jdk1.5之后的自动装箱和拆箱:

自动装箱:可以直接把一个基本类型的数据赋值给自己对应的包装类型。

//定义一个int类型数据

       intx=123;

       //使用jdk5以前办法将基本数据x变成包装类型

       Integer i = newInteger(x);

       Integer i1 = Integer.valueOf(x);

       //jdk5自动装箱

       //先把int类型数据x包装成Integer对象,然后把对象的内存地址放到i2变量中

       //在底层其实就是执行Integer.valueOf(x)这句话

       Integer i2=x;

 

自动拆箱:可以直接把一个包装类型的数据赋值给自己对应的基本类型。

    //jdk5的自动拆箱

        intz=i.intValue();

       //根据i引用变量空间中的地址找到对应的基本数据类型,保存在y变量空间中

       int y=i;

 

基本数据类型-包装类-字符串   之间的转换

 

46 系统类(System)

System.out.println();

System.err.println();

区别:颜色.(不同时使用,出错)

System类中的常用方法:

System类中的常用方法:

1、

    

currentTimeMilllis()方法的作用:

1)获取当前系统时间的毫秒值。

2)在开发中,用来计算程序中功能的执行时间。

 

 

2、 System.exit(0);终止JVM运行  (开发中不建议使用);

3、重要

    

获取某个属性.

 

System类中换行方法:

在Java中的System类中提供了一个函数就是getProperty(String key) ,然后line.separator

 

47 Math类

Math.abs() 绝对值

Math.ceil() 向上取最近整数

Math.floor() 向下取最近整数

Math.random()  [0.0,1.0随机一个

Math.round() 四舍五入

说明:

1)Math类不能有子类;

2)Math类不能被创建对象;

Math类中常用的函数:

1)abs():返回一个数的绝对值;

2)ceil():返回比指定数大的最小整数,返回值类型是double;

3)floor():返回比指定数小的最大整数,返回值类型是double;

4)round():返回四舍五入的数,返回值类型是int;

5)random():生成大于等于 0.0 且小于 1.0 的随机 double类型的值

 

48 Random类

nextInt 生成随机数

nextInt( int   n) 生成0—n之间随机数包头不包尾

 

49 Date类(时间日期类

2017年10月07日

格式化:就是将看不懂的时间变为看得懂的时间 格式化(也就是日期 -> 文本)

Sat Oct 07 15:01:16 GMT+08:00 2017 -----》"2017年10月07日"

String format(Date date)

 

 

解析:看的懂的时间变为看不懂的 解析(文本-> 日期)

"2017年10月07日"----->Sat Oct 07 15:01:16GMT+08:00 2017

Date parse(String source)

 

Date d = new Date();

d//

 

毫秒值转换成Date对象d:::::::d.setTime(System.currentTimeMilllis());设置毫秒转成Date格式

第二种方式,构造方法:::::::Date(long  time)

Date对象d  转成毫秒;

long getTime()    获取当前系统毫秒值

System.currentTimeMilllis()

 

 

50 DateFormat类

时间的格式化和解析

抽象类,所以不能直接创建对象,所以调用自己静态方法来让外界访问

DateFormat df = DateFormat.getDateTimeInstance();

df.format(date);

String format(date)将Date转换成字符串

默认格式:2017-10-7 20:50:59     yyyy-MM-ddHH:mm:ss

 Date

parse(String source)
          从给定字符串的开始解析文本,以生成一个日期。

用给定的字符串转换成Date对象的格式,

但是字符串只能是yyyy-MM-ddHH:mm:ss格式

SimpleDateFormat类

构造方法

SimpleDateFormat(String pattern)
          用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat

SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMdd HHmmss");

        //创建系统日期对象

        Date date = newDate();

        //输出日期

        System.out.println(date);

        //将日期格式化为字符串

        StringnewDate = sdf.format(date);

        //输出格式化后的日期

        System.out.println(newDate);

按照指定格式生成日期

 

String  format(date)将Date转换成字符串

SimpleDateFormat构造给定格式

Date   parse(String)将符合格式的字符串转换成Date

 

 

51 Calendar类

也是抽象类,通过静态访问

说明:

1)Calendar类是一个抽象类,不能实例化对象。(需要通过方法获取Calendar对象)

2)Calendar类属于一个日历类,记录了一些生活中常用的日历字段,比如年、月、日、时、分、秒等一些日期与时间的相关信息。

   Calendar c = Calendar.getInstance();

      System.out.println(c);

运行结果:

注意:

1)在计算机中月份是从零开始计算的。也就是说数字0 表示1月,数字1表示2月,以此类推数字11表示12月。12表示下一年的1月;

  2)一周中周日是第一天;

  3)Calendar类中输出结果是一些key-value对应的信息。其实在Calendar对象内部维护了一个Map集合,把当前系统日期与时间上的所有信息全部使用key=value的形式保存在Calendar这个类中。

 

//创建日历类Calendar类的对象

        Calendarc = Calendar.getInstance();//使用静态方法获取日历对象

        //使用日历对象c调用get函数获得年份

        int year = c.get(Calendar.YEAR);//

        int month = c.get(Calendar.MONTH)+1;//月份0开始到11

        int day = c.get(Calendar.DAY_OF_MONTH);//一个月中的某一天

        System.out.println(year+""+month+""+day+"");

 

Calendar类的set()和add()函数;

 

说明:给当前Calendar对象中的某个key设置value值。

 

 

c.add(Calendar.MONTH, 1);//在当前月份上加1个月

        c.add(Calendar.DAY_OF_MONTH, -1);//在当前月的天数上减1

        //获取年月日

        int year=c.get(Calendar.YEAR);//

        int month=c.get(Calendar.MONTH)+1;//

        int day=c.get(Calendar.DAY_OF_MONTH);//

        //输出

        System.out.println(year+""+month+""+day+"");

           1)月份超出了范围,修改年;

  2)天数超出了范围,修改月;

      3)如果日历字段设置的值为负数:就在当前日历字段的基础上减;

      4)如果日历字段设置的值为正数:就在当前日历字段的基础上加;

 

 

52 Collection集合(单列集合)

集合属于容器,存储数据。

几种容器:

变量只能存储一个

数组可以存储多个数据,但是长度固定,数据类型单一

字符串缓冲区:长度可变,可以存储任意数据类型。致命缺点:不管存储什么数据类型最后都变为字符串。

集合:长度可变,可以存储任意引用数据类型,不能存储基本数据类型。存放到集合中属于什么数据类型

取出来还是那个数据类型。

 

Collection方法

添加

Collection coll=newArrayList();//这里发生多态了

       //使用coll对象调用add函数向集合中添加引用类型数据

       coll.add("aaaa");

 

coll.add(123);//这里相当于coll.add(Integer.valueOf(123));

       //BooleanvalueOf = Boolean.valueOf(true);

       coll.add(true);//这里相当于coll.add(Boolean.valueOf(true));

 

删除

       //使用集合对象coll调用remove删除函数

       boolean boo= coll.remove("aaa");

//     boolean boo1 = coll.remove("aaa");

//     boolean boo = coll.remove("xxx");//由于要删除的元素不在集合中,所以返回结果是false

 

判断

 

toArray() 遍历集合

 

遍历Object数组

 

 

53 迭代器(遍历器)

Iterator接口的迭代(取出、遍历)方式:

针对一个集合,需要遍历的时候,应该首先去判断集合中有没有元素(对象),有就取出这个元素,没有就不用再进行遍历了。

 

hasNext()函数表示判断容器中还有没有元素,如果有返回true,我们就可以根据这个返回的结果确定到底还要不要遍历这个集合容器

 

next()函数表示取出当前遍历到的那个元素。

       void  remove() 表示删除当前迭代器对象指向的集合中的元素。

 

注意:在使用集合对象生成迭代器对象后,那么此时这个迭代器对象已经记录下来此时集合中的结构,在使用迭代器遍历的时候,一定记住不能使用集合的对象来对集合中的元素进行删除或者添加,如果要改动可以使用迭代器对象改动集合,如果要改动集合中的内容可以根据改动后的集合对象再重新生成迭代器对象。

 

使用:

    //根据当前集合获取迭代器对象

       Iterator it = coll.iterator();

       //取出数据

       /*System.out.println(it.next());//it.next()表示获取迭代器对象指向集合中的数据

       System.out.println(it.next());

       System.out.println(it.next());

       System.out.println(it.next());*/

       //使用while循环遍历集合

       while(it.hasNext())//it.hasNext()表示循环条件,如果为true,说明集合中还有元素可以获取,否则没有元素

       {

           //获取元素并输出

           System.out.println(it.next());

       }

增强for循环(foreach)

       举例:

for(int x:arr)//这里的x表示数组的数据

{

    syso(x)

}

注意:增强for循环只能用来遍历数组或者集合

54 泛型<>

      

泛型介绍:格式:<标识符> 

注意:泛型的的标识符建议都大写 <IT> <E>

 

/*

 * 泛型注意:

 * 1.泛型不能是基本数据类型,必须是引用数据类型

 * 2.泛型不支持继承 ArrayList<Object> list=newArrayList<Integer>();

 */

 

       1.自定义泛型

public class Demo<IT>

{

 

}

                     newDemo<String>();

public class ArrayList<E>

       2.自定义泛型方法:

方法定义格式:

方法修饰符 <标识符> 方法返回值类型 方法名(参数列表)

{

       方法体

}

 

举例:

public  <IT> voidmethod(IT it)

{

    方法体

}

注意啦:<IT> 主要是定义泛型  参数列表中的IT表示使用定义的泛型

       3.自定义泛型接口

接口定义格式:

interface 接口名<标识符>

{

}

举例:

interface Inter<IT>

{

}

 

集合接口的泛型传递:

 

public interface Collection<E>

{

 

}

public interface List<E> extends Collection<E>

{

 

}

public class ArrayList<E> implements List<E>

{

 

}

通配符:<?>

通配符限定:

有两种:

上限限定: ? extends 父类

       举例: ?  extends Person ?可以是Person类本身及其子类,不能是及其他类

 

下限限定:? super 子类

       举例:? super Student ?可以是Student类本身及其父类,不能是兄弟及其他类

/*

     * ArrayList<Object> list=newArrayList<String>();

     * ArrayList<Object> list=newArrayList<Integer>();

     * 泛型通配符:使用 ?当传递的是list new ArrayList<String>();那么通配符>?表示String类型

     *                当传递的是list2new ArrayList<Integer>();那么通配符>?表示Integer类型

     *

     * ? extends Person 泛型上限限定,?只能接收Person及其子类,不能是其他的类

     */

    public static void printList(ArrayList<?extends Person> list) {

       //遍历集合

       for (Iterator<?>it = list.iterator();it.hasNext();) {

           Object objit.next();

           System.out.println(obj);

       }

    }

 

 

55 集合---List接口

List接口:

1)是Collection接口的子接口,继承了Collection接口中的所有方法

2)List接口定义的所有集合中的元素都可以重复,并且还可以保证存取的顺序一致(存储和取出的顺序一致的);

3)List接口下的所有集合全部拥有下标,List接口更像数组;

4)由于List接口规定自己的真实实现类(集合)都拥有下标,因此我们在操作List接口下的所有集合容器的时候,都可以通过下标操作;

5)因此在List接口中它不仅仅继承到Collection接口中的所有函数,同时java 还根据List的下标的特性,定义了适合List接口的特有函数;

 

LinkedList集合

       LinkedList集合它采用的是数据结构中的链表结构:

链表结构的特点:有头有尾。

链表结构:由一个链子把多个节点连接起来的数据结构。

节点:在链表结构中每个可以保存数据的空间称为节点,而一个链表结构是由多个节点组成的。

 

总结:

1)数组结构查询快,但是增删慢;

2)链表结构查询慢,但是增删快;

上述两种数据结构快慢只是相对来说。

 

LinkedList集合特点:

1、它的底层使用的链表结构;

2、有头有尾,其中的方法都是围绕头和尾设计的;

3、LinkedList集合可以根据头尾进行各种操作,但它的增删效率高,查询效率低;

LinkedList集合增删效率高是因为底层是链表结构,如果增加或者删除只需要在增加或者删除节点的位置上记住新的节点的地址即可,而其他节点不需要移动,所以速度会快。

而查询遍历由于链表结构的特点,查询只能从头一直遍历到链表的结尾,所以速度会慢。

4、LinkedList集合底层也是线程不安全。效率高;

5、也可以存储null元素;

 

由于LinkedList是链表结构,而链表有头有尾,所以在LinkedList集合中专门为链表结构提供了特有的函数。

 

 

队列和堆栈结构

队列结构:先进的先出或者后进的后出。(排队买票)

堆栈结构:先进的后出或者后进的先出。(手枪的弹夹)

模拟队列结构,先进先出,出去就不存在队列中

 


importjava.util.LinkedList;

/*

 * 模拟队列结构特点:先进先出,类似买票

 */

//创建模拟队列的类

classQueueDemo

{

    //创建LinkedList集合对象

    LinkedList list=newLinkedList();

    //定义函数模拟向队列中添加元素

    public void addElement(Object obj)

    {

       //每次都向集合最后面添加数据添加到链表的尾部

       list.addLast(obj);

    }

    //定义函数,让外界获取元素

    publicObject getElement()

    {

       /*

        * 由于队列的特点是获取一个元素便同时将获取的元素直接删除

        * 可以理解为一个人买票,买完票就不在队伍中了

        * 由于队列的特点,是先进先出,所以这里可以删除第一个元素,并返回删除的元素

        */

       returnlist.removeFirst();

    }

    //判断队列中是否还有元素存在

    public boolean isNull()

    {

       /*

        * LinkedList函数中虽然没有判断集合中是否还含有数据

        * 但是它的接口List中含有,所以我们可以使用list.isEmpty()来判断集合中是否还含有数据

        *isEmpty()函数是判断集合中没有元素返回true,有元素返回false

        */

       returnlist.isEmpty();

    }

}

public class LinkedListQueue {

    public static voidmain(String[] args) {

       //创建模拟队列类的对象

       QueueDemo q=newQueueDemo();

       //向队列中添加数据

       q.addElement("元素1");

       q.addElement("元素2");

       q.addElement("元素3");

       //判断集合中是否还含有元素,有,则输出数据

       while(!q.isNull())//!q.isNull()如果为true,表示集合中还有数据

       {

           //说明集合中还有元素,取出数据输出元素结果"元素1" "元素2" "元素3"

           System.out.println(q.getElement());

       }

    }

}

 

 

1)案例:使用LinkedList模拟堆栈结构。先进的后出,(手枪的弹夹)

 

代码和上述相同,只是将QueueDemo类中的getElement()函数体中的代码改成

return list.removeLast()即可

 

56 Set接口

不能保存重复的元素,没有下标,无序,

说明:

    1)Set接口中没有自己的特有函数,所有的函数全部来自于Collection接口。

HashSet

说明:

1)实现了Set接口,具备了Set集合的特性;

2)不保证集合中的迭代顺序(不保证元素存取一致),允许存储null元素;

3)底层使用哈希表结构;

 

HashSet 特点:

1.存储无序

2.没有下标

3.数据不可以重复

 

哈希表讲解:

 

如果保存自定义对象,需要注意复写Object类中的hashCode方法,如果需要对象属性不重复还需要重写equals方法,

所以如果需要完全不同的元素,最好定义自定义对象的时候直接快捷键复写toString,hashCode,equals三种方法

下面详细:

HashSet集合存储对象的时候:

1、HashSet集合的底层使用的哈希表结构。那么就要求存放的对象必须具备hashCode功能。由于任何一个类的父类都是Object类,而hashCode函数定义在了Object类中,因此所有的对象都具备hashCode功能。

2、如果我们要把一个对象可以正确的存放在HashSet集合中,这个对象所属的类一般都需要复写hashCode函数。建立本类自己的计算哈希值的方式。

3、如果在HashSet集合中要保证对象唯一,不能仅仅依靠hashCode函数,还要依赖于对象的equals函数,当hashCode函数计算出来的哈希值相同的时候,还要调用equals方法比较2个对象是否相同。

4、要求在向HashSet集合中存储自己定义一个类对象的时候,那么必须在这个自定义类中复写Object类中的hashCode和equals函数。

5、注意当向HashSet集合中存储数据的时候,对象一定会调用hashCode函数计算下标,但是不一定一定会调用equals函数,只有当计算的下标相同时

才会调用equals函数,否则不会调用equals函数来比较两个对象是否相等。

 

LinkedHashSet(了解)

LinkedHashSet 是Set集合下面唯一一个存储有序的集合。

因为在这个集合中有两个数据结构:哈希表和链接列表。

注意啦:哈希表是真正存储数据的数据结构,而链表只是记录着存储数据的顺序。

 

57 Collection总结

Collection:集合体系的顶层接口。

Collection集合(接口):

   |----List集合(接口):存取元素有序、可以存储重复元素、可以存储null、有角标,可以精确控制集合中的每一个元素。

       |-----ArrayList集合(类)

                                               1)实现了List接口;

      2)底层使用可变数组

                              3)方法都是围绕着角标操作的

                              4)查询遍历效率比较高,增删的效率比较低;

                              5)属于线程不安全的集合类;

 

       |-----LinkedList集合(类):

  1)实现了List接口;

                              2)底层使用链表结构

  3)方法都是围绕着头和尾来设计的;

                              3)查询遍历效率比较低,增删的效率比较高;

                              4)属于线程不安全的集合类;

    |-----Vector集合(类):底层可变数组,什么都慢,但线程安全,已经被ArrayList集合取代。

 

 

  |----Set集合(接口):存取元素无序(LinkedHashSet除外,因为底层有链表,存取有序)、不能存储重复元素、只能存储一个null、没有角标,只能通过迭代器遍历获取元素。该集合中的方法全部来自于Collection集合中。

       |-----HashSet集合(类):

      1)实现Set接口;

                              2)底层使用哈希表结构保证对象唯一依赖于对象的hashCode和 equals方法;

说明:使用对象的内容先调用hashCode ()函数生成哈希码值,然后结合数组长度计算数组下标,如果生成的下标对应的空间中

已经有数据,这时需要使用对象调用equals()函数来判断两个对象的内容是否相同,如果不相同,就会在当前空间在划出一个

空间来保存当前的对象。如果相同,直接舍去。

                              3)查询元素和添加不重复元素的效率比较快;

               |-----LinkedHashSet集合(类):

1)HashSet集合类的子类,存取元素有序,元素唯一,没有自己的特有方法;

                                            2)底层使用链表+哈希表结构;

                                                            补充:哈希表用来保存数据,保证数据唯一,不重复。链表用来记录数据的添加顺序,保证数据存取有序。

 

 

58 Map 集合(双列集合)

特点:

1)Map集合可以一次性存储两个对象;

2)在Map集合中保存的key和value这样的具备一定对应关系的一组(一对)数据,Map集合中存储的是两个对象的对应关系(映射关系)。[ key-value映射关系 ];

3)Map集合中的key必须保证唯一(存储的key元素不能重复,value可以重复,但是一个key只能对应一个value);

4)Map集合中的key和value属于一一对应关系(一个key只能对应一个value)

 

 

其实就是:

1.    储存两个对象.

2.    key(键)---value(值)-----一对,一一对应

3.    key唯一不可重复,value可重复,一个key只能对应一个value

 

Map和Collection的区别

区别:

       1)Map中键唯一,值没有要求。Collection中只有Set体系要求元素唯一;

       2)Map的数据结构针对键而言,Collection的数据结构针对元素而言;

3)Map是双列集合顶级接口,Collection是单列集合顶级接口,他们两个分别是两种集合的顶级接口,之间没有必然的联系;

 

Map集合中的方法

注意:由于Map是接口,不能创建对象,只能使用Map下面的子类HashMap创建对象。

 

/*

 * Map集合中的添加方法

 * V put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。

 * 注意:如果添加数据的时候,集合中没有与之对应的key,那么直接添加数据,并返回null

 * 注意:如果添加数据的时候,集合中有与之对应的key,那么put方法变为修改,根据key进行修改,使用新添加的

 * 值将原来的值进行覆盖,并返回原来旧的值

 * 

 * 注意啦:put方法除了具备添加功能,还有修改功能。

 */

/*

 * Map集合中的删除方法讲解

 * 1. void clear() 从此映射中移除所有映射关系(可选操作)。

 * 2V remove(Object key)根据键删除键值对整体,并返回对应的值,如果指定的键不存在,则返回null

 

 */

/*

 * Map集合中的判断方法讲解

 * boolean containsKey(Object key)

            如果此映射包含指定键的映射关系,则返回 true

    booleancontainsValue(Object value)

            如果此映射将一个或多个键映射到指定值,则返回 true

    boolean isEmpty()

            如果此映射未包含键-值映射关系,则返回 true

 */

/*

 * Map集合中的其他方法

 * Set<K> keySet()  获取Map集合中的所有的键并存放到set集合。

 * int size() 获取集合大小

 * Collection<V> values()  返回Map集合中的所有的值

         

 */

Map集合的遍历方法两种

第一种主要(竖向

public static void main(String[] args) {

       // 创建集合对象

       Map<String, String> m =new HashMap<String, String>();

       // 添加数据

       m.put("文章","马伊琍");

       m.put("邓超","孙俪");

       m.put("李晨","范冰冰");

       //使用Map集合的对象调用keySet方法获取Map集合中的键

       Set<String> keys = m.keySet();

       //迭代Set集合

       for (Iterator<String>it = keys.iterator();it.hasNext();) {

           String key = it.next();

           //调用get方法根据获取的键来获取值

           String value = m.get(key);

           System.out.println(key+"---"+value);

       }

    }

 

 

第二种需要了解会用(横向

public static void main(String[] args) {

       // 创建集合对象

       Map<String, String> m =new HashMap<String, String>();

       // 添加数据

       m.put("文章","马伊琍");

       m.put("邓超","孙俪");

       m.put("李晨","范冰冰");

       //获取键值对整体对象,称为结婚证 Set<Map.Entry<K,V>> entrySet() 

       Set<Map.Entry<String,String>> entrys = m.entrySet();//entry表示键值对整体对象

       //迭代Set集合

       for (Iterator<Map.Entry<String,String>>it = entrys.iterator();it.hasNext();) {

           Map.Entry<String,String> entry =it.next();

           //获取键

           String key = entry.getKey();

           //获取值

           String value = entry.getValue();

           System.out.println(key+"--"+value);

       }

    }

HashMap 集合

 

HashMap特点:

1)HashMap底层是哈希表;

2)键唯一,要保证键唯一,所以底层的哈希表主要作用在key上。存在HashMap的键位置的对象所属类必须复写hashCode和equals函数,而存在value位置的对象所属的类可以不复写hashCode和equals函数;

3)存取无序;

4)线程不安全,所以效率高;

补充:由于HashMap底层是哈希表,而HashMap集合上面的键又是保存在哈希表中的。所以根据哈希表的特点,保存在HashMap键的位置上数据都要复写hashCode()和equals()函数,这样才能保证key值唯一和存取无序。

LinkedHashMap集合

如果希望集合中的元素存取有序时,需要使用HashMap集合类下的子类:LinkedHashMap。底层是哈希表和链表,链表保证存取有序。

 

 

特点:

       1)存取有序;链表

       2)元素唯一;哈希表

59 可变参数

对一般方法的优化,参数列表数据类型一样

方法修饰符方法返回值类型方法名(数据类型变量名,数据类型变量名..)

{

}

参数列表格式:数据类型 ...变量名

/*

     * 可变参数其实底层就是一个数组

     * int ... num={1,2}--->int[]num={1,2}

     * int ... num={1,2,3}

     * int ... num={1,2,3,4}

     */

    public static int getSum(int ...num) {

       //定义变量保存和值

       int sum=0;

       // 遍历数组

       for (inti = 0; i < num.length; i++) {

           sum=sum+num[i];

       }

       returnsum;

    }

可变参数注意事项:

 * 1.如果使用可变参数时,有单独的数据处理,那么这个数据放到可变参数之前

 * 2.如果使用可变参数时,那么同一个类中就不能存在一模一样的函数(参数是数组)

 

public static int getSum(double x,String name,int ...num){

       System.out.println(x);

       System.out.println(name);

       // 定义变量

       int sum=0;

       for (int i = 0; i <num.length; i++) {

           sum=sum+num[i];

       }

       return sum;

传入数组也是一样,底层可变参数就是数组.

 

60 工具类

Collections工具类

       静态类名调用方法:

 * 1.static <T> booleanaddAll(Collection<? super T> c, T... elements)

 * 将所有指定元素添加到指定 collection中。

 * 2.static voidreverse(List<?> list)反转指定列表中元素的顺序。

 * 3.static voidshuffle(List<?> list)对集合的顺序进行打乱。这个方法一般使用在纸牌游戏。

 * 4.static void sort(List<T>list) 对集合进行排序

Arrays工具类

Arrays 方法:

 * static <T> List<T>asList(T... a) 将数组变为集合

    集合转数组toArray

 * 注意:

 * 1.如果将数组变为集合,使用asList方法的时候,建议不要定义基本数据类型的数组,应该定义对应的包装类类型

 * 2.由于数组长度是固定不变的,那么要求转化后的集合长度也不能改变,如果改变,那么会报UnsupportedOperationException异常

 * 里面数据的内容可以改变。

 

61 File类

  File类:描述文件或文件夹,

File类构造方法

File类构造函数介绍:

 * 1.File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File实例。

 * 注意:对于参数pathname所表示的路径是否存在,这个构造函数不会判断

 

 * 2.File(File parent, Stringchild)  根据 parent 抽象路径名和 child路径名字符串创建一个新 File实例。

 

 * 3.File(String parent, Stringchild)根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

 * 举例:D:\\abc\\1.txt

 * 参数:parent表示父目录 D:\\abc

 * child 表示子目录 1.txt

优先级1---3----2

 

File类获取方法

获取:

 * String getAbsolutePath()  返回此抽象路径名的绝对路径名字符串。

 * 绝对路径:带盘符 D:\\abc\\1.txt

 * 相对路径:1.txt

 *

 * String getName() 返回由此抽象路径名表示的文件或目录的名称。返回最后一级名字

 * String getPath()  将此抽象路径名转换为一个路径名字符串。

 * long length()  返回由此抽象路径名表示的文件的长度。获取文件或者文件夹大小,以字节为单位。

 

File类创建文件方法

创建文件讲解:

 * boolean createNewFile() 如果创建成功,那么返回true,失败,false

 * 注意:

 * 1.如果指定的路径文件不存在,则创建成功,如果指定路径的文件存在,则创建失败

 * 2.如果创建文件指定的路径不存在,那么会报异常:java.io.IOException:系统找不到指定的路径。所以要求指定的路径必须存在。

File类创建文件夹方法

创建文件夹讲解:

 * boolean mkdir()

          创建此抽象路径名指定的目录。

    booleanmkdirs()

          创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

          

         

          注意:

          1.对于mkdir方法来说,如果指定整体路径不存在,那么不会报异常,会返回false,创建文件夹失败

          2.对于mkdirs()方法既可以创建单级目录又可以创建多级目录,开发中使用它较多

         

   删除方法: boolean delete() 删除指定路径,但是注意此删除不走回收站.如果指定文件夹下面含有其他的文件或者文件夹,那么不会删除。

File类判断方法

File类中的判断方法讲解:

 * boolean isDirectory()  判断指定的路径是否是文件夹,如果是文件夹,返回true,否则返回false

 * boolean isFile()  判断指定的路径是否是文件,如果是文件,返回true,否则返回false

 * boolean exists()  判断指定路径是否存在,存在返回true,否则false

 * boolean isHidden() 测试此抽象路径名指定的文件是否是一个隐藏文件。


 

File类列举方法

File类中的列举方法:

 * String[] list() 返回一个字符串数组,

 * 注意:

 * 1.这个方法获取的是指定路径下的子文件或者子文件夹的相对路径举例:1.jpg 1.txt

 * 2.如果指定路径存在,但是下面没有任何子文件或者子文件夹,那么返回的数组中没有任何内容

 * 3.如果指定路径是文件不是文件夹或者指定路径不存在,那么list()方法会返回null

File[]

listFiles()
          返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件

 

文件过滤器

FileFilter:它也是一个过滤器,专门用来过滤文件或文件夹的。

 

File类中的函数:

File[] listFiles(FileFilter filter) 返回符合过滤器条件的所有儿子的File数组

 

FileFilter过滤器中的accept方法中的pathname是当前需要过滤的那个文件或文件夹对象。

或者可以这么理解pathname:就是某个儿子的File对象。

 

自定义过滤器类

 * File[] listFiles(FileFilterfilter)

 * 使用过滤器步骤:

 * 1.定义一个实现类实现FileFilter接口,这个类就是过滤器类

 * 2.实现类要求必须实现accept(File pathname)方法,然后在这个方法中书写满足过滤器条件的代码

 * 3.只要这个方法给底层返回true,那么说明满足过滤器条件,则会将满足的内容添加到File类型的数组中

源码图解:

62 递归

Java中的递归:

    在方法的函数体中又调用了方法自己本身。

递归调用的细节:必须要求递归中有可以让函数调用的结束条件。否则函数一直调用,就会导致内存溢出。

 

public void show()

{

       show();

}

 

需求:扫描D:\\test所有子文件夹及子子文件夹下的.jpg文件,输出其绝对路径。

 * 步骤:

 * 1.创建File类的对象,D:\\test作为父目录

 * 2.调用自定义方法,上述对象作为参数

 * 3.在自定义方法中获取到对象之后,使用对象调用File类中的listFiles()方法,获取所有的儿子存放到File类的数组中

 * 4.遍历数组,依次取出数组中的每个儿子,判断每个儿子是否是文件夹

 *     是文件夹   :以这个儿子的文件夹作为父目录,继续回到第2步调用自定义方法

 *     不是文件夹:说明是文件,判断该文件的后缀名是否是.jpg

 *                   是:输出其绝对路径。

 */

public class ScanFilesAndFolders{

 

    public staticvoid main(String[] args) {

        //1.创建File类的对象,D:\\test作为父目录

        File f = newFile("D:\\test");

        //2.调用自定义方法,上述对象作为参数

        scanFilesAndFolders(f);

    }

 

    public staticvoid scanFilesAndFolders(Filef) {

        //3.在自定义方法中获取到对象之后,使用对象调用File类中的listFiles()方法,获取所有的儿子存放到File类的数组中

        File[]arr = f.listFiles();

        //4.遍历数组,依次取出数组中的每个儿子,判断每个儿子是否是文件夹

        for (File f2: arr)//f2表示父目录下的每一个儿子

        {

            //判断每个儿子f2是否是文件夹

            if(f2.isDirectory())

            {

                //是文件夹   :以这个儿子的文件夹作为父目录,继续回到第2步调用自定义方法

                scanFilesAndFolders(f2);//此时f2作为参数

            }else

            {

                //不是文件夹:说明是文件,判断该文件的后缀名是否是.jpg

                //f2 表示 D:\test\3.jpg

                //判断该文件的后缀名是否是.jpg

                if(f2.getName().endsWith(".jpg"))

                {

                    //后缀名是.jpg输出其绝对路径。

                    System.out.println(f2.getAbsolutePath());

                }

            }

        }

    }

 

63 IO流

 

IO流:读写文件中的数据。

字符流自带缓冲区 FileWriter  BufferedWriter newLine()

注意啦:

1.字节流不自带缓冲区

字节输出流

创建对象:构造函数:

 * FileOutputStream(String name) 参数:name表示具体的文件名 使用多

 * FileOutputStream(File file) 参数:file表示具体的文件名,只是属于File类型

 *

 * 调用方法,向指定文件中写数据:

 * void write(byte[] b) 向指定文件中写字节数组数据,参数 b表示字节数组名

 * 

 * 注意:构造函数FileOutputStream(String name)做了哪些事情:

 * 1.如果文件不存在,构造函数会自动帮我们创建文件

 * 2.如果指定路径不存在,则会报异常:java.io.FileNotFoundException:D:\test1ajahahahahha\1.txt (系统找不到指定的路径。)

 * 3.如果指定的路径是文件夹,则会报异常:java.io.FileNotFoundException:D:\test1\haha (拒绝访问。)

 * 原因:因为文件夹是用来存储文件的额,而文件是用来存储数据的,如果想把数据写到持久设备上,那么关联的必须是文件,不能是文件夹

 * 4.如果指定文件已经存在,会将原来的数据进行覆盖掉

 

* 使用String类中的getBytes()方法可以将一个字符串转换为字节数组

 * 注意:

 * 如果一个流关闭了,在重新写数据的时候,那么后写的数据会将关闭之前写的数据进行覆盖。

 * 但是如果使用一个流多次写数据(流没有关闭),那么这些数据会全部写到文件中,不会覆盖。

 

追加数据,

使用构造函数:

 * FileOutputStream(String name,boolean append)

 * 参数:name表示文件名 append如果为true,表示追加原来数据的后面,如果为false,则会将原来的数据进行覆盖。

//换行,必须获取当前系统的行分隔符

        String line_separator = System.getProperty("line.separator");

        //调用方法写数据

        fos.write((line_separator+"你好吗").getBytes());

 

字节输入流

构造函数:

 * FileInputStream(String name) 参数表示要读取的文件名

int read() 一次读取一个字节数据。存放到返回值,直到读取到文件末尾返回-1,结束。

int read(byte[] b) 一次读取多个字节数据,并将多个字节数据存放到参数的字节数组b中。

所以我们必须定义一个空的byte数组,这个数组大小是1024的整数倍。

返回值 int 表示每次读取的字节个数。注意这个返回值不是上述定义的字节数组长度。

读取到文件末尾返回-1

   

 * 函数:一次读取一个字节数据

 * int read() 读取到文件末尾返回-1

* 注意:

 * 1.如果指定的文件不存在,则会报异常:java.io.FileNotFoundException:D:\test1\111.txt (系统找不到指定的文件。)

    2.

    3.

//读取数据模板

        int b=0;//保存每次读取的数据

        while((b=fis.read())!=-1)

        {

            System.out.println((char)b);

        }

        //关闭资源

        fis.close();

 

//定义一个空的字节数组

        byte[] buf=new byte[1024];

        //定义变量保存每次读取的字节个数

        int len=0;

        //循环

        while((len=fis.read(buf))!=-1)

        {

            //输出 String(byte[] bytes, int offset, int length)

            System.out.println(newString(buf,0,len));

        }

        //关闭资源

        fis.close();

 

 

字节流缓冲区

字节流缓冲区:作用:提高效率,只是临时存储数据。并且缓冲区流没有读写能力。

注意啦:在IO流中只有字节流具备读写能力。

关于字节流缓冲区你呀,了解就行。

字节输出流缓冲区:

 * BufferedOutputStream

 * 构造函数:

 * BufferedOutputStream(OutputStreamout)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

 * 方法:

 * 写数据:

 * void write(byte[] b, intoff, int len)

 

使用字节输入流缓冲区读取数据:

 * 类:

 * BufferedInputStream

 * 构造函数:BufferedInputStream(InputStreamin) 创建一个 BufferedInputStream并保存其参数,即输入流 in,以便将来使用。

 * 函数:int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中。

 

64 编码表

 

什么是编码表?

编码表其实就是一个字典。编码表就是我们人类所熟知的内容和计算机所熟知的内容之间进行转换。

   编码值

A  65   01000001

不同国家编码表都不同:

ASCII :美国  所有内容只占一个字节 11101011

ISO-8859-1 : 欧洲Latin- 1 所有内容只占一个字节

GBK: 中文两个字节

Unicode

UTF-8 : 美国 1个字节,欧洲2个字节,中文3个字节

二进制:

89

1            1            1            1            1            1            1            1

128    64      32      16          8            4       2      1

0      1       1       0      1       0       0      1

 

65 转换流

InputStreamReader 硬盘---》内存 字节数据----》字符数据 

字节转字符输入转换流

65----》A

他与FileReader的唯一区别是:这个转换流可以指定任意编码表来读取数据。

构造函数:

InputStreamReader(InputStream in, StringcharsetName) 创建使用指定字符集的InputStreamReader。

参数:in 用来读取硬盘文件数据的字节流  charsetName 表示指定的编码表

 

字符转字节输出转换流:内存----》硬盘 字符----》字节

A----》65

OutputStreamWriter

构造函数:

OutputStreamWriter(OutputStream out, StringcharsetName) 创建使用指定字符集的OutputStreamWriter。

参数 out 表示关联目的地文件的字节输出流对象  charsetName 表示指定的编码表

 

66 键盘录入

键盘录入介绍:

InputStream is=System.in;

Scanner(InputStream source)

Scanner sc=new Scanner(is);

sc.nextLine();

换行:Stringproperty= System.lineSeparator();

//键盘录入一次读取一行数据

    public static void method_2() throwsIOException {

        //通过System类获取到输入流

        //InputStream is = System.in;

        /*

         * 由于我们想一次性读取一行数据,所以可以考虑使用readLine()函数

         * 但是这个函数属于字符输入流缓冲区BufferedReader类中的函数,

         * 而我们这里获取的是字节流,所以我们需要将字节数据先转换成字符数据

         * 然后再将获得的字符数据转换为字符流缓冲区

         */

        //将字节流变成字符流

        //InputStreamReader isr = new InputStreamReader(is);

        //将字符流转成字符流缓冲区

        //BufferedReaderbr = new BufferedReader(isr);

         BufferedReader br = newBufferedReader(new InputStreamReader(System.in));

        System.out.println("请输入数据:");

        //按照行读取数据

        Stringline=null;//"null"

        //使用循环键盘录入数据的时候,是无法停止循环的,需要我们在程序中手动的结束条件

        while((line=br.readLine())!=null)

        {

            //键盘录入是不会出现null的,所以循环不会停止

            //我们需要约束一个结束循环的条件

            System.out.println(line);

            if("over".equals(line))

            {

                break;

            }

        }

    }

JDK5之后可以使用Scanner代替上面的录入:

       Scannersc = new Scanner( System.in );

       在Scanner类中提供可以录入不同类型的数据。

 

67 Properties类(写入持久设备的Map集合)

Properties 属于双列集合。

Properties 集合一般用来操作配置文件。.txt .ini .xml 等

在配置文件中#表示注释的意思

* 使用Properties类中的特有的函数存储数据并遍历添加数据的方法:

Object setProperty(String key,String value)向集合添加数据,相当于之前的put方法

* 根据键获取对应的值: String getProperty(String key)用指定的键在此属性列表中搜索属性。相当于之前的get(key)

* 获取所有的键方法: Set<String>stringPropertyNames()返回此属性列表中的键集。相当于之前的keySet方法

 

将数据持久保存到硬盘上:写入用字节读取就字节

 * void store(OutputStream out, String comments)

    voidstore(Writer writer, String comments)

    向指定硬盘文件中写入集合中的key-value数据

    参数:第一个参数用来关联目的地文件 第二个参数:comments属性列表的描述。

   

 将之前持久到硬盘上的数据读取到内存中的方法:

    voidload(InputStream inStream)   从输入流中读取属性列表(键和元素对)。

void load(Reader reader) 从输入流中读取属性列表(键和元素对)。

FileReaderfr = new FileReader("person.ini");

      p.load(fr);

FileWriterfw = new FileWriter("person.ini");

      p.store(fw,"person");

68 序列化流和反序列化流

1.类实现Serializable接口

2.显示声明版本号

可以保存对象,保存Object

序列化流:输出到硬盘字节ObjectOutputStream      writeObject()

当对创建的对象进行序列化操作时,必须保证对象所属的类要实现序列化接口Serializable

 

反序列化流:输入到内存字符 ObjectInputStream  readObject()

 

序列化实现类需要实现接口Serializable

同时会给实现类一个序列版本号,声明版本号保证修改类的内容序列号不会改变,这样反序列化时版本号还是一致,不会报错.

 

//transient表示瞬态,是一种修饰符。他修饰的内容的值不能被序列化到硬盘上

   public transient String name;

69 打印流

System.out.println()

PrintStream打印字节流

 

静态System.out 系统输出.返回值类型PrintStream  

PrintStream(OutputStream out)
          创建新的打印流。直接调用其中方法println.自动刷新

注意:

PrintWriter 打印字符流

自带缓冲区,但是他不具备自动刷新功能,需要启动自动刷新。

 * 如何启动呢?

 * 通过构造函数:

 * PrintWriter(Writer out, booleanautoFlush)创建新 PrintWriter

 * autoFlush true表示已经启动自动刷新功能

自动刷新需要使用printlnprintfformat 方法自动刷新

构造函数:

 * PrintWriter(OutputStream out) 根据现有的 OutputStream创建不带自动行刷新的新 PrintWriter

 

70 第三方包

导入:

对项目右键→New→Folder→name lib

把解压的jar包赋值粘贴到lib文件夹下.

右键jar→Build Path→Add to Build Path

commons-io

FileUtils类

l  常用方法:

1)copyFile(File srcFile, File destFile):文件复制

            2)copyDirectoryToDirectory(FilesrcDir,File destDir);文件夹复制

      3)readFileToString(File file):读取文件内容,并返回一个String;

4)writeStringToFile(Filefile,String content):将内容content写入到file中;

 

71 多线程

进程:正在进行的程序。就是正在运行的软件。

多进程:就是一台电脑同时运行多个程序。

多进程好处:高效。

线程:就是进程中的每一个小的任务。每个线程之间都是独立运行的,互不干扰

多线程:一个进程中有多个任务在执行,比如360软件,那么里面的木马查杀 体检

多线程好处:高效。合理使用了CPU的资源。

线程是不是越多越好呢?

不是。cpu过载

线程调度:

1.分时调度:就是每个线程分配的CPU执行时间是一样的。

2.抢占式调度:哪个线程的优先级高,就先执行谁。

 

JVM运行时,是单线程还是多线程?

多线程:main函数--》主线程。gc垃圾回收。

并发:就是某一时间。并发访问量。

并行:就是某一时

实现多线程

方法一(了解)

步骤:

 * 1.自定义类继承Thread

 * 2.重写Thread类中的run方法   run  Alt+/ 选择Thread类的重写

 * 3.创建自定义类的对象

 * 4.调用Thread类中的start方法启动线程

如何获取线程名字?

 * 肯定使用Thread类中的方法: String getName()返回该线程的名称。

 * 由于getName属于非静态方法,所以需要使用线程类的对象调用,所以我们还必须的获取当前线程类的对象

 * 如何获取当前线程的对象?

 * 使用Thread类中的静态方法:static Thread currentThread()返回对当前正在执行的线程对象的引用。

 *

 * 注意:

 * 1.主线程名字是 main

 * 2.其他线程默认名字是:Thread-x x0开始依次递增

 * 

 * 设置线程名字: void setName(String name)改变线程名称,使之与参数 name相同。

 * 参数:name表示设置的新的线程的名字

自定义类对象,setname设置名字

Thread. currentThread().getname  获取名字

 

方法二 实现Runnable(掌握)

1.自定义一个类实现Runnable接口 Runnable 接口叫做任务接口 实现类叫做任务类

2.重写 Runnable 接口中的run方法,书写任务

3.创建任务类对象

4.创建Thread类的对象, Thread(Runnable target)  任务对象作为参数传递

                     Thread(Runnable target, String name) 分配新的 Thread 对象。 name表示现成的名字

5.使用线程类对象调用Thread类中的start方法启动线程

好处,

避免了单继承的问题

线程代码与任务代码分离,解耦合,扩展性好

线程休眠(sleep)

static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),

1000毫秒=1

Alt+Shift+Z抓异常

多线程匿名内部类用法

l  使用匿名内部类的方式实现Runnable接口,重新复写Runnable接口中的run方法。

 

public static voidmain(String[] args) {

        //使用匿名内部类实现多线程 r表示任务类的对象

        Runnabler=new Runnable(){

            public void run() {

                for (inti = 0; i < 10;i++) {

                    System.out.println(Thread.currentThread().getName()+"---"+i);

                }

            }

        };

        //创建线程类对象

        Threadt1=new Thread(r,"t1");

        Threadt2=new Thread(r,"t2");

        //启动线程

        t1.start();

        t2.start();

}

多线程的运行状态图

72 多线程的安全问题

卖票案例(同步)

操作同一资源会产生安全问题

要解决安全问题:

    可以人为的控制CPU在执行某个线程操作共享数据的时候,不让其他线程进入到操作共享数据的代码中去,这样就可以保证安全。

    上述的这个解决方案:称为线程的同步。

同步:就是CPU在使用某个线程操作共享资源时,不让其他线程操作。

同步使用关键字: synchronized

同步有三种:

第一种同步代码块

1) 加同步格式:

Object obj = new Object;                                obj

    synchronized(需要一个任意的对象(锁))锁唯一

   {

代码块中放操作共享数据的代码。

}

说明:

1)上述的格式称为多线程中的同步代码块。

2)同步代码块上的锁,可以是随便任意的一个对象。但是必须是唯一的。

    问题1:对象是什么?

       不确定,所以随便给一个。

    问题2:哪些代码需要被同步?

       操作共享数据的代码。

 

第二种非静态同步方法

将第一种同步代码块当中的代码抽取成方法

锁:this

格式: synchronized 属于修饰符

public synchronized void show()

{

 

} A:如果一个方法内部,所有代码都需要被同步,那么就用同步方法;

B:同步方法的锁是this

第三种静态同步方法

第二种加静态

锁 类名.class

格式: synchronized 属于修饰符

public static synchronized void show()

{

 

}     

静态同步方法的锁是:当前类的字节码文件对象(Class对象)。

 

总结:

       同步代码块:锁是任意对象,但是必须唯一;

       非静态同步方法:锁是this

       静态同步方法:锁是当前类的字节码文件对象;类名.class

死锁问题

死锁:是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待的现象。

死锁在开发中,也会遇到,当线程进入到死锁状态时,程序中线程就会一直处于等待状态。

 

 

解决办法:

  可以使用一个同步代码块解决的问题,不要使用嵌套的同步代码块,如果要使用嵌套的同步代码块,就要保证同步代码块的上的对象锁使用同一个对象锁(唯一的对象锁)

 

73 JDK1.5之后同步解决

属于接口不能创建对象所以我们可以使用它的子类ReentrantLock来创建对象并使用Lock接口中的函数。

 

Lock l=new ReentrantLock();

l.lock()获取锁

l.unlock()释放锁

该解决方案与synchronized都可以.

 

74 网络编程基础

网络三要素

1.IP:通过IP找计算机设备,而在网络中IP是唯一标识

IP分两种:

 

IPv4 地址 :192.168.37.155

4*8=32

 192.    168.      37.       155

 11000000 10101000  00100101 10011011

 点分十进制法:

 

 

本地链接 IPv6 地址:fe80:0:0:0:c8d3:7ca7:8123:5f3c%12

8*16=128

零式压缩法:FF01:0:0:0:0:0:0:1101 → FF01::1101

 

特殊IP:

本机IP 127.0.0.1

 

 

2.端口号:就是找计算机中的具体哪个进程,一台计算机中的进程端口号是唯一的。

端口号范围 0-65535 2个字节16位2进制

3.网络协议:就是一种规范。 UDP TCP http

UDP: User Datagram Protocol 用户数据报包协议

特点:

1.一般使用在聊天工具,传输数据较小,最大64K

2.发送端发送数据的时候,接收端不一定在

3.效率高,但是不安全

4.把数据封装成数据报包;

TCP:TransmissionControl Protocol 传输控制协议

特点:

1.可以传输数据较大的数据,比如文件上传 大小没有限制

2.这个协议要求客户端发送数据的时候,必须有服务端,必须先建立连接通道,所有数据向通道中写

3.安全,但是效率低

4.满足三次握手协议

InetAddress

InetAddress类介绍

 * 获取对象方法:

 * 1)staticInetAddress getByName(String host)在给定主机名的情况下确定主机的 IP地址。 host 表示主机名也可以是IP或者域名

 * 2)static InetAddress[] getAllByName(String host)在给定主机名的情况下,根据系统上配置的名称服务返回其 IP地址所组成的数组。

 * 调用非静态方法获取具体的IP和主机名:

 * 1) String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。

 * 2)String getHostName() 获取此 IP地址的主机名。

 

UDP协议

UDP编程:使用DatagramSocket 类 套接字

一、发送端:

       构造函数:  DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可用的端口。

       调用方法:

       发送数据方法:

              voidsend(DatagramPacket p) 从此套接字发送数据报包。

 

       将发送的数据进行打包: DatagramPacket  数据报包类

              打包的构造函数:

                     DatagramPacket(byte[] buf, int length,InetAddress address, int port)

                     构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。

                     参数:

                     buf:表示发送的数据

                     length数组长度

                     address接收端IP地址

                     port接收端的具体端口号

DatagramSocket ds= new DatagramSocket();

        byte[] buf= "Hello World".getBytes();

        InetAddressaddress = InetAddress.getByName("目标IP");

        DatagramPacketp = newDatagramPacket(buf,buf.length,address,目标端口);

        ds.send(p);

        ds.close();

 

二、接收端:

       构造函数:  DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口。

       调用方法:

       接收数据方法:

               void receive(DatagramPacket p) 从此套接字接收数据报包。

              拆包构造函数:    DatagramPacket(byte[] buf,int length)

                            构造 DatagramPacket,用来接收长度为 length 的数据包。

                     参数:

                     buf表示接收的数据

                     length表示接收到字节个数

              取出数据报包中的数据:

              使用DatagramPacket类中的非静态方法:

                     1.   InetAddress getAddress() 获取发送端IP

                     2.   byte[] getData() 获取发送端发送过来的数据

                     3.   int getLength() 返回将要发送或接收到的数据的长度。

                     4.    int getPort()  获取发送端端口号

lic staticvoid main(String[] args)throws Exception {

        DatagramSocketds = newDatagramSocket(接收端口);

        byte[] buf= new byte[1024];

        DatagramPacketp = newDatagramPacket(buf,buf.length);

        ds.receive(p);

        InetAddressia = p.getAddress();

        Stringip = ia.getHostAddress();

        byte[] data= p.getData();

        int len = p.getLength();

        int port = p.getPort();

        System.out.println(ip+"--"+newString(data,0,len)+"--"+len+"--"+port);

        ds.close();

TCP协议

客户端套接字类Socket

服务端套接字类ServerSocket

一、客户端:

TCP必须有两个 Socket

客户端套接字: Socket

       构造函数:  Socket(String host, intport) 创建一个流套接字并将其连接到指定主机上的指定端口号。

              参数:host 表示服务端的ip地址  port 表示服务端的端口号

               Socket(InetAddress address, int port)  创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

       方法:

              获取向通道中写数据的字节输出流函数:

               OutputStream getOutputStream()  返回此套接字的输出流。

//A:创建客户端套接字对象;Socket(Stringhost, int port)

        Sockets = new Socket("127.0.0.1",9999);

        //B:获取输出流,关联通道; OutputStreamgetOutputStream()

        OutputStreamos = s.getOutputStream();

        //C:写数据; 目的地是通道

        os.write("hello,TCP我又来了".getBytes());

        //D:释放资源;

        s.close();

 

服务端套接字: ServerSocket

              构造方法:ServerSocket(int port) 创建绑定到特定端口的服务器套接字。

 

       方法:

              1、 Socket accept() 侦听并接受到此套接字的连接。

                     就是获取访问服务端的具体哪个套接字的。

              2、  InputStream getInputStream()返回此套接字的输入流。

              使用侦听到的客户端套接字对象调用getInputStream()方法获取字节输入流对象

// 1.创建服务端套接字对象ServerSocket(int port)

        ServerSocket ss = new ServerSocket(9999);

        // 2.调用非静态方法accept() 侦听并获取客户端套接字对象

        Socket s = ss.accept();

        // 3.使用客户端套接字对象调用getInputStream()方法获取字节输入流

        InputStream is = s.getInputStream();

        //4.读取数据,数据源是通道

        byte[] buf=new byte[1024];

        int len=0;

        while((len=is.read(buf))!=-1)

        {

            //输出控制台

            System.out.println(newString(buf,0,len));

        }

        //5.关闭资源

        ss.close();

        s.close();

TCP协议上传文件响应

客户端上传

        //1.创建字符输入流缓冲区对象关联数据源文件bw.txt

        BufferedReader br = new BufferedReader(newFileReader("bw.txt"));

        //2.创建客户端套接字Socket对象 Socket(Stringhost, int port)

        Socket s = new Socket("127.0.0.1",6666);

        //3.使用客户端套接字对象调用getOutputStream()方法获取字节输出流对象,目的地是通道

        OutputStream os = s.getOutputStream();

        //4.创建字符输出流缓冲区对象,上述的字节输出流作为参数

        BufferedWriter bw = new BufferedWriter(newOutputStreamWriter(os));

        //5.读写数据

        String line=null;

        while((line=br.readLine())!=null)

        {

            //向通道中写数据

            bw.write(line);

            bw.newLine();

            bw.flush();

        }

       

        //告诉服务端客户端已经上传结束

        //向通道中写结束标记 void shutdownOutput() 禁用此套接字的输出流。

        s.shutdownOutput();

        //从通道中读取服务端的反馈信息

        //获取字节输入流对象

        InputStream is = s.getInputStream();

        byte[] buf=new byte[1024];

        int len=is.read(buf);

        //将反馈信息输出到客户端的控制台

        System.out.println(newString(buf,0,len));

        //6.关闭资源

        br.close();

        s.close();

服务端

// 1.创建服务端套接字对象 ServerSocket(int port)

        ServerSocket ss = new ServerSocket(6666);

        // 2.侦听并获取客户端套接字对象 accept()

        Socket s = ss.accept();

        // 3.使用客户端套接字对象调用getInputStream()方法获取字节输入流对象,数据源是通道

        InputStream is = s.getInputStream();

        // 4.将上述字节流转换为字符输入流缓冲区对象

        BufferedReader br = new BufferedReader(newInputStreamReader(is));

        // 5.创建字符输出流缓冲区对象关联目的地文件copy.txt

        BufferedWriter bw = new BufferedWriter(newFileWriter("copy.txt"));

        // 6.读写数据

        String line=null;

        while((line=br.readLine())!=null)

        {

            //结束循环

            /*if("over".equals(line))

            {

                break;

            }*/

            //向服务器中写数据

            bw.write(line);

            bw.newLine();

            bw.flush();

        }

        System.out.println(s.getInetAddress().getHostAddress());

        //向客户端写反馈信息

        //获取向通道中写数据的字节输出流对象,目的地是通道

        OutputStream os = s.getOutputStream();

        //写数据

        os.write("亲,恭喜您,种子上传成功,可以继续上传。。。".getBytes());

        // 7.关闭资源

        ss.close();

        s.close();

        bw.close();

 

75 反射

就是用来操作字节码文件的 .class  成员变量 成员方法 构造方法

获取Class对象  Class类

三种方法:

一.   类名.class

需要知道类名.不常用 没有对类进行初始化

二.   对象.getClass()   Object类中的方法

不常用. 效率低

三.   Class类中的静态方法 .forName(“类全名即:包名.类名”);  对类进行初始化了常用效率高,只需要类全名

Class<?> clazz= Class.forName("java.lang.String");

System.out.println(clazz.getName());//java.lang.String

System.out.println(clazz.getSimpleName());//String

Class类中的非静态方法:

 * String getSimpleName()  只获取类名 String

 * String getName()   获取包名.类名类全名 java.lang.String

 

九种预定义对象

八种基本数据类型+void

不属于任何包.Class对象就是本身

数组类名 [I

clazz3.isArray() 判断当前类Class类的对象是否是数组,返回true,是数组,false不是数组

反射获取一个类中的构造方法

三步,

先获取对应的Class对象

一获取对象

Class<?> clazz = Class.forName("java.io.File");

获取其中的构造方法,

Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes)获取某个类中的指定的构造函数包括私有的

 * Constructor<?>[] getDeclaredConstructors()  获取某个类中的所有的构造函数包括私有的

!!!

如果有无参构造

clazz.newInstance();直接创建对象

使用Constructor类中的 T newInstance(Object...initargs)   方法创建具体类的对象

 * 参数:initargs表示要调用的构造函数的实际参数

Constructor<?> c =clazz.getDeclaredConstructor(String.class,File.class);

//取消权限检测机制或者暴力访问

       c.setAccessible(true);解除权限检测可以访问私有

       //使用c对象调用Constructor类中的方法创建File类的对象 T newInstance(Object... initargs)

三创建对象传入参数

       File f = (File) c.newInstance("柳岩.jpg",new File("D:\\test"));

 

反射获取一个类中的成员变量

Field getDeclaredField(String name) 获取某个类中的指定成员变量包括私有的

 *   Field[] getDeclaredFields() 获取某个类中的所有成员变量包括私有的

Field类中的方法

void set(Object obj, Objectvalue)将指定对象变量上此 Field对象表示的字段设置为指定的新值。

 * 参数:

 * obj 表示获取类的哪个对象

 * value 赋的新值

 * Object get(Object obj)返回指定对象上此 Field表示的字段的值。

 * 参数:

 * obj 表示对象补充:就是获取值所属的对象

 

反射获取一个类中的成员方法

Method getMethod(String name, Class<?>... parameterTypes)获取某个类中的指定的公共成员方法

 * 参数:

 * name 表示方法名字

怎么执行?

 * 使用Method类中的方法:

 *  Object invoke(Object obj, Object...args) 执行方法

 *  参数:

 *  obj  : 调用函数执行的具体的对象

 *  args :表示调用具体方法的实际参数

 *  

 *  如果执行的方法没有返回值,则返回null,如果有返回值,就返回具体的内容

 * parameterTypes 表示参数列表,属于Class类型

 * Method[] getMethods() 获取某个类中的所有公共成员方法,以及父类中的公共成员方法

 

Method getDeclaredMethod(String name, Class<?>... parameterTypes)获取某个类中的指定的方法,包括私有的

 参数:

 name 方法名

 parameterTypes 方法的参数列表,属于Class类型

 Method[] getDeclaredMethods() 获取某个类中的所有方法,包括私有的,但是不包括父类的

 

静态方法的Object invoke(Object obj, Object... args)对象参数为null

 

76 类加载器

类加载器:就是将硬盘上的.class文件加载到内存中。

 

 

BootStrap 顶层根类加载器 加载API中定义好的类(一段C++代码)

       ↑

ExtClassLoader 扩展类加载器   

AppClassLoader 应用类加载器 

 

ClassLoader getClassLoader() 返回该类的类加载器

ClassLoader loader =clazz.getClassLoader();

   ClassLoaderparent =loader.getParent();

委托机制

保证一个类的.class在方法区只有一份

全盘负责: 当一个ClassLoader(类加载器)加载一个类的时候,那么在这个类中所引用的所有其它的类通常也都由这个类加载器来加载。

委托机制:先让Parent(父)类加载器寻找,只有在Parent找不到的时候,才从自己的范围中寻找。(询问父类有没有加载,有则不加载,没有就加载)

cache缓存机制: 如果一个类被加载器已经加载到方法区中了,那么会将这个类的.class文件存放到方法区中的cache缓存中,以保证下面在使用的时候,不用再重新加载了。

77 Junit 单元测试

Junit单元测试:可以没有main方法就可以运行某个方法

 * 对于@Test测试注意:

 * 1.要求测试的方法必须public修饰

 * 2.要求方法返回值类型必须是void

 * 3.要求方法不能含有参数

@Test,用于修饰需要执行的方法

@Before,测试方法前执行的方法

@After,测试方法后执行的方法

 

78 注解

标注解释 其实就是注释。之前学习的注释是给程序员看的。给jvm看的。

注解与类、接口同级别

1编译检查:通过代码里标识注解,让编译器能够实现基本的编译检查。例如:@Override。表示复写的意思。

说明:如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。

2代码分析:通过代码里标识注解,对代码进行分析。比如之前讲解的@Test @Before @After。

3编写文档:通过代码里标识注解,辅助生成帮助文档对应的内容  例如我们使用的java api有些方法上有@Deprecated 表示过时的意思。

 

 

JDK提供的三个注解:

1.@Deprecated 已过时show

 * 2.@Override 表示子类复写父类中的方法

 *     注意:对于子类实现接口,并复写接口中的方法,添加@Overridejdk1.6之后的技术.

3.@SuppressWarnings(“all”)

@SuppressWarnings 表示抑制警告

 * 抑制警告中的属性:

 * unused 表示忽略不使用警告

 * rawtypes 表示忽略类型安全

 * unchecked 表示忽略类型检查

 * null 表示忽略空指针异常

 * deprecation 表示忽略已过时异常

 * serial 表示忽略未声明版本号异常

 *

 * all 表示忽略所有异常就用它

 

自定义注解

自定义注解:

定义类:class 类名

{

 

}

定义接口:interface 接口名

{

 

}

定义注解:@interface 注解名{

属性

publicabstract 属性类型 属性名()   /*一般不写     default 默认值    */;

}

使用注解:@注解名

@MyAnn(属性名=属性值,属性名=属性值,属性名={})

 

元注解

@Target(value= {METHOD,TYPE})

注解属性:

u  ElementType.TYPE 修饰类、接口;

u  ElementType.CONSTRUCTOR  修饰构造方法;

u  ElementType.METHOD 修饰方法;

u  ElementType.FIELD 修饰字段;

@Retention(value= RetentionPolicy.RUNTIME)

在元注解@Retention中可以使用如下几个属性:用来表示元注解所修饰的注解能使用到什么时候

u  RetentionPolicy.SOURCE 被修饰的注解只能存在源码中,即.java文件中。字节码.class文件中没有。用途:提供给编译器使用。

u  RetentionPolicy.CLASS 被修饰的注解只能存在源码和字节码中,运行时内存中没有。用途:JVM, java虚拟机使用。

RetentionPolicy.RUNTIME 被修饰的注解存在源码、字节码、内存(运行时)。用途:取代xml配置。注意:因为我们要解析注解,而解析注解需要使用反射技术,要想使用反射技术,那么要求注解必须存在内存中,即在元注解@Retention中需要设置RetentionPolicy.RUNTIME

 

解析自定义注解(反射)

获取方法method上的注解使用Method类中的方法:

       /*

        * <T extends Annotation> TgetAnnotation(Class<T> annotationClass)

        *  如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null

        *  参数:

        * annotationClass 表示注解的名字属于Class类型

        */

       MyAnnotation2 an = m.getAnnotation(MyAnnotation2.class);

       //根据注解对象名an获取注解 MyAnnotation2中的属性值

       int age = an.age();

 

判断方法上是否有注解

使用Method的父类AccessibleObject类中的方法:

            * boolean isAnnotationPresent(Class<? extends Annotation>annotationClass)

            *   如果指定类型的注释存在于此元素上,则返回 true,否则返回 false

            *   参数:

            *  annotationClass 注解的类名属于Class类型

 

79 动态代理

动态代理:就是在程序运行的过程中,动态的生成一个类,这个类要代理目标业务对象,并且可以动态生成这个代理类的对象。

需要

被代理类

共同方法接口

创建测试类

使用jdk中的Proxy类生成代理类的对象:使用Proxy中的方法: static Object

返回接口类型 * newProxyInstance(ClassLoaderloader, Class<?>[] interfaces,

        * InvocationHandler h) 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。参数:

        * 1.loader 表示类加载器注意:一个类的字节码文件不可能自己出现在方法区中,必须需要类加载器来加载,所以我们这里必须给一个类加载器来

        * 将代理类加载到方法区中

        * 2.interfaces 获取代理类和被代理类的共同接口们,返回值属于Class类型并且是一个数组

        * Class<?>[] interfaces={Star.class};使用Class类中的方法: Class<?>[]

        * getInterfaces() 确定此对象所表示的类或接口实现的接口。

        * 3.h

        * 属于InvocationHandler接口的实现类对象,表示调用处理器,

        * InvocationHandler接口中的只有一个非常重要的方法: Object invoke(Objectproxy,Method

        * method, Object[] args) 在代理实例上处理方法调用并返回结果。

invoke 方法的三个参数:proxy 表示动态代理类的对象这里不用管 method

            * 表示方法。表示接口中的方法即就是代理类和被代理类中的共有方法args 表示参数.表示接口中具体方法的参数

public Object invoke(Objectproxy,Method method, Object[]args) throwsThrowable {

                // 获取代理类和被代理类中的共有方法的名字

                /*

                 * StringgetName() String形式返回此 Method对象表示的方法名称。

                 */

                Stringmethod_name = method.getName();

                // 判断method_name表示哪个方法

                if ("sing".equals(method_name)) {

                    // 说明是sing方法

                    // 获取sing方法的参数

                    doublemoney= (double)args[0];

                    // 判断money钱数

                    if (money< 200000) {

                        System.out.println("穷屌丝,一边玩泥巴去,滚。。。。");

                        return null;

                    }

                    // 说明钱够用

                    System.out.println("我抽取了" +money * 0.2 + "");

                    // 调用LiuYan类中的方法

//                  ly.sing(money * 0.8);

//                  return null;

                    returnmethod.invoke(ly,money *0.8);

 

80 XML

xml的作用就是保存数据的,然后使用java代码来读取数据的。浏览器也可以解析xml文档中的数据,但是在开发中用处不大。

XML(可扩展标记语言)

第一行声明:

<?xmlversion=”1.0”encoding=”utf-8”?>

版本号           编码

 

标签格式:

注释<!--  -->

<> 

</>

标签:分两类:

    1.双标签 <标签名属性名=属性值属性名=属性值属性名=属性值。。。。>文本值</标签名>

    2.单标签 <标签名属性名=属性值属性名=属性值属性名=属性值。。。。/>

    注意:标签中的属性名可以任意,属于标识符

   

    xml中的预定义实体:

       <  使用 &lt;          > 使用 &gt;

    <java从入门到放弃>

    CDATA:可以将文本数据原样显示

    格式:<![CDATA[原样数据]]>

   

注意:

1.  在一个xml文件中华必须只有一个根标签例如:<persons></persons>

dtd约束

后缀是.dtd

1- 描述书籍的xml DTD的内部约束

    <!DOCTYPE 根元素 [元素声明]>表示DTD约束的内部声明或者引入

引入本地外部约束dtd格式:

    <!DOCTYPE 根标签 SYSTEM "外部约束的路径">

3.外部公共约束,DTD文档在网络上,一般都有框架提供。

<!DOCTYPE 根标签 PUBLIC"//UNKNOWN/" "unknown.dtd">

DOCTYPE:表示声明。

PUBLIC : 公共的,修饰符;

"//UNKNOWN/": 给引的外部文件取别名;

"unknown.dtd":外部文件的地址,一般是一个互联网地址。http://......

 

    <!ELEMENT 元素名称类别>表示DTD约束中对于元素(标签)的声明

    注意啦:

    1.如果声明的标签下面含有子标签,那么声明元素格式是:<!ELEMENT元素名称 (子标签1,子标签2,子标签3......)>

    2.如果标签下面没有子标签了,直接是文本,那么声明格式是:<!ELEMENT元素名称 (#PCDATA)>  #PCDATA表示前面的元素必须是文本

<!ELEMENT books (book)> 表示在根标签books下只有有一个子标签book

       * 0 1 n

       ? 0 1

       + 1 n

<!ELEMENT name (#PCDATA)> 表示name标签下面必须是文本

<!ELEMENT books (book*)可以有多个子标签book

<!ELEMENT book (name,author,price)有以下子标签

<!ELEMENT name (#PCDATA)>标签内容seria

 

属性声明拥使用下列语法:

<!ATTLIST 元素名称属性名称属性类型默认值>

解释:

元素名称就是表示哪个标签名称即哪个标签需要属性

属性名称表示标签上面的属性名

属性类型 CDATA表示字符数据 ID 值为唯一的 id

默认值就是前面元素的属性默认值 如果属性不给值,那么会使用默认值

<!ATTLISTbook address CDATA"图书馆">

<bookaddress="藏经阁"id="b1">

 

<!ATTLISTbook id ID #REQUIRED>

<bookid="b2">

属性的默认值

#REQUIRED

属性值是必需的

#IMPLIED

属性不是必需的

#FIXED value

属性值是固定的

 

schema约束

后缀.xsd

1.xmlns="http://www.w3.org/2001/XMLSchema"表示此schema约束受到W3组织约束

    2.targetNamespace="http://www.example.org/books"名称空间他就相当于我们javase中的package包,只要在xml中使用该约束的时候

       导入这个名称空间名:http://www.example.org/books即可

    3.elementFormDefault="qualified"他的值有两个一个是qualified表示这个约束的名称空间中包含了所有标签

    如果值是unqualified表示名称空间只有根标签

   

    关于schema约束,对xml中的标签分为:

    复杂标签:带子标签或者属性<book address="藏经阁"></book>

    对于复杂标签我们需要使用:

    complexType 复杂

    表示子标签顺序:<sequence>

    简单标签:只有文本的标签 <name>java从入门到放弃</name>

 

<schema

    xmlns="http://www.w3.org/2001/XMLSchema"

    targetNamespace="http://www.example.org/books"

    elementFormDefault="qualified">

      <!-- 在这里书写schema约束

        <element name=”标签名”></element>

      -->

      <elementname="books">

        <complexType><!--表示books标签是一个复杂标签 -->

            <sequence><!-- books下的子标签的顺序 -->

                  <elementname="book">

                    <complexType>

                        <sequence>

                              <elementname="name"></element>

                              <elementname="author"></element>

                              <elementname="price"></element>

                        </sequence>

                        <attributename="address"></attribute>

                    </complexType>

                  </element>

            </sequence>

        </complexType>

      </element>

</schema>

<!--

    xmlns="http://www.example.org/books" 表示引入外部的schema约束的工作空间

   

    xsi:schemaLocation="http://www.example.org/books     books.xsd"

                            表示引入外部的schema约束的工作空间     schema约束的具体位置

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">表示此xml文件是一个schema约束的一个实例

 

 -->

<books

    xmlns="http://www.example.org/books"

    xsi:schemaLocation="http://www.example.org/booksbooks.xsd"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <bookaddress="藏金阁">

        <name>面试宝典</name>

        <author>锁哥</author>

        <price>12.2</price>

    </book>

</books>

 

解析XML

常用解析方式:

DOM解析:将文档整体加载到内存形成一个DOM树在解析,DOM解析支持文档的增删改查。

SAX解析:读取一行解析一行,只支持文档的查询,不支持文档的增删改查。

PULL解析:类似SAX解析,Android的常用解析技术。

 

dom解析与sax解析的区别:

dom:整个文档加载,可以增删改查,效率低。

sax:  逐行解析,不可以增删改,只是支持查询,效率高。

常用解析技术(了解)

JAXP:SUN公司的官方解析技术,支持DOM解析和SAX解析。

JSOUP:一种解析HTML的特定解析的开发包。

JDOM:开源组织的DOM方式的解析技术。

DOM4J:JDOM的分离版 增强版,开源,dom解析方式,Hibernate底层的XML解析技术。

注意:对于上述解析技术我们只需要了解,因为后期我们学到框架的时候,这些解析技术框架全部给我们已经提供了。

使用xpath技术结合DOM4J技术读取xml文件

代码实现:

@Test

    public void xpathTest() throwsException {

       // 1.xml文件加载到内存中,形成document对象

       SAXReader reader = newSAXReader();

       // 通过reader.read("books.xml")获取document对象

       Document document = reader.read("books.xml");

       //获得name标签

       List<Element> names = document.selectNodes("//name");

       //输出长度

       System.out.println(names.size());

    }

 

81 BeanUtils工具类

第三方包

需要无参构造setget方法

需要抓异常

BeanUtils.setProperty(Object bean,String name, Object value);

bean 对象

name 属性名

value 设置的值

对应也有get方法

BeanUtils.getProperty(Object bean,String name);

bean 对象

name 属性名

 

// 创建User类的对象

       User u = new User();

       // 使用BeanUtils类中的方法给User类中的属性赋值

       /*

        * bean 表示给哪个对象的属性赋值 name表示属性名 value属性值

        */

       try {

           BeanUtils.setProperty(u,"username", "柳岩");

           BeanUtils.setProperty(u,"password", "123");

 

populate(Object bean, Map<String,String[]>properties)

 * 参数:

 * bean 向哪个对象封装数据

 *properties 获取的数据存储到集合中

 * Map集合中的key表示User类中的属性名  value 表示给属性赋的值

//创建User类的对象

        Useru = new User();

       //创建集合对象

       Map<String,String[]> m=new HashMap<String,String[]>();

//     String[] arr={"柳岩"};

//     String[] arr=newString[]{"柳岩"};

       //添加数据

       m.put("username",new String[]{"刘亦菲","柳岩"});

       m.put("password",new String[]{"123"});

       m.put("age",new String[]{"18"});

       m.put("hobbies",new String[]{"吃饭","睡觉"});

       //使用BeanUtils类中的populate方法封装数据

       try {

           BeanUtils.populate(u,m);

           System.out.println(u);

       } catch (Exceptione) {

           e.printStackTrace();

       }

原创粉丝点击