java se 订阅
Java SE(Java Standard Edition,Java 标准版)是Java技术的核心和基础,是Java ME和Java EE编程的基础 [1]  。Java SE是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的Hot Java浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器均支持Java applet。 展开全文
Java SE(Java Standard Edition,Java 标准版)是Java技术的核心和基础,是Java ME和Java EE编程的基础 [1]  。Java SE是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台的总称。用Java实现的Hot Java浏览器(支持Java applet)显示了Java的魅力:跨平台、动态的Web、Internet计算。从此,Java被广泛接受并推动了Web的迅速发展,常用的浏览器均支持Java applet。
信息
外文名
Java标准版
类    属
软件
相关版本
Java EE
中文名
JAVA SE
设计公司
Sun Microsystems
所属学科
计算机
JAVA SE版本平台
标准版的Java平台是一个Java2的平台,为用户提供一个程序开发环境。这个程序开发环境提供了开发与运行Java软件的编译器等开发工具、软件库及Java虚拟机。它也是Java2平台、企业版本和Java网页服务的基础。Java2平台有3个版本,它们是适用于小型设备和智能卡的Java2平台Micro版(Java2 Platform Micro Edition,JavaME)、适用于桌面系统的Java 2平台标准版(Java2 Platform Standard Edition,Java SE)、适用于创建服务器应用程序和服务的Java 2平台企业版(Java2 Platform Enterprise Edition,Java EE)。
收起全文
精华内容
参与话题
问答
  • javase知识点大全总结

    千次阅读 多人点赞 2018-09-24 12:21:02
    JAVASE知识点总结 Java基础语法 1.标识符 1.在java语言中,对各种变量,方法和类等要素命名时所使用的字符序列就是标识符。 这些标识符有jdk定义好的,也有我们自己开发时候需要定义的。 2.java中标识符由26个英文...

    JAVASE知识点总结

    Java基础语法
    1.标识符
    1.在java语言中,对各种变量,方法和类等要素命名时所使用的字符序列就是标识符。
    这些标识符有jdk定义好的,也有我们自己开发时候需要定义的。
    2.java中标识符由26个英文字符大小写,数字0-9,符号_ $。注意:数字不能开头。
    3.java中是严格区分大小写
    4.在实际写程序的过程中定义标识符遵守“见名之意”.
     类名和接口的规范:
    在上面的约束的命名规范的情况下,首字符要大写。如果由多个单词构成每个单词的首字符都大写。
    XxxYyy
    如:PersonService
     变量名和方法名:
    在上面的约束的命名规范的情况下,我们遵守单词首字符不要大写,如果由多个单词构成,从第二个单词起首字符都大写。这叫驼峰模式。
    xxxYyyZzz
    如:personDao
     包名
    在上面的约束的命名规范的情况下,都小写。
    xxx.yyy.zzz
     常量
    所有字符都大写,多个单词之间使用下划线来分隔。
    XXX_YYY_ZZZ
    2.关键字
    Jdk定义的标识符就是关键字,我们不可以使用。所以我们定义标识符的时候一定要避开关键字。

    3.java中的注释
    注释就是给程序说明的作用,我们要养成写注释的良好习惯,增强代码的可读性。
    Jvm运行时注释不会被解析。Jvm会跳过注释。
     多行注释:/…./,通常用于方法内的多行或者类的多行注释

    /*
    public static void main(String[] args){

    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	
    }
    */
    

     单行注释语法://,注释代码中的一行,建议大家放在要注释的代码的上面
     文档注释:语法/**…*/,用于类的说明和方法的说明

    /**
    *这是我们第一个HelloWorld的程序
    */
    class HelloWorld{

    /**
    

    *这是这是我们的主方法
    */
    public static void main(String[] args){

    	//输出helloWorld
    	System.out.println("HelloWorld1");
    	//输出helloWorld1
    	System.out.println("HelloWorld1");
    	
    	/*
    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	System.out.println("HelloWorld1");
    	*/
    }
    

    }
    4.进制(了解)
    几进制就是数字达到几就进一位。常用的进制:十进制,二进制,八进制,十六进制。
    生活中十进制用的最多。
    计算机中二进制用的最多。
    1.进制的转换
    1.十进制转成R进制
    十进制转换R进制,用十进制来除以R,把余数保留下来,用得到的商再去除R再保留余数,知道商为0为止。我们所得到的余数的倒序就是转换成R进制之后的数。
    把十进制转换成十进制。

    							余数
    

    10| 9527 7
    10 952 2
    10 95 5

    			10	  9				9
    

    把16转换成二进制的数。

    							余数
    

    2 16 0

    2	  8							0
    		2	4					0
    		
    			2     2				0
    
    					2   1       1
    

    结果是10000
    如果要把十进制转换成其他进制同理。
    2.把R进制转换成十进制
    范例1:把十进制9527数转换成十进制
    91000+5100+210+7
    9
    (10)3+5*(10)2+2*(10)1+7*(10)0=9527
    范例2:把二进制10000转换成十进制
    1*(2)4+0*(2)3+0*(2)2+0*(2)1+ 0*(2)0=16

    总结:如果把R进制的某个数xyz转换成十进制,x*®2+y®1+z®0, 每一位的次方数是数的位数从左到右递减到0的各个数。
    5.常量和变量

    1.开辟内存空间(创建jvm)
    2.加载数据
    3.CPU提取数据运行
    当数据加载到内存中时,我们按着运行期数据的是否变化把数据分成常量和变量
    1常量:
    数据不发生变化的量。
    例如:
    整数常量:24小时,一周7天,一年12月
    小数:重力系数9.8, 圆周率,3.14
    字符串常量:“旺财”, “小强”
    字符常量:‘男’,‘a’
    布尔常量:true,false
    空常量:null,代表一个空的引用,可以理解占位的作用,表示不存在。
    2.变量
    程序运行期间可以发成变化的数据

    变量的定义需要进行定义变量名字,而且还要定义变量的存储空间,而且还可以定义存储的数据类型。变量中的数据能发生变化。
    常量的定义需要进行定义常量名字,而且还要定义常量的存储空间,而且还可以定义存储的数据类型。常量中的数据不能发生变化。
    6.数据类型
    1.基本数据类型
    1.基本数据类型概述
    根据不同的数据类型可以划分内存的存储的空间大小,不同的类型就是数据类型
     整数的基本类型
    一个字节
    1 1 1 1 1 1 1 1

    byte		最小存储整数的空间		1字节
    short							2字节
    int								4字节
    long		最大存储整数的空间		8字节
    
    byte和short计算时产生的结果默认是int类型
    

     小数的基本类型
    flout 4个字节
    double 8个字节
    如果整型数据在计算的时候结果出现了小数,结果类型默认是double

    建议使用double
     字符数据类型
    char 2字节
    如:‘a‘,’亮‘
     布尔数据类型
    boolean true false
    一共8种数据类型。
    2.定义变量
    语法:数据类型 变量名 = 值;
    我们对变量的操作:取值和存值。
    class Demo1{
    public static void main(String[] args){
    //数据类型 变量名 = 值;
    int age = 10;
    System.out.println(age);
    }
    }

    变量的定义位置:定义在方法中或者语句块中。
    变量的一定要赋初始值,否则使用该变量的时候会报错的。

    变量的作用范围:只在当前的大括号内有效,大括号外的所有程序不能使用该变量,所以这种变量也称为局部变量。

    class Demo2{
    public static void main(String[] args){
    //字节数据类型
    byte workYear = 10;
    //短整型
    short salary = 2000;
    //数据类型 变量名 = 值;
    int age = 30;
    //长整型,在定义长长整型的数据时在值后面加上l
    long empTime = 10000000l;

    	//小数类型float,float类型的数值后面一定要有f
    	float price = 45.6f;
    	//小数类型double,建议在值的后面加d
    	double totalPrice = 10000.5d;
    	
    	//布尔数据类型
    	boolean isMarry = false;
    	//字符类型
    	char sex = '男';
    	
    	
    	System.out.println("工作年限:"+workYear);
    	System.out.println("月薪:"+salary);
    	System.out.println("年龄:"+age);
    	System.out.println("入职时长:"+empTime);
    	
    	System.out.println("单价:"+price);
    	System.out.println("总价:"+totalPrice);
    	System.out.println("是否结婚:"+isMarry);
    	System.out.println("性别:"+sex);
    }	
    

    }
    这八种数据类型是有默认值的。这个默认值如果在变量中不能使用的,必须是在类的属性中使用,因为类的属性可以不赋初始化值。
    类型 默认值
    byte 0
    short 0
    int 0
    long 0
    float 0.0
    double 0.0
    char ‘/u0000’
    boolean False

    3.基本数据类型转换
    八种数据类型除了布尔类型以外都可以相互的转换。
    1.自动类型转换
    基本数据类型在计算的时候都会向数值范围大的方向转换
    byte—short–int ----long–float—double
    1.所有的byte类型和short类型和char值运算的时候都会提供成int类型。
    2.如果计算中一个操作数据类型是long,另一个数的空间小于等于long,那么结果就是long
    3.如果计算中一个操作数据类型是float,另一个数的空间小于等于float,那么结果就是float
    4.如果计算中一个操作数据类型是double,另一个数的空间小于等于double,那么结果就是double
    2.强制转换
    当大容量类型的变量向小容量的类型去转换需要强制转换。
    语法:(目标类型)值
    //在java程序中同一个范围内变量名字不能重复
    int i3 = 97;
    //把int类型的数据强制转换成byte
    byte b3 = (byte)i3;
    //把int类型的数据强制转换成short
    short s3 = (short)i3;
    //把int类型的数据强制转换成char
    char c3 = (char)i3;
    System.out.println(b3);
    System.out.println(s3);
    System.out.println(c3);

    	  int i4 = 200;
    	  //注意如果被转换的值超过了要转换的值的最大值,转换时精度就损失了,不准确。
    	  byte b4 = (byte)i4;
    	  System.out.println(b4);
    	  //把long类型的数据转换成int
    	  long l4 = 10000l;
    	  int i5 = (int)l4;
    	  System.out.println(i5);  
    	  //把小数float转换成整型,直接把小数舍弃(非四舍五入)
    	  float f1 = 12.5f;
    	  int i6 = (int)f1;
    	  System.out.println(i6);
    	   //把小数double转换成整型,直接把小数舍弃(非四舍五入)
    	  double d1 = 15.5f;
    	  int i7 = (int)d1;
    	  System.out.println(i7);
    

    思考:
    byte b1 = 3,b2=4, b;
    b = b1 + b2;//报错,因为byte类型计算完毕后会自动提升为int类型。
    b= 4+3;//不会报错,因为int类型的常量相加只要没有达到byte的上限就可以。
    2.引用数据类型
    7.运算符
    1.算数运算符
     四则运算:
    +,-,*,/
     给数值变量自身加1或减一

    class Demo4{
    public static void main(String[] args){
    //定义两个int类型的变量
    int a = 30;
    int b = 20;
    System.out.println(“a+b=”+(a+b));
    System.out.println(“a-b=”+(a-b));
    System.out.println("ab="+(ab));
    //整数之间做除法叫取整30/20=1.5,要把小数位舍弃
    System.out.println(“a/b=”+(a/b));
    //++, –
    //a++起到了给a加1的作用
    a++;
    //会输出a加1之后的值
    System.out.println(a);
    //a–起到了给a减1的作用
    a–;
    //会输出a减一1之后的值
    System.out.println(a);

    	//如果我后++或者后--和用变量在同一句代码中使用,是先使用a变量,再做加1或者减一
    	System.out.println(a--);
    	System.out.println(a)
    	//起到了给变量a加1的作用
    	--a;
    	System.out.println(a);	
    	//如果我前++或者前--和用变量在同一句代码中使用,是先做加1或者减一,再使用a变量
    	System.out.println(--a);
    }		
    

    }

    2.赋值运算符
    =,+=,-=,*=,/=, %=
    =:将左边的数值赋给右边的变量
    +=:int x = 2;x+=3;相当于x=x+3
    class Demo5{
    public static void main(String[] args){
    //把20这个值赋给a变量
    int a = 20;
    //+=,相当于a = a + 5;
    //a = a + 5;
    a+=5;
    System.out.println(a);
    //-=,相当于a = a - 5;
    a-=5;
    System.out.println(a);

    	//*=,相当于a = a * 5;
    	a*=5;
    	System.out.println(a);
    	///=,相当于a = a / 5;
    	a/=5;
    	System.out.println(a);
    	//%=,相当于a = a % 5;
    	a%=5;
    	System.out.println(a);
    }	
    

    }

    3.比较运算符
    ==,!=, >, >=, <, <=
    ==:等于
    !=:不等于

    :大于
    =:大于等于
    <:小于
    <=:小于等于
    class Demo6{
    public static void main(String[] args){
    int a = 19;
    int b = 10;
    //比较运算符的结果是布尔类型true,false
    System.out.println("ab:"+(ab));
    System.out.println(“a!=b:”+(a!=b));
    System.out.println(“a>b:”+(a>b));
    System.out.println(“a<b:”+(a<b));
    System.out.println(“a>=b:”+(a>=b));
    System.out.println(“a<=b:”+(a<=b));
    }
    }

    4.逻辑运算符
    &,|,^, &&, ||,!
    应用场景:如果某个结果需要多个条件满足或者部分条件满足的判断时使用。
    &: 用于连接多个表达式的判断,true&true=true,&两边的表达式都要参与计算。
    |:用于连接多个表达式的判断,false|false=false, &两边的表达式都要参与计算
    短路逻辑(效率高)
    &&:用于连接多个表达式的判断, true&&true=true,如果第一个表达式能决定整个表达式的结果第二个表达式就不计算了。
    ||:用于连接多个表达式的判断, false||false=false,如果第一个表达式能决定整个表达式的结果第二个表达式就不计算了。
    ^:用于连接多个表达式的判断,如果两个表达式相同就是false,不同是true,两边都参加计算 (了解)
    !:取反
    class Demo7{
    public static void main(String[] args){
    int java = 90;
    int sql = 70;
    //只有java和sql打分都大于90分才合格
    //System.out.println(java>=90&(sql++) >= 90);
    //System.out.println(java>=90|(sql++) >= 90);
    //短路与,如果第一个表达式是false,后面的表达式就不需要判断了,效率高
    //System.out.println(java>=90&&(sql++) >= 90);
    //短路或,如果第一个表达式是true,后面的表达式就不需要判断了,效率高
    //System.out.println(java>=90||(sql++) >= 90);
    //异或了解
    //System.out.println(java>=90^(sql++) >= 90);
    //System.out.println(sql);
    //如果对于表达式取反需要通过括号括上。
    System.out.println(!(java > 80));
    }
    }

    5.位运算符
    << >> >>> & | ^
    在计算机中参与计算的都是二进制的数据,二进制数据分为原码,反码,补码,运算的时候都是用补码来运算。
    原码 反码 补码

    整数	0000 0011		0000 0011          0000 0011
    负数	1000 0011		1111 1100		   1111 1101
     1111 1100
    
    • 0000 0001

     1111 1101
    

    <<:将参与运算的二进制数据向左移动,在低位产生的空位用0来做补齐。
    整数3二进制的形式
    0 0 0 0 0 0 1 1
    整数3二进制左移2位
    0 0 0 0 1 1 0 0
     >>将参与运算的二进制数据向右移动,在高位产生的空位如果高位是0那么就用0来做补齐,如果高位是1就用1来补齐。也就是说右移是带着符号位移动
    整数3二进制的形式
    0 0 0 0 0 0 1 1
    右移2位
    0 0 0 0 0 0 0 0
    如果是负数-3右移2位
    1 1 1 1 1 1 0 1
    向右移动2位
    1 1 1 1 1 1 1 1

     >>>:无符号右移,将参与运算的数据向右移动,在高位所产生的空位0补齐。
    3二进制数
    0 0 0 0 0 0 0 0
    如果是负数-3右移2位
    1 1 1 1 1 1 0 1
    向右移动2位
    0 0 1 1 1 1 1 1
    左移和右移特点:执行速度快

    &:与,&不仅可以作为逻辑运算符,还可以做与运算,0相当于false,1相当于true,只有1和1与计算结果是1,其余都是0
    0011
    & 0101

    0001
    |:与,|不仅可以作为逻辑运算符,还可以做与运算,0相当于false,1相当于true,只有0和0与计算结果是0,其余都是1
    0011

    0101

    0111
    ^: 异或计算,^不仅可以作为逻辑运算符,还可以做与运算,如果计算的两个数相同就是0,不同就是1
    0011

    0101

    0110
    J2SE程序的流程控制
    1.判断结果
    1.简单if
    语法:if(条件判断表达式){
    执行语句
    }
    如果条件判断的表达式返回值是true则可以执行if内部的语句,否则如果是false就不可以执行。
    范例1:如果java考试成绩大于等于60及格
    class Demo1{
    public static void main(String[] args){
    int score = 70;
    if(score >= 60){
    System.out.println(“及格”);
    }
    System.out.println(“程序结束”);
    }
    }
    2.if…else
    语法:if(条件判断表达式){
    执行语句
    }else{
    执行语句
    }
    范例2:如果java考试成绩大于60及格,否则是不及格
    class Demo1{
    public static void main(String[] args){
    int score = 10;
    if(score >= 60){
    System.out.println(“及格”);
    }else{
    System.out.println(“不及格”);
    }
    System.out.println(“程序结束”);
    }
    }
    3.多重 if….else if…else
    语法:if(条件判断表达式){
    执行语句
    }else if(条件表达式1){
    执行语句
    }else if(条件表达式2){
    ……
    }else{
    }
    范例3:如果大于等于60小于等于85及格,大于等于85小于100优秀,如果等于100完美,其余的不及格。
    class Demo1{
    public static void main(String[] args){
    int score = 100;
    if(score >= 60 && score < 85){
    System.out.println(“及格了”);
    }else if(score >= 85 && score < 100){
    System.out.println(“优秀”);
    }else if(score == 100){
    System.out.println(“完美”);
    }else{
    System.out.println(“不及格”);
    }
    System.out.println(“程序结束”);

    }
    

    }
    范例: 如果工资大于3000D级,大于5000C级,大于7000B级,大于10000A级
    通过简单if组合的形式
    class Demo2{
    public static void main(String[] args){
    int salary = 7000;
    if(salary >= 3000 && salary < 5000){
    System.out.println(“D级”);
    }
    if(salary >= 5000 && salary < 7000){
    System.out.println(“C级”);
    }
    if(salary >= 7000 && salary < 10000){
    System.out.println(“B级”);
    }
    if(salary >= 10000){
    System.out.println(“A级”);
    }
    }
    }

    通过多重if实现
    class Demo3{
    public static void main(String[] args){
    int salary = 3000;
    //多重if当遇到第一个满足的表达式条件时执行当前的if语句,就不会再向下去执行
    if(salary >= 10000){
    System.out.println(“A级”);
    }else if(salary >= 7000){
    System.out.println(“B级”);
    }else if(salary >= 5000){
    System.out.println(“C级”);
    }else if(salary >= 3000){
    System.out.println(“D级”);
    }
    }
    }
    2.Switch分支判断
    Switch:由上到下用switch中的表达式和值进行比较,如果匹配成功就执行case后的语句,在执行break的时跳出switch,如果一个也没有匹配上就执行default默认情况。

    Switch(表达式){
    case 常量1:
    执行语句1;
    break;
    case 常量2:
    执行语句2;
    break;
    ……
    default:
    执行语句 ;
    break;
    }
    范例1:通过等级打印不同星
    class Demo4{
    public static void main(String[] args){
    /***
    等级1用☆
    等级2用☆☆
    等级3用☆☆☆
    等级4用☆☆☆☆
    等级4用☆☆☆☆☆
    */
    int grade = 0;

    	switch(grade){
    		case 1:
    			System.out.println("☆");
    			break;
    		case 2:
    			System.out.println("☆☆");
    			break;
    		case 3:
    			System.out.println("☆☆☆");
    			break;
    		case 4:
    			System.out.println("☆☆☆☆");
    			break;
    		case 5:
    			System.out.println("☆☆☆☆☆");
    			break;
    		default:
    			System.out.println("输入错误");
    			break;
    	}
    }
    

    }
    Break可以省略不会报错,如果省略就会穿透执行语句(不管是否能匹配上),知道遇到一个break才会跳出,所以我们不建议省略break。
    在jdk1.7之前,swtich的表达式只能是byte, short, char, int,但是1.7后可以使用String
    范例2:计算指定年的月中有多少天
    class Demo5{

    public static void main(String[] args){
    	//计算每一年的每一月有几天
    	int year = 2000;
    	int month = 2;
    	int day = 0;
    	switch(month){
    		case 1:
    		case 3:
    		case 5:
    		case 7:
    		case 8:
    		case 10:
    		case 12:
    			day = 31;
    			break;
    		case 4:
    		case 6:
    		case 9:
    		case 11:
    			day = 30;
    			break;
    		case 2:
    		if((year%400) == 0 || (year%4 == 0&& year%100 != 0)){
    			day = 29;
    		}else{
    			day = 28;
    		}
    		break;
    		default:
    		break;	
    	}
    	System.out.println(year + "年"+ month+"月有"+day+"天");
    }
    

    }
    注意:
    Switch和多重if的区别:
    If可以做等值判断也可以做区间判断。
    Switch只能做等值判断,不能做区间判断
    3.三元运算符
    语法:表达式1 关系运算符 表达式2?表达式3:表达式4
    ?前面的表达式2如果运算的结果是true,整个表达式的结果就是表达式3
    ?前面的表达式2如果运算的结果是false,整个表达式的结果就是表达式4
    注意:三元运算符适合两个值的判断
    class Demo6{
    public static void main(String[] args){
    //如果gender=1我们genderText就是男,如果gender=2那么genderText=女
    int gender = 1;
    char genderText = ’ ';
    /*
    if(gender == 1){
    genderText = ‘男’;
    }else if(gender == 2){
    genderText = ‘女’;
    }
    System.out.println(genderText);
    */
    //表达式1 赋值 表达式2
    genderText = gender == 1?‘男’:‘女’;
    System.out.println(genderText);
    }
    }
    4.循环结构
    循环:就是重复发生的过程(循环一般有重复的前提条件)。
    1.While
    语法:while(表达式){
    循环体
    }
    表达式结果如果是true那么就执行循环体,如果是false就结束循环

    								否
    
    
    
    
    				是
    

    范例:1
    class Demo7{
    public static void main(String[] args){
    /*
    打印1到100之间的数字
    分析:
    循环条件:是否完成打印100次
    循环操作:输出,自增
    */

    	//循环变量,计数器
    	int i = 1;
    	while(i <= 100){
    		System.out.println(i);
    			//更改循环条件
    			i++;
    	}	
    }
    

    }

    范例:2
    class Demo8{
    public static void main(String[] args){
    /*
    需求:打印1到100之间的所有的偶数和
    分析:
    循环条件:判断计数器是否小于等于100
    循环操作:累加偶数和,更新计数器
    */
    //定义计数器
    int i = 0;
    //定义偶数和的结果变量
    int sum = 0;
    while(i <= 100){
    //判断i是否是偶数
    if(i%2 == 0){
    //累加偶数
    sum += i;
    }
    //更新计数器
    i++;
    }
    System.out.println(sum);
    }
    }

    2.do…while
    语法:do{
    循环体
    }while(表达式)
    注意:do…while和while,前者是先执行循环体,后者是先判断在执行循环体。

    范例1:
    class Demo9{
    public static void main(String[] args){
    /*
    需求:打印100到1000之间的所有水仙花数。
    234
    分析:
    循环条件:判断计数器是大于等于100小于1000
    循环操作:更新计数器,判断是否是水仙花数。
    /
    int i = 100;
    do{
    //获得个位数
    int g = i%10;
    //获得十位数
    int s = i/10%10;
    //获得百位数
    int b = i/100;
    //判断是否是水仙花数
    if((g
    gg + sss + bb*b) == i){
    System.out.println(i);
    }
    i++;

    	}while(i < 1000);	
    }
    

    }

    范例2:
    class Demo10{
    public static void main(String[] args){
    /*
    需求:打印100到1000之间的所有夹心饼数。
    如:191,838
    分析:
    循环条件:判断计数器是大于等于100小于1000
    循环操作:更新计数器,判断是否是夹心饼干
    */
    int i = 100;
    do{
    //获得个位数
    int g = i%10;
    //获得百位数
    int b = i/100;
    //判断是否是水仙花数
    if(g == b){
    System.out.println(i);
    }
    i++;

    	}while(i < 1000);
    }
    

    }

    3.for
    语法:for(表达式1; 表达式2; 表达式3){
    循环体
    }
    表达式1:计数器的初始化,它只初始化一次
    表达式2:循环条件的判断,多次执行
    表达式3:修改计数器,多次执行
    范例1:
    class Demo11{
    public static void main(String[] args){
    /*
    需求:打印1到100之间的所有的偶数和
    分析:
    循环条件:判断计数器是否小于等于100
    循环操作:累加偶数和,更新计数器
    */
    //定义偶数和的结果变量
    int sum = 0;
    for(int i = 0; i <= 100; i++){
    if(i%2 == 0){
    sum += i;
    }
    }
    System.out.println(sum);
    }
    }
    范例2:打印一个5行5列的☆
    class Demo12{

    public static void main(String[] args){	
    	/*
    		需求:打印5行5列 的☆
    		分析:
    			我们要使用2个循环
    			循环条件:判断计数器是否小于等于100
    			循环操作:累加偶数和,更新计数器
    	*/
    	//定义偶数和的结果变量
    	for(int i = 0; i < 5; i++){
    		for(int j = 0; j < 5; j++){
    			System.out.print("☆");
    		}
    		System.out.println();
    	}
    	
    }
    

    }

    范例2:打印乘法口诀
    11=1
    1
    2=2 22=4
    1
    3=3 23=6 33=9
    ……
    class Demo13{
    public static void main(String[] args){
    /*
    范例2:打印乘法口诀
    11=1
    1
    2=2 22=4
    1
    3=3 23=6 33=9
    ……
    */

    	for(int i = 1; i <=9; i++){
    		for(int j = 1; j <= i; j++){
    			System.out.print(j+"*"+i+"="+j*i+"\t");					
    		}
    		System.out.println();
    	}	
    }
    

    }

    总结:
     最重要的循环是while和for
     如果循环开始之前就能确定循环次数我们建议使用for
     如果循环次数不定建议使用while

    4.break
    Break用来跳出循环和switch
    class Demo14{
    public static void main(String[] args){
    /**
    需求:运动会上跑5000米,跑到第三圈时,抽筋了退赛
    /
    for(int i = 1; i <= 10; i++){
    if(i == 3){
    System.out.println(“抽筋了退出”);
    //跳出循环
    break;
    }
    System.out.println(“我跑到第”+i+“圈”);
    }
    }
    }
    5.continue
    也是来控制循环,在某次循环的时候放弃,后续的接着循环。
    class Demo15{
    public static void main(String[] args){
    /
    *
    需求:一周上五天班,然后我周三请假一天

    	*/
    	for(int i = 1; i <= 5; i++){
    		if(i == 3){
    			System.out.println("周三肚子疼请假");
    			//跳出本次循环,接着下一次循环
    			continue;
    		}
    		System.out.println("今天星期"+i+"上班");
    	}	
    }
    

    }

    J2SE函数和数组
    1.函数(方法)
    1.函数(方法)
    方法是一段能完成独立功能的代码块。我们只需要写一次方法,可以被多次调用,提高了代码的复用性。

    2.语法:
    返回值类型[void] 方法名([数据类型 变量名, 数据类型1 变量名1,……]){
    //方法体
    [return 结果值];
    }

     :后续详解
     返回值类型[void]:方法给调用者返回的数据类型,如果放飞没有返回值,我们就使用void
     方法名: 见名之意,使用驼峰模式来规范方法名:xxxYyyZzz
     参数列表:方法的参数可有可无,参数列表中可以有无数个参数,先指定参数数据类型,再指定参数的变量名,多个参数用逗号分隔。
     Return:在方法有返回值的情况,返回的具体数据。
    注意:方法是定义在类里面的。

    a
    
    									b
    
    
    
    
    
    
    
    
    
    
    				aa     bb
    

    a和b叫做实参,方法参数列表中的aa和bb是形参,a,b和aa,bb的地址是不同的,只不过是通过值传递的方式放实参的值传递给形参,所以参数列表中的数据类型必须匹配,变量名可以随意。
    注意:当前语句块中return 语句下不能再有代码。
    如果返回值类型是void 就不需要return语句
    public static void compareMax1(int aa, int bb){
    if(aa > bb){
    System.out.println(aa+“大”);
    }else{
    System.out.println(bb+“大”);
    }
    }

    3.方法的重载
    在同一个类中函数(方法)名字,参数列表不一样(1. 参数个数不一样,或者2.类型不一样),跟返回值一点关系没有。
    目的:为了节约方法的功能命名和提高代码的可读性。
    public static int add(int a, int b){
    return a+b;
    }
    public static double add(int a, double b){
    return a+b;
    }

    public static int compareMax(int aa, int bb){
    if(aa > bb){
    //把大的值返回去
    return aa;
    //System.out.println(“hh”);
    }else{
    return bb;
    }
    }
    public static int compareMax(int aa, int bb, int cc){
    //返回的一定aa和bb中大的数
    int resultab = compareMax(aa, bb);
    //拿aa和bb中大的数和cc比较
    int resultabc = compareMax(resultab, cc);
    return resultabc;
    }

    打印乘法口诀
    class Demo8{
    public static void main(String[] args){
    print99();
    }
    public static void print99(){
    for(int i = 1; i <= 9; i++){
    for(int j = 1; j <=i; j++){
    System.out.print(i+""+j+"="+ij+"\t");
    }
    System.out.println();
    }
    }
    }
    2. 数组
    整数类型(byte,short,int,long)
    数值型
    浮点类型(float, double)
    基本数据类型 字符型 (char)

    数据类型 布尔类型(boolean)
    类(class)
    引用数据类型 接口(interface)

    							数组([])
    

    数组:内存中保存数据的集合。
    1.数组的定义
    语法:
    定义1:
    数据类型[] 数组名 = new 数据类型[整数];
    整数:是数组的长度。

    获得数组的长度使用数组的属性length。
    我们通过数组的变量名(数组的整地址),通过数组的变量名加上数组的下标或者索引可以对数组的每一个值进行操作。
    class Demo9{
    public static void main(String[] args){
    //定义了一个10个长度的int类型的数组
    int[] array = new int[10];
    array[0] = 12;
    array[1] = 63;
    array[2] = 87;
    array[3] = 45;
    array[4] = 52;
    array[5] = 134;
    array[6] = 29;
    array[7] = 98;
    array[8] = 13;
    array[9] = 56;
    //获得数组的长度
    System.out.println(“数组的长度:”+array.length);
    //打印数组
    for(int i = 0; i < array.length; i++){
    System.out.println(array[i]);
    }
    }
    }
    数组定义的第二种方式:
    语法:数据类型[] 数组变量名 = {值1, 值2,……}
    Int [] array = {12, 34, 56,……};
    数组的长度由value的数量来决定
    数组的定义的第三种方式:
    语法:数据类型[] 数组变量名 = new 数据类型[]{值1,值2,值3,……}
    数组的长度由value的数量来决定
    class Demo10{
    public static void main(String[] args){
    //定义了一个不定长度的int类型的数组
    //int[] array = {12,4,5,24,78,94};
    int[] array = new int[]{12,4,5,24,78,94};
    //获得数组的长度
    System.out.println(“数组的长度:”+array.length);
    //打印数组
    for(int i = 0; i < array.length; i++){
    System.out.println(array[i]);
    }
    }
    }

    注意:在数组的操作过程中常见的问题就是数组的越界问题
    class Demo11{
    public static void main(String[] args){
    //定义了一个不定长度的int类型的数组
    int[] array = {12,4,5,24,78,94};
    //获得数组的长度
    System.out.println(“数组的长度:”+array.length);
    System.out.println(“打印指定数组的值:”+array[6]);
    }
    }

    2.数组在内存中的划分
    内存区分配:
    栈内存:容量小,速度快,数据的生命周期短,先进后出,保存局部变量(函数里面的变量,语句块中的变量)
    堆内存:容量大,速度慢,保存引用数据类型的数据。
    方法区:保存所有对象的共享数据。

    定义数组
    int[] array = new int[]{12,4,5,24,78,94};
    栈中存储堆中数组的首地址。

    3.数组的常用的操作
    1.遍历
    把整个数组每个数都访问一遍。
    public static void printArr(int[] array){
    for(int i = 0; i < array.length; i++){
    System.out.print(array[i]+"\t");
    }
    }

    2.求极值
    在操作数组的时候常见的错误

    12 4 5 78 94 24
    Max = 94
    class Demo13{
    public static void main(String[] args){
    //定义了一个不定长度的int类型的数组
    int[] array = {12,4,5,24,78,94};
    //int[] array = {};
    int max = getMax(array);
    System.out.println(max);
    }
    public static int getMax(int[] array){
    if(array != null && array.length != 0){
    int max = array[0];
    for(int i = 0; i < array.length; i++){
    if(max < array[i]){
    max = array[i];
    }
    }
    return max;
    }else{
    return 0;
    }
    }
    }

    3.排序
    冒泡排序(Bubble sort):相邻的两个数逐个的做比较,如果前一个数比后一个数小那么就交换过来,当第一轮比较完毕后最小的值一定产生在末尾。

    23 25 25 25 51

    25 23 23 51 25

    12 12 51 23 23

    7 51 12 12 12

    51 7 7 7 7
    class Demo14{
    public static void main(String[] args){
    int [] array = {23, 34, 87, 12,7, 83, 57};
    bubbleSort(array);
    printArr(array);
    }
    public static void bubbleSort(int [] array){
    //比较的轮数
    for(int i = 0; i < array.length - 1; i++){
    //每一轮所比较的次数,因为每一轮比较时会产生一个最小值,所有每一轮比较就会少一次
    for(int j = 0; j < array.length - 1 -i; j++){
    //如果后一个数比前一个数大,那么就做交换
    if(array[j+1] < array[j]){
    //通过临时变量来存储后一个数
    int temp = array[j+1];
    //把后一个数换成前一个数
    array[j+1] = array[j];
    //再把前一个数换成后一个数
    array[j] = temp;
    }
    }
    }
    }
    public static void printArr(int [] array){
    for(int i = 0; i < array.length; i++){
    System.out.print(array[i]+"\t");
    }
    }
    }

    4.查找
    1.对任意的数组查找:

    class Demo15{
    public static void main(String[] args){
    int [] array = {23, 34, 87, 12, 7, 83, 57};
    int index = getValueIndex(array, 57);
    System.out.println(index);
    }
    public static int getValueIndex(int [] array, int value){
    //定义要查找的索引
    int index = -1;
    //遍历数组
    for(int i = 0; i < array.length; i++){
    //如果找到了目标值
    if(array[i] == value){
    //把索引赋给结果值
    index = i;
    //跳出循环
    break;
    }
    }
    //返回结果
    return index;
    }
    }
    2.对有序的数组查找—二分法查找
    二分法查找数据的数组是要有排序的。效率非常高。
    我们要查找7

    1 2 3 4 5 6 7 8 9 10

    我们可以把有序的数组一分为二取到中间值
    minIndex = 0;
    maxIndex = length -1
    midIndex = (minIndex + maxIndex)/2
    如果要查找的值大于中间索引的值,那么我们就大于中间索引的半个数组中去查找,然后再在半个数组中取中间值,继续比较然后依次二分,直到找到数据为止。
    class Demo16{
    public static void main(String[] args){
    int [] array = {1,2,3,4,5,6,7,8,9,10};
    int index = getBinaryQuery(array, 3);
    System.out.println(index);
    }
    public static int getBinaryQuery(int [] array, int value){
    //定义最小的索引
    int min = 0;
    //定义最大索引
    int max = array.length -1;
    //计算中间索引
    int mid = (min + max)/2;
    //通过while来做二分循环
    while(array[mid] != value){
    //重新计算最小和最大索引
    //如果要查找的值比中间小
    if(array[mid] > value){
    max = mid - 1;
    //如果要查找的值比中间大
    }else{
    min = mid + 1;
    }
    //更新中间索引
    mid = (min + max)/2;
    }
    return mid;
    }
    }

    5.倒置
    原数组
    12 3 56 7 23 4 57
    倒置后
    57 4 23 7 56 3 12

    1.获得数组中间的索引length/2;
    2.获得中间索引前的索引的对称端的索引
    Length -1 – i

    class Demo17{
    public static void main(String[] args){
    int [] array = {1,2,3,4,5,6,7,8,9};
    reversArray(array);
    printArray(array);
    }
    public static void reversArray(int [] array){
    for(int i = 0; i < array.length/2; i++){
    int temp = array[i];
    array[i] = array[array.length - 1- i];
    array[array.length - 1 - i] = temp;
    }
    }
    public static void printArray(int [] array){
    for(int i = 0; i < array.length; i++){
    System.out.print(array[i]+"\t");
    }
    }
    }
    4.二维数组
    二维数组就是集合中套集合。
    数据类型[][] 数组名 = new 数据类型[整数][]
    注意:必须明确外围数组名
    数据类型[][] 数组名 = {{值1,值2,值3},{值4,值5,值6}, ,……}
    Int[][] array1 = new int[3][4];
    int[][] array = {{1,2,3},{4,5,6},{8,3,6},……}

    class Demo18{
    public static void main(String[] args){
    int [][] array = {{1,2,3,4},{5,6,7,8},{13,3,4,9}};
    printArray(array);
    }
    public static void printArray(int [][] array){
    //array.length指的是集合中有几个集合
    for(int i = 0; i < array.length;i++){
    for(int j = 0; j < array[i].length; j++){
    System.out.print(array[i][j]+"\t");
    }
    System.out.println();
    }
    }
    }
    面向对象
    1.面向对象概述
    1.类的概念
    我们把某些具有相同的属性和行为的事物抽象成一类。
    狗:狗是一类,所以类是一个概念,类中的一个具体的对象如:金毛犬,牧羊犬,八哥犬,京吧犬等等。
    类和对象的关系:犹如模板和样本的关系,通过一个模板可以创建多个当前模板下的样例。
    注意:类是概念,对象才是真正的实例。
    定义类的语法:
    class 类名{
    属性
    方法
    }

    类名:首字母大写的驼峰模式XxxYyy

    我们可以根据类来创建对象
    创建对象的语法:类名 变量名 = new 类名();

    实例代码:
    class Dog{
    /**
    定义狗这个类的属性
    /
    double weight;
    double height;
    String name;
    /
    *
    定义狗类的方法
    /
    public void protectHome(){
    System.out.println(name+“在看家”);
    }
    public void sleep(){
    System.out.println(name +“在睡觉”);
    }
    }
    /
    *
    创建测试类
    /
    class TestClass{
    public static void main(String[] args){
    //创建一个Dog类的对象
    Dog dog = new Dog();
    //根据对象变量.属性就可以获得或者设置属性的值
    dog.name = “栗子黄”;
    dog.height = 0.5;
    dog.weight = 50;
    System.out.println(“狗的名字:”+dog.name);
    System.out.println(“狗的体重:”+dog.weight);
    System.out.println(“狗的身高:”+dog.height);
    //通过dog对象调用它的方法
    dog.protectHome();
    dog.sleep();
    System.out.println("-------------------------------------");
    /
    *
    通过Dog类再创建一个狗
    */
    Dog dog1 = new Dog();
    dog1.name = “旺财”;
    dog1.height = 0.3;
    dog1.weight = 20;
    System.out.println(“狗的名字:”+dog1.name);
    System.out.println(“狗的体重:”+dog1.weight);
    System.out.println(“狗的身高:”+dog1.height);
    dog1.protectHome();
    dog1.sleep();
    }
    }

    在内存中创建对象:
    对象都是存储在堆中,然后在栈中存储局部变量,这个变量所存储的值就是想要的堆内存中的地址

    					dog
    
    
    					dog1
    

    当使用new 创建的两个对象时会开辟两个不同的内存空间所有他们是相互隔离的。

    					dog
    
    
    					dog1
    
    
    
    					dog2
    

    我们可以在栈内存中创建两个变量都指向都一个堆内存中的地址,所以其中一个变量修改了堆内存中的数据,另一个变量就会读取到修改后的数据。
    2.成员变量和局部变量
    1.局部变量
     局变量是定义在方法中或语句块中。
    如:public static void printArray(int [] array){
    int sum = 0;
    for(int i = 0; i < array.length; i++){
    sum + = i;
    }
    }
     作用范围:只限于所定义的大括号。
     存储的位置:存储在栈内存中。
     默认值:无,局部变量必须赋值。
     生命周期:所属的大括号结束就消失。

    2.成员变量(类的属性)
     成员变量是定义在类中,也可以叫类的属性。
     作用范围:在整个类中
     存储位置:堆内存
     默认值:有
     生命周期:由jvm通过垃圾回收机制来自动回收。
    3.匿名对象
    class Car{
    String color;
    double displacement;
    String brand;
    public void run(){
    System.out.println(brand+“车在跑”);
    }
    public void introduce(){
    System.out.println(“我是一款”+brand+“的排量是”+displacement+“L”+color+“的车”);
    }
    }

    class TestCar{
    public static void main(String[] args){
    //在堆内存中创建了一个car的对象,但是在栈内存中没有变量引用他。
    new Car().brand = “兰博基尼”;
    //又在内存中创建了一个匿名对象;
    new Car().color = “黄色”;
    new Car().introduce();
    }
    }

    匿名对象由于没有栈中的变量来引用,所以不就就会被回收掉,所以匿名对象是无意义的。

    4.面向对象的特征之封装
    程序是模拟生活,万物皆对象。
    目的:提高数据安全性,通过封装,可以实现对属性的访问权限控制,同时增加了程序的可维护性。
    封装:
    将属性私有化,使用private关键字完成属性私有化,这种属性只有本类能访问。
    我们一般对每一个私有属性提供公共public的set和get这种方法供外界来访问我们的私有属性。
    class Teacher{
    private String name;
    /**
    private 修饰的属性是私有属性,这个变量只有本类能访问,private也可以作用在方法上
    /
    private int age;
    private char gender;
    /
    *
    通过一个public方法来访问private的属性
    /
    public void setAge(int a){
    age = a;
    }
    public void setName(String n){
    name = n;
    }
    public void setGender(char g){
    gender = g;
    }
    /
    *
    通过public公共的方法来访问私有的属性
    */
    public String getName(){
    return name;
    }
    public int getAge(){
    return age;
    }
    public char getGender(){
    return gender;
    }
    public void teach(){
    System.out.println(name+“在讲课”);
    }
    public void introduce(){
    System.out.println(“我叫”+name+“性别”+gender+“年龄是”+age+“岁”);
    }
    }

    class TestTeacher{
    public static void main(String[] args){
    Teacher t = new Teacher();
    /*
    t.name = “任亮”;
    t.setAge(30);
    t.gender = ‘男’;
    */

    	t.setName("任亮");
    	t.setAge(30);
    	t.setGender('男');
    	t.introduce();
    	System.out.println(t.getName());
    	System.out.println(t.getAge());
    	System.out.println(t.getGender());		
    }
    

    }
    5.this关键字
    在每一个方法中都包含一个this关键字,代表调用当前调用方法的对象的自身。This在set方法中可以区分同名的变量,加this是成员变量,没有this就是局部变量。
    class Student{
    private int age;
    private String name;
    public void setAge(int age){
    //this.name是调用当前set方法的对象的引用
    this.age = age;
    }
    public int getAge(){
    return age;
    }
    public void setName(String name){
    //this.name是调用当前set方法的对象的引用
    this.name = name;
    }
    public String getName(){
    return name;
    }
    public void study(){
    //代表调用当前调用方法的对象的自身
    System.out.println(this);
    }
    public void introduce(){
    System.out.println(“我的名字是”+this.name+",年龄是"+this.age);
    }
    }
    class TestStudent{
    public static void main(String[] args){
    //创建学生对象
    Student student = new Student();
    //输出student对象在堆内存中的地址
    //Student@1dd3812
    //Student@1dd3812
    //System.out.println(student);
    //student.study();
    student.setAge(25);
    student.setName(“张三”);
    student.introduce();
    }
    }

    This关键字程序的内存结构流程
    栈 堆

    					student
    

    方法区

    第一步:运行java TestStudent时把TestStudent.class载入内存,main方法存储在方法区里面
    第二步:将TestStudent的main方法压入栈内存来执行main
    第三步:,先把Student.class载入到内存中,把方法存储在方法区中,在堆中创建一个Student对象,在栈中创建student的变量,把堆中对象的地址存储在student变量中。
    第四步:调用setAge方法,放setAge方法压栈,把调用setAge的student变量的地址给this,然后通过this给堆中Student的对象来赋值age,set方法执行完毕,setAge方法出栈。
    第五步:调用setName方法(和第四步同理).
    第六步:调用introduce方法,把introduce压栈,来执行introduce通过this输出name和age,然后introduce出栈。
    第七步:main方法出栈。
    6.构造器
    作用:创建对象,给对象赋初始值;
    构造器本身是一个方法:
    没有返回值,也没有void。
    构造器的方法名必须和类名一致
    在方法中定义要初始化的参数列表
    在构造器中通过this(…)可以来调用其他的构造器,而且this必须放在方法的第一行
    默认构造器,如果在类中没有带有参数的构造器,默认构造器是隐式存在的,如果类中定义了有参数的构造器,那么默认构造器就被覆盖了,如果想要使用默认构造器,只需要把它显示的定义出来即可。
    创建对象时使用new
    Static关键字和单例模式
    1.static关键字
    1.static关键字修饰在属性上
    1.语法
    语法:static数据类型 变量名
    使用static修饰的属性我们认为是类的属性,不带static修饰的属性我们认为是对象的属性。
    2.类属性访问
    类的属性访问:
    第一种方式:类名.类属性(推荐使用),
    第二种方式:对象实例.类属性
    3.应用场景
    应用的场景:我们把常量一般定义成static,或者当前类创建的每一个对象都有相同的属性也可以把这种属性定义成static的
    class Person{
    /**
    name和age都是对象属性
    /
    String name;
    int age;
    /
    *
    人的数量,类属性
    */
    static int personNum;
    //static String file_name = “struts.xml”
    public void introduce(){
    //通过对象实例来访问类属性
    System.out.println(“我叫”+this.name+“年龄是”+this.age+“编号”+this.personNum+“报到”);
    }
    }
    class StaticDemo{
    public static void main(String [] args){
    //创建一个person的实例
    Person p = new Person();
    //给人的数量加一
    Person.personNum++;
    p.name = “任亮”;
    p.age = 30;
    p.introduce();
    //创建一个person的实例
    Person p1 = new Person();
    //给人的数量加一
    Person.personNum++;
    p1.name = “鲁达”;
    p1.age = 30;
    p1.introduce();
    //通过类名来访问类的属性
    System.out.println(“当前人数:”+Person.personNum);
    //通过对象实例来访问类属性
    System.out.println(“当前人数:”+p.personNum);
    }
    }
    4.内存中的加载流程
    上述代码在内存中的流程

    栈内存 堆内存

    					p
    

    5.生命周期
    对象属性生命周期:创建对象的时候初始化对象属性(没有类属性早),当当前对象变成匿名对象时,jvm会回收该垃圾对象,对象属性随之消失。
    类属性的生命周期:当Person.class被载入内存时personNum类属性就初始化了,jvm关闭类属性就消失了
    2.static关键字修饰在方法上
    1.语法
    语法:public static 返回值(void) 方法名(数据类型1 变量1,数据类型2 变量2,….){
    方法体
    [return 结果]
    }

    Static修饰在方法上就是类方法。
    2.类方法的访问
    类方法访问:
    第一种方式:类名.类方法()推荐使用
    第二种方式:对象实例.类方法()
    3.类方法对属性的访问
     访问对象属性:
    类方法是无论是通过类访问还是通过对象访问都不能直接访问对象属性的
    class Demo{
    int num = 50;
    static int num1 = 100;
    //类方法
    public static void printNum(){
    //System.out.println(“我是一个静态方法”);
    System.out.println(num);
    }
    }

    类方法对类属性的访问:
    类方法对类属性的访问是可以的。
    注意:对象方法和属性只能通过对象来调用。
    类方法和类属性既可以通过类来调用也可以通过对象来调用。
    4.类方法应用场景:
    做工具类
    做数组的工具类
    class ArrayUtils{
    public static void sort(int [] array){
    for(int i = 0; i < array.length -1 ; i++){
    for(int j = 0; j < array.length - 1 -i; j++){
    if(array[j] < array[j+1]){
    int temp = array[j];
    array[j] = array[j+1];
    array[j+1] = temp;
    }
    }
    }
    }
    public static void printArray(int [] array){
    for(int i = 0; i < array.length; i++){
    System.out.print(array[i]+"\t");
    }
    }
    public static void main(String [] args){
    int [] array = {97,12,190, 4, 52,98};
    //ArrayUtils.printArray(array);
    //ArrayUtils.sort(array);
    System.out.println();
    //ArrayUtils.printArray(array);
    //在同一个类中可以不加类名去访问静态方法。如果是不同类之间来访问静态方法必须加类名
    printArray(array);
    sort(array);
    System.out.println();
    printArray(array);
    }
    }
    2.单例模式
    设计模式:一共有23种设计模式 设计模式就是有经验的前人通过实践总结下来被大家公认的代码设计思想。
    单例模式:这种模式只能产生一个对象。
    应用场景非常多:比如windows的任务管理器,回收站,java中数据库连接池,spring中bean的管理等等。
    1.单例模式的创建步骤
    (1)将默认的构造器私有化
    (2)在类中定义一个当前类的类型的静态属性,并且创建该当前类的对象。
    (3)提供一个静态的类方法来返回当前类的静态属性的对象。
    懒汉模式
    /**
    懒汉模式
    /
    class Singleton{
    private static Singleton s = new Singleton();
    /
    *
    创建私有构造器
    */
    private Singleton(){

    }
    /**
    	提供一个共外界来获得当前类的一个实例的类方法
    	注意:类方法所访问的类的属性一定是类属性
    */
    public static Singleton getInstance(){
    	return s;
    }
    

    }
    class TestSingleton{
    public static void main(String [] args){
    Singleton s = Singleton.getInstance();
    System.out.println(s);
    Singleton s1 = Singleton.getInstance();
    System.out.println(s1);
    }
    }
    饿汉模式
    /**
    饿汉模式
    /
    class Singleton1{
    private static Singleton1 s = null;
    /
    *
    创建私有构造器
    /
    private Singleton1(){
    }
    /
    *
    提供一个共外界来获得当前类的一个实例的类方法
    注意:类方法所访问的类的属性一定是类属性
    */
    public static Singleton1 getInstance(){
    if(s == null){
    s = new Singleton1();
    }
    return s;
    }
    }
    class TestSingleton1{
    public static void main(String [] args){
    Singleton1 s = Singleton1.getInstance();
    System.out.println(s);
    Singleton1 s1 = Singleton1.getInstance();
    System.out.println(s1);
    }
    }

    类的继承
    1.继承
    描述事物的时候,我们如果发现几个类有重复的属性和方法我们就可以采用继承的方式来设计。
    1.继承语法
    继承的语法:
    使用extends关键字来继承
    class 子类 extends 父类{
    子类属性
    子类方法
    }
    继承的特点:子类会把父类所有的属性和方法继承下来(暂时不考虑final)。

    2.细节
    1.如果父类中包含了某些类中的共同的属性和行为,我们可以使用继承来设计程序。
    2.子类使用extends关键字继承父类的共同属性以外,子类还需要有自己特有的属性或者方法。
    3.父类更通用,子类更具体。
    4.子类只能获得父类中的非private的属性,如果想要继承就得提供公共的set和get的方法。 私有的方法是无法继承下来的
    5.java中只能做单继承
    比如:A extends B{
    }
    6.java支持多级继承
    比如:
    A extends B{

    	}
    	C  extends B {
    	
    	}
    

    继承的好处:提高代码的复用性。
    3.继承的内存结构
    /**
    我们创建老师的父类
    */

    class Teacher{
    String name;
    int age;
    public void sleep(){
    System.out.println(this.name+“正在睡觉”);
    }
    }
    /**
    创建子类继承父类
    */
    class JavaTeacher extends Teacher{

    public void teachJava(){
    	System.out.println(this.name+ "正在教课java");
    }	
    

    }

    class PHPTeacher extends Teacher{
    public void teachPHP(){
    System.out.println(this.name+ “正在教课php”);
    }
    }
    class ExtendsDemo2{
    public static void main(String [] args){
    JavaTeacher jt = new JavaTeacher();
    //调用继承下来的set方法
    jt.name = “任亮”;
    jt.age = 30;
    //调用本身的teach方法
    jt.teachJava();
    //调用继承下来的sleep方法
    jt.sleep();
    }
    }
    内存中继承执行流程:
    栈 堆

    					jt
    

    方法区和数据共享区

    2.super关键字
    1.子类实例化的过程中父类的构造器先被调用,然后再调用子类的构造器
    2.子类通过构造器实例化时要调用父类的默认构造器,是隐含的调用了super()这个方法。但是如果子类的构造器中调用了父类中的有参数的构造器,那么无参数的构造器就不会被调用了。
    3.super()的调用必须要放在方法的第一行。
    4.super可以表示父类的引用,我们可以使用super和this来区分父类和子类中同名的属性。在子类中访问属性的查找顺序首先在子类中查找指定的属性名字,如果在子类中没有该属性,那么就去父类中去查找该属性。方法也是一样的当子类和父类有同样的方法时通过子类调用的这个相同的方法时调用的是子类的方法。但是我们可以通过super对父类的引用来调用父类的方法。
    This关键字
    1.代表当前类的引用
    2.可以区分同名的属性和局部变量
    3.通过this可以调用同类中的构造器(this(), this(参数列表))
    4.调用本类里面的属性, this.属性名,this.方法()
    3.方法的重写(override)
    在子类继承父类时,子类的方法和父类的方法相同(访问修饰限制符, 返回值类型, 方法名, 参数列表),方法体不同。这种子类的方法将父类的方法覆盖叫做重写。

    重写和重载的区别:
    重写(override):在父子类的继承中有相同的方法,唯一不同就是方法体,一般是父类的该方法满足不了子类的需求所以才发生重写。
    重载(overload):重载是在同一个类中,有着相同的方法名但是参数的数据类型或者参数的个数不同这两个方法就是重载。重载的目的:节省类中的命名资源和提高代码的可读性。
    4.final关键字
    1.修饰在方法上
    final修饰的方法不能被复写
    语法:
    权限修饰符 final 返回值类型 方法名(参数列表){
    方法体
    }

    class User{
    int username;
    int password;
    /**
    final修饰的方法不能被复写
    /
    public final void login(int username, int password){
    if(username == 111 && password == 111){
    System.out.println(“登录成功”);
    }else{
    System.out.println(“用户名或者密码错误”);
    }
    }
    }
    class Emp extends User{
    String realName;
    /

    final修饰的方法不能被复写
    public void login(int username, int password){
    System.out.println(“登录成功”);
    }
    */
    }
    class FinalDemo{
    public static void main(String [] args){
    Emp s = new Emp();
    s.login(111,111);
    }
    }

    2.修饰在属性上
    语法:
    权限修饰符 [static] final 数据类型 属性名 = 值;
    属性名:一般采用大写,多个单词使用下划线来分隔。而且这种常量多定义在接口中。

    class User{
    public static final int USERNAME = 111;
    int password;
    }
    class FinalDemo1{
    public static void main(String [] args){
    User.USERNAME = 222;
    }
    }

    3.修饰在类上
    语法 final class 类名{
    属性
    方法
    }
    final所修饰的类是不能被继承的。
    final class User{
    int username;
    int password;
    }
    class Emp extends User{
    String realName;

    public void login(int username, int password){
    	System.out.println("登录成功");
    }
    

    }
    class FinalDemo1{
    public static void main(String [] args){
    Emp s = new Emp();
    s.login(111,111);
    }
    }

    5.抽象类
    1.抽象方法概念
    当多个具体的实力类存在着共同的行为,但是有不同的表现,我们在父类继承过程中父类的方法具体实现不同确定,但是能确定的是他们都有这种行为。
    我们要把这种行为方法作为抽象方法。
    2.抽象语法
    public abtract [返回值][void] 方法名 (参数列表); 没有方法体。如果在一个类中存在一个方法,那么这个类一定是抽象类。这个类上也要有abstract标识,
    抽象类的语法:
    abstract class 类名{
    属性
    方法
    }
    注意:抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类

    3.抽象类的特点
    1.抽象类不能被实例化。

    2.抽象类必须被子类继承才能使用子类实例化。
    3.继承了抽象类的非抽象类必须实现抽象类的所有抽象方法。

    4.抽象类也可以继承抽象类,这样不需要实现父抽象类的方法。

    5.抽象类的抽象方法不能和private,final, static共存。
    private 错误

    final错误

    static错误

    接口和多态
    1.接口
    什么是接口:当一个抽象类,如果抽象类中的所有方法都是抽象的,那么我们就可以把它定义为一个接口,接口是对行为的抽象。类是对属性和行为的抽象。
    1.语法
    interface 接口名{
    方法定的定义;
    ….
    }
    2.接口的特征
    1.接口中的方法的定义不需要Abstract来修饰,默认就是抽象的
    2.接口是不可以实例化的,需要有类来实现接口

    实现接口的语法:
    class 类名	implements 接口名,接口名,…{
    	//实现每一个接口中的方法
    }
    实现了接口的类必须实现接口中的所有方法,接口实现类的方法的权限限制修饰符一定要大于等于接口的(实现类中建议都使用public)
    

    3.接口中的方法不能和private,static和final共存
    4.在接口中可以定义属性,可以通过接口的实现类的实例来访问,还可以通过接口名来访问(推荐大家使用),接口中的属性不能修改,我们接口中的属性默认都是final static 的,通常在接口中来定义属性把它作为常量,常量的名字规范是单词大写,而且多个单词之间用下划线来分隔。比如:FILE_PATH
    5.接口可以继承接口(单继承)
    interface A{
    public void method();
    }
    interface B extends A{
    }
    6.接口可以多实现
    interface A{
    public void method();
    }
    interface A1{

    public void method();	
    

    }
    interface B extends A{
    }
    class Demo implements B{
    public void method(){
    }
    }
    class Demo1 implements A,A1{
    public void method(){
    }
    }
    3.接口应用
    范例:使用接口方式计算圆和正方形的面积和周长。
    interface CalInterface{
    /*
    定义圆周率
    /
    public static final float PI = 3.14f;
    /

    *定义计算面积的方法
    /
    public float getArea(float r);
    /

    *定义计算周长的方法
    */
    public float getLength(float r);
    }

    /*
    创建一个圆的类实现计算的接口
    /
    class Circle implements CalInterface{
    public float getArea(float r){
    return PI
    r
    r;
    }
    public float getLength(float r){
    return 2PIr;
    }
    }
    /*
    创建一个正方形的类实现计算的接口
    /
    class Zfx implements CalInterface{
    public float getArea(float r){
    return r
    r;
    }
    public float getLength(float r){
    return 4
    r;
    }
    }
    class InterDemo3{
    public static void main(String [] args){
    /*
    Circle circle = new Circle();
    float area = circle.getArea(3f);
    float length = circle.getLength(3f);
    System.out.println(“半径是3的圆的面积是:”+area);
    System.out.println(“半径是3的圆的周长是:”+length);
    */
    Zfx z = new Zfx();
    float area = z.getArea(5f);
    float length = z.getLength(5f);
    System.out.println(“边长是5的正方形的面积是:”+area);
    System.out.println(“边长是5的正方形的周长是:”+length);
    }
    }
    使用接口的好处:

    1. 接口定义的是一种标准,可以使我们的代码分层开发,分模块开发。
    2. 降低代码的耦合度,提高代码的可扩展性和可维护性
    3. 接口改进了单继承的局限。
      接口和抽象类的区别:
      1.接口的所有方法都是抽象的,抽象类里面的方法可以是抽象的也可以是不抽象的。
      2.接口和抽象类都不能实例化,接口需要类来实现后实例化实现类,抽象类需要类来继承然后实例化子类。
      3.抽象类智能单继承,接口也可以单继承接口,接口还可以多实现。
      4.接口中的属性是static final类型的,抽象类中的属性跟普通类中的属性没有区别。
      5.接口中的方法默认就是抽象的不需要加absract,抽象类中的抽象方法需要加Abstract关键字。
      2.多态
      1.概述
      多态就是事物具有表现多种功能的能力。
      class Teacher{
      String name;
      /**
      • 父类提供一个空实现的方法
        /
        public void teachLession(){
        }
        }
        /
        *
    • 创建JavaTeacher
      /
      class JavaTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲java多态”);
      }
      }
      /
      *
    • 创建NetTeacher
      /
      class NetTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲.Net基本语法”);
      }
      }
      class TestTeacher{
      public static void main(String [] args){
      JavaTeacher jt = new JavaTeacher();
      jt.name = “任亮”;
      jt.teachLession();
      NetTeacher nt = new NetTeacher();
      nt.name = “张三”;
      nt.teachLession();
      }
      }
      1.继承多态
      我们通常使用抽象类来抽象要使用多态的方法
      abstract class Teacher{
      String name;
      /
      *
      • 父类提供一个抽象方法让子类以多态形式体现
        /
        public abstract void teachLession();
        /
        *
      • 父类提供一个普通的共性的方法给每一个子类使用
        /
        public void sleep(){
        System.out.println(name + “在睡觉”);
        }
        }
        /
        *
    • 创建JavaTeacher
      /
      class JavaTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲java多态”);
      }
      }
      /
      *
    • 创建NetTeacher
      */
      class NetTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲.Net基本语法”);
      }
      }
      class TestTeacher1{
      public static void main(String [] args){
      JavaTeacher jt = new JavaTeacher();
      jt.name = “任亮”;
      //jt.teachLession();
      jt.sleep();
      NetTeacher nt = new NetTeacher();
      nt.name = “张三”;
      //nt.teachLession();
      nt.sleep();
      }
      }
      特点:
      1.必须要有继承关系,在抽象类中可以定义多态的抽象方法,通过子类来继承这个抽象类然后复写抽象类中的抽象方法以达到多态的效果。
      2.多态子类的实例可以赋给父类的引用

    abstract class Teacher{
    String name;
    /**
    * 父类提供一个抽象方法让子类以多态形式体现
    /
    public abstract void teachLession();
    /
    *
    * 父类提供一个普通的共性的方法给每一个子类使用
    /
    public void sleep(){
    System.out.println(name + “在睡觉”);
    }
    }
    /
    *

    • 创建JavaTeacher
      /
      class JavaTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲java多态”);
      }
      }
      /
      *
    • 创建NetTeacher
      /
      class NetTeacher extends Teacher{
      public void teachLession(){
      System.out.println(name+“在讲.Net基本语法”);
      }
      }
      /
      *
      *创建领导类

    class Leader{
    //如果存在着多个学科的老师,就要求领导类中有多个学科老师考察的方法
    public void checkJavaTeacher(JavaTeacher jt){
    System.out.println(“考察开始”);
    jt.teachLession();
    System.out.println(“考察结束”);
    }
    public void checkNetTeacher(NetTeacher nt){
    System.out.println(“考察开始”);
    nt.teachLession();
    System.out.println(“考察结束”);
    }
    }
    /
    class Leader{
    /
    *
    * 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
    /
    public void checkTeacher(Teacher t){
    System.out.println(“考察开始”);
    t.teachLession();
    System.out.println(“考察结束”);
    }
    }
    class TestTeacher2{
    public static void main(String [] args){
    /

    JavaTeacher jt = new JavaTeacher();
    jt.name = “任亮”;
    jt.teachLession();
    NetTeacher nt = new NetTeacher();
    nt.name = “张三”;
    nt.teachLession();
    /
    //子类可以转换为父类,把子类的实例赋给父类的引用
    /

    Teacher jt = new JavaTeacher();
    jt.name = “任亮”;
    jt.teachLession();
    Teacher nt = new NetTeacher();
    nt.name = “张三”;
    nt.teachLession();
    /
    JavaTeacher jt = new JavaTeacher();
    jt.name = “任亮”;
    NetTeacher nt = new NetTeacher();
    nt.name = “张三”;
    Leader leader = new Leader();
    //考察java老师
    /

    leader.checkJavaTeacher(jt);
    leader.checkNetTeacher(nt);
    */
    leader.checkTeacher(jt);
    leader.checkTeacher(nt);
    }
    }
    内存结构
    栈 堆

    						 leader
    
    						 nt
    
    						 jt
    

    方法区和数据共享区

    3.我们可以通过instanceof来判断当前父类的引用的实例是什么类型
    class Leader{
    /**
    * 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
    /
    public void checkTeacher(Teacher t){
    String teacher = null;
    if(t instanceof JavaTeacher){
    teacher = “java老师”;
    }else{
    teacher = “.Net老师”;
    }
    System.out.println(teacher + “考察开始”);
    t.teachLession();
    System.out.println(teacher +“考察结束”);
    }
    }
    2.接口多态
    接口的多态基本上和类的继承的多态一致:不同的是类的继承使用的是继承关系实现多态,接口采用实现的方式实现多态。
    interface Teach{
    /
    *
    * 父类提供一个抽象方法让子类以多态形式体现
    /
    public void teachLession();
    }
    /
    *

    • 创建JavaTeacher
      /
      class JavaTeacher implements Teach{
      String name;
      public void teachLession(){
      System.out.println(name+“在讲java多态”);
      }
      }
      /
      *
    • 创建NetTeacher
      /
      class NetTeacher implements Teach{
      String name;
      public void teachLession(){
      System.out.println(name+“在讲.Net基本语法”);
      }
      }
      class Leader{
      /
      *
      • 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
        */
        public void checkTeacher(Teach t){
        String teacher = null;
        if(t instanceof JavaTeacher){
        teacher = “java老师”;
        }else{
        teacher = “.Net老师”;
        }
        System.out.println(teacher + “考察开始”);
        t.teachLession();
        System.out.println(teacher +“考察结束”);
        }

    }
    class TestTeacher4{
    public static void main(String [] args){
    JavaTeacher jt = new JavaTeacher();
    jt.name = “任亮”;
    NetTeacher nt = new NetTeacher();
    nt.name = “张三”;
    Leader leader = new Leader();
    leader.checkTeacher(jt);
    leader.checkTeacher(nt);
    }
    }
    3.模板模式
    第一种角色:抽象模板
    定义三种方法:第一个抽象方法需要子类去实现,子类必须实现
    第二个扩展方法,是一个空方法,子类可以去复写也可以不复写
    第三个私有的最终方法,不可复写的
    第四个模板方法,这个方法中定义了每一个方法的执行顺序和逻辑
    第二种角色:具体模板要继承抽象模板
    需要实现抽象模板中的抽象方法,可以扩展抽象模板中的扩展方法。
    理论代码:

    /**

    • 抽象模板
      /
      abstract class AbstractTemplate{
      /
      *
      在抽象模板中定义一个抽象方法,这个方法是为了让子类去实现
      /
      public abstract void abstractMethod();
      /

      定义一个回调方法,用于扩展
      /
      public void hookMethod(){
      }
      /
      • 定义抽象模板中的子类不可修改的方法
        /
        private final void concrateMehtod(){
        System.out.println(“不变而且是必须的业务逻辑”);
        }
        /
        *
      • 模板方法
        /
        public void templateMehtod(){
        abstractMethod();
        hookMethod();
        concrateMehtod();
        }
        }
        /
        *
    • 定义具体模板
      */
      class ConcrateTemplate extends AbstractTemplate{
      public void abstractMethod(){
      //写业务方法
      System.out.println(“子类的具体业务逻辑”);
      }
      public void hookMethod(){
      //扩展代码
      System.out.println(“业务逻辑扩展”);
      }
      }
      class TemplateTest{
      public static void main(String [] args){
      ConcrateTemplate ct = new ConcrateTemplate();
      ct.templateMehtod();
      }
      }

    范例:计算程序的执行时间。
    /**

    • 抽象模板
      /
      abstract class CalTimeTemplate{
      /
      *
      在抽象模板中定义一个抽象方法,这个方法是为了让子类去实现
      /
      public abstract void doJob();
      /

      定义一个回调方法,用于扩展
      /
      public void expandMethod(){
      System.out.println(“运行开始”);
      }
      /
      • 定义抽象模板中的子类不可修改的方法
        /
        private final long getCurrentTime(){
        return System.currentTimeMillis();
        }
        /
        *
      • 模板方法
        /
        public long templateMehtod(){
        expandMethod();
        //获得当前时间的毫秒数
        long startTime = getCurrentTime();
        doJob();
        //获得当前时间的毫秒数
        long endTime= getCurrentTime();
        return endTime - startTime;
        }
        }
        /
        *
    • 定义具体模板
      */
      class ConcrateTemplate extends CalTimeTemplate{
      public void doJob(){
      for(int i = 0; i < 5; i++){
      System.out.println(“正在执行”);
      }
      }
      }
      class TemplateTest1{
      public static void main(String [] args){
      ConcrateTemplate ct = new ConcrateTemplate();
      long times = ct.templateMehtod();
      System.out.println(“程序执行了”+times+“毫秒”);
      }
      }

    JAVASE
    1.API的使用
    Api是我们写代码的帮助文档。后续要接触很多第三方的技术,他们都会给我们提供api,我们就必须会读懂。Jdk也给我们提供了帮助文档。
    通过索引的方式来根据类名来查找类的api信息

    (1)看包,如果是java.lang下的类,写代码的时候我们不用引入包。

    (2)看这个指定类是具体类,抽象类,接口,并且关注开始的版本号。

    (3)属性和构造器

    (4)方法

    再看从父类所继承下来的方法

    1.Math类
    class MathDemo{
    public static void main(String [] args){
    //Math类中的属性
    System.out.println(“自然对数:”+Math.E);
    System.out.println(“圆周率:”+Math.PI);
    //Math类中的方法
    System.out.println(“绝对值:”+Math.abs(-1.5));
    //把小数去掉整数加1
    System.out.println(“ceil结果:”+Math.ceil(12.1));
    //把小数位舍弃
    System.out.println(“floor结果:”+Math.floor(12.9));
    //比较两个数的大小
    System.out.println(“大的数是:”+Math.max(12.9, 27));
    //比较两个数的大小
    System.out.println(“小的数是:”+Math.min(12.9, 27));
    //计算某个数的n次幂
    System.out.println(“n次方是:”+Math.pow(3, 3));
    //四舍五入
    System.out.println(“四舍五入的结果是:”+Math.round(4.5));
    //开平方
    System.out.println(“16开平方是:”+Math.sqrt(16));
    //获得从0到1的随机数包括0,不包括1
    for(int i = 0 ; i < 10; i++){
    System.out.println(“随机数:”+Math.random());
    }
    for(int i = 0 ; i < 10; i++){
    System.out.println(“1-100之间随机整数数:”+(int)Math.floor(Math.random()*100));
    }
    }
    }
    2.Scanner
    第一步:导入Scanner,语法:import java.util.Scanner
    第二步:创建对象

    第三步:使用功能
    调用int nextInt(),等待我们从键盘输入一个数值。
    2.内部类
    1.内部类简单使用
    类内部的类就是内部类。
    位置:把一个类定义到另一个类中,那么内部的类就是内部类。
    注意:内部类不能直接创建
    创建内部类的语法:
    外部类.内部类 变量名 = new 外部类对象.new内部类对象
    内部类的外部类的方法如果想要访问内部类的方法,必须创建内部类的对象,根据内部类的对象来访问。
    class Outer{
    private int num = 10;
    //内部类的定义
    class Inner{
    public void show(){
    System.out.println(“我是内部类”);
    System.out.println(“num:”+num);
    }
    }
    /*
    创建外部类的方法
    /
    public void method(){
    //在外部类内部创建内部类对象
    Inner inner = new Inner();
    inner.show();
    }
    }
    class OutDemo{
    public static void main(String [] args){
    //内部类不能直接创建
    //Inner inner = new Inner();
    //inner.show();
    //创建内部类
    //Outer.Inner inner = new Outer().new Inner();
    //inner.show();
    Outer outer = new Outer();
    outer.method();
    }
    }
    2.内部类被private来修饰
    被private修饰的内部类只能在它所属的外部类中访问
    class Outer{
    private int num = 10;
    public int getNum(){
    return num;
    }
    public void setNum(int num){
    this.num = num;
    }
    //内部类的定义
    private class Inner{
    public void show(){
    System.out.println(“我是内部类”);
    System.out.println(“num:”+num);
    }
    }
    /

    * 对内部类的封装,给其他的外部类提供接口来访问Inner内的方法
    /
    public void method(){
    Inner inner = new Inner();
    inner.show();
    }
    }
    class OutDemo1{
    public static void main(String [] args){
    //被private修饰的内部类只能在它所属的外部类中访问
    //Outer.Inner inner = new Outer().new Inner();
    Outer outer = new Outer();
    outer.setNum(12);
    System.out.println(outer.getNum());
    outer.method();
    }
    }
    3.静态内部类
    静态内部类的创建语法:
    外部类名.内部类名 变量名 = new 外部类名.内部类对象
    class Outer{
    private static int num = 10;
    /
    *
    定义静态内部类,它只能访问它的外部类的静态属性和静态方法
    /
    static class Inner{
    public void show(){
    System.out.println(“num:”+num);
    //System.out.println(“我是内部类”);
    }
    /

    * 静态类中创建静态方法
    */
    public static void show2(){
    System.out.println(“num:”+num);
    }
    }
    }
    class OutDemo2{
    public static void main(String [] args){
    //Outer.Inner inner = new Outer().new Inner();
    //静态内部类对象创建
    Outer.Inner inner = new Outer.Inner();
    //根据内部类的对象来访问内部类的对象方法
    inner.show();
    //根据内部类的对象来访问内部类中的静态方法
    inner.show2();
    //根据类名来访问静态类中的静态方法
    Outer.Inner.show2();
    }
    }
    4.局部内部类(了解)
    把内部类定义到方法中,局部内部类
    class Outer{
    private static int num = 10;
    public void show(){
    //把内部类定义到方法中,局部内部类
    class Inner{
    public void method(){
    System.out.println(“num:” +num);
    }
    }
    //创建局部内部类的对象
    Inner inner = new Inner();
    //调用局部内部类的方法
    inner.method();
    }
    }
    class OutDemo3{
    public static void main(String [] args){
    Outer outer = new Outer();
    outer.show();
    }
    }
    5.匿名内部类
    什么是匿名类:没有名字的类,这种类需要在接口上实现。
    匿名类和匿名内部类都需要接口或者抽象类的支持。
    创建一个匿名的类的对象这个类的对象实现OuterInter的接口,在大括号中实现接口中的方法,方法调用完毕后就会被垃圾回收
    interface OuterInter{
    public void show();
    }
    class OutDemo4{
    public static void main(String [] args){
    //创建一个匿名的类的对象这个类的对象实现OuterInter的接口,在大括号中实现接口中的方法,方法调用完毕后就会被垃圾回收
    new OuterInter(){
    public void show(){
    System.out.println(“show something”);
    }
    }.show();
    //匿名类适合一次性的使用
    OuterInter oi = new OuterInter(){
    public void show(){
    System.out.println(“show something”);
    }
    };
    oi.show();
    }
    }
    匿名内部类
    interface OuterInter{
    public void show();
    }
    class Outer{
    public void method(){
    //创建匿名内部类的对象
    new OuterInter(){
    public void show(){
    System.out.println(“我是匿名内部类”);
    }
    }.show();
    //创建一个匿名内部类的对象,并且把这个对象赋给接口
    OuterInter oi = new OuterInter(){ //多态
    public void show(){
    System.out.println(“我是匿名内部类1”);
    }
    };
    oi.show();
    }
    }
    class OutDemo5{
    public static void main(String [] args){
    Outer outer = new Outer();
    outer.method();

    } 
    

    }
    3.包的使用
    1.包的定义
    包:就是文件夹
    作用:对类做分类管理,可以区分同名不同包的类。
    语法: package 表名(不同级别用“.”来分隔);,如 package com.rl;, 位置放置文件的有效代码第一行(注释不算)
    如何编译:
    Javac –d . 类文件

    运行:
    在类的编译的目录下使用 java 包名.类名

    2.类和类之间的访问
     同一个包下的类的访问。
    当前类在编译的时候它所关联的类也会被编译
    在同一包下的两个类可以直接访问
    ArrayTools
    class ArrayTools{
    public void show(){
    System.out.println(“我是一个show”);
    }
    }

    ArrayTest.java
    class ArrayTest{
    public static void main(String[] args){
    //我们发现当前的文件中没有ArrayTools
    //当前类在编译的时候它所关联的类也会被编译
    //在同一包下的两个类可以直接访问
    ArrayTools at = new ArrayTools();
    at.show();
    }
    }
     不同包下的类如何访问
    1.方式1:访问不同包的类在类前面加上包的全路径:如com.rl.array.ArrayTools1, 这种情况我们必须先编译com.rl.array.ArrayTools1才能编译当前ArrayTest1.
    2.方式2:在使用某个包下的类时需要引入这个包的类,语法:import 包名.类名;这行代码放在package包代码行的下面,class代码行的上面

    package com.rl.test;
    //import com.rl.array.ArrayTools1;//引入com.rl.array.ArrayTools1这个类
    import com.rl.array.*;//引入com.rl.array包下的所有类
    class ArrayTest2{
    public static void main(String[] args){
    //在使用的类的前面加上包的路径
    //这种情况我们必须先编译com.rl.array.ArrayTools1才能编译当前ArrayTest1
    ArrayTools1 at = new ArrayTools1();
    at.show();
    }
    }
    4.访问权限的修饰符
    1.权限修饰符可以作用在哪些概念上
    访问权限的修饰符一共有四种:private, 默认, protected, public
    private 默认 protected public
    类(非内部类) N Y N Y
    方法 Y Y Y Y
    属性 Y Y Y Y
    在类上如果同public来修饰,那么这个类可以被任何类所访问。类如果是默认修饰在本类中可以访问,在同一个包下的类可以访问。其余都不可以访问。
    2.权限修饰符对方法和属性的控制

    同类中	同一个包下	不同包子类	不同包无关类
    

    private Y N N N
    默认 Y Y N N
    protected Y Y Y N
    public Y Y Y Y
    我们通常情况:类我们一般设置成public的,属性一般都是private, 方法一般都是public的,也有少数使用(protect,private)
    5.Object类
    1.Object概述
    Object是所有类的根类,所有的类都是直接或者间接的去继承Object类。
    类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

    /**

    • Object的类是Student隐藏着继承的
      */
      public class Student{ //extends Object{
      private String name;
      private int age;
      public Student(){
      super();
      }
      public Student(String name, int age){
      this.name = name;
      this.age = age;
      }
      public void setName(String name){
      this.name = name;
      }
      public String getName(){
      return this.name;
      }
      public void setAge(int age){
      this.age = age;
      }
      public int getAge(){
      return this.age;
      }
      }
      class StudentDemo{
      public static void main(String[] args){
      Student s = new Student();
      System.out.println(s);//打印对象的时候,底层输出的其实是调用toString方法。
      System.out.println(s.toString());
      }
      }
      2.方法的讲解
      1.toString()方法:
      返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
      Object中的toString的实现
      Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
      获得类的名称 “@”

    getClass().getName() + ‘@’ + Integer.toHexString(hashCode())

    /**

    • Object的类是Student隐藏着继承的
      */
      public class Student1{ //extends Object{
      private String name;
      private int age;
      public Student1(){
      super();
      }
      public Student1(String name, int age){
      this.name = name;
      this.age = age;
      }
      public void setName(String name){
      this.name = name;
      }
      public String getName(){
      return this.name;
      }
      public void setAge(int age){
      this.age = age;
      }
      public int getAge(){
      return this.age;
      }
      }
      class StudentDemo1{
      public static void main(String[] args){
      Student1 s = new Student1();
      System.out.println(“获得当前对象的类名:”+s.getClass().getName());
      System.out.println(“获得当前对象的十进制哈希值:”+s.hashCode());
      System.out.println(“获得当前对象的十六进制哈希值:”+Integer.toHexString(s.hashCode()));
      System.out.println(s);//打印对象的时候,底层输出的其实是调用toString方法。
      System.out.println(s.toString());
      }
      }

    2.getClass()
    getClass()返回值是Class(类的类对象),这边的知识点我们会在反射中详细讲解。通过getClass().getName()获得对象的类名。
    3.hashCode()
    由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。
    4. finalize()
    用于垃圾回收,我们不用手动的去调用,由jvm来调用,
    当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
    面试题:
    final,finally,finalize的区别?
    5. public boolean equals(Object obj)
    equals用于比较两个对象是否相等
    /**

    • Object的类是Student隐藏着继承的
      /
      public class Student2{ //extends Object{
      private String name;
      private int age;
      public Student2(){
      super();
      }
      public Student2(String name, int age){
      this.name = name;
      this.age = age;
      }
      public void setName(String name){
      this.name = name;
      }
      public String getName(){
      return this.name;
      }
      public void setAge(int age){
      this.age = age;
      }
      public int getAge(){
      return this.age;
      }
      /

      public String toString(){
      return “name :”+this.name+ " age:"+this.age;
      }
      /
      /
      *

      • 重写equals方法,我们认为所有的属性相等两个对象就相等
        */
        public boolean equals(Object obj){
        //判断传递过来的对象实例是否是Student2的类的对象
        if(!(obj instanceof Student2)){
        return false;
        }
        Student2 s = (Student2)obj;
        if(this.name.equals(s.name) && this.age == s.age){
        return true;
        }else{
        return false;
        }
        }
        //我们建议大家重写hashCode
        public int hashCode(){
        return 1;
        }
        }
        class StudentDemo2{
        public static void main(String[] args){
        Student2 s = new Student2();
        s.setName(“任亮”);
        s.setAge(30);
        Student2 s1 = new Student2();
        s1.setName(“任亮”);
        s1.setAge(30);

        //equals的参数类型是Object但是我们传递的是Student2,多态的应用
        System.out.println(“s和s1是否相等:”+s.equals(s1));
        Demo d = new Demo();
        System.out.println(s.equals(d));
        }
        /*
        public boolean equals(Object obj) {
        return (this == obj);
        }
        */
        }
        class Demo{
        }
        eclipse的使用和异常处理

      (1)视图,视窗
      当前是JavaEE视图

      (2)视图就是某些视窗的组合。
      A:Java视图
      B:Debug视图
      C:JavaEE视图
      (3)视图还原
      在视图操作中,我有可能有误操作。这个时候怎么办?
      Window–Reset重置视图

      (4)Package Explorer 包资源管理器(重点)

       A:该视图中显示当前工作空间中的所有项目以及项目中的文件。
          但不显示项目下bin目录中的运行文件。
       B:可以直接在该视图中创建项目,包,类,接口等。
      

      (5)Outline 大纲视窗

       A:该视图中显示当前代码视图中源文件中定义的类或者接口。
          以及定义的所有成员。
       B:当代码过长时,查找代码中的某一个类或者成员,在该视窗中
          是最方便的。
       C:在代码中出现多次的名称要同一更改,也可以在该视窗中完成。
          同时其他代码如果使用了该变量,那么也会一并改变。
      

      (6)Console 控制台视窗

       A:用于显示程序的运行结果,相当于DOS命令。
       B:如果有多个控制台同时运行。比如:服务器端和客户端。
          可以通过控制台上的小屏幕按钮进行控制台的切换。
       C:通过点击小方框,进行控制台的强制停止,相当于DOS中的Ctrl+C。
      

      (7)Hierarchy 层次视窗
      A:用于显示类之间的层次(继承)关系。
      B:在当前类上,按F4就可以切换到该视窗,并查看层次关系。
      查看原码,当前类上F3,或者Ctrl+鼠标点击

    3.对工作空间进行基本配置
    注意:在工作空间的设置对于该空间中的所有项目都有效。
    更换了工作空间,需要重新设置。
    (1)配置Java的编译和运行环境版本

    	windows--perference-Java
    				|--Compiler 设置成5.0以上,要和运行环境版本一致。
    				|--Installed JREs:可以指定多个jre环境,但是仅有一个是当前执行的。
    						   要和编译器一致,或者高于编译器版本。
    	如果采用高版本编译,用低版本jre运行,会出现异常。
    (2)代码视窗加上行号。
    	A:首选项--常规--编辑器--文本编辑器
    	B:在当前类中,左侧,右键。Show Line Numbers
    (3)调整字体
    	windows--perference-General--Appearance--Color and Fonts
    	右边选择Java。编辑即可。
    	字体选择 Courier New 比较标准,个人爱好
     
    (4)取消默认注释
    	在首选项设置面板中
    	Java--Code Style--Code Templates
    	右边选择Code,将不希望出现默认注释的代码块中的注释去掉。
    

    4.常用的提高开发效率的操作
    (1)创建面板 定义类和接口,权限,父类已经实现的接口等。

    syso:然后alt+/就能出现输出语句
    main:然后alt+/就能出主方法
    (2)常用的快捷键 (A,E,F必须掌握)
    	A:alt+/ 内容辅助键 这个功能很酷啊.
    		补充类或者接口名,帮我们起变量名,new 后面直接提示等。
    	B:ctrl+/ 单行注释,在按一次,取消单行注释
    	C:ctrl+shift+/ 对选中的区域进行多行注释的封装
    	D:ctrl+shift+\ 用于取消多行注释,只要光标在多行注释中即可
    	E:ctrl+shift+o 对使用了其他包中的类或者接口进行自动导入,也可以消除没有引用的包。
    	F:ctrl+shift+f 对代码进行格式化
    	G:alt+上键 向上移动当前行或者选中行
    	H:alt+下键 向下移动当前行或者选中行
    	I:ctrl+d 删除当前行,或者删除选中行
    	J:ctrl+shift+x 将选中部分的字母大写
    	K:ctrl+shift+y 将选中部分的字母小写
    	L:ctrl+1 光标放在编译中出现红色波浪线提示的内容上,
    	   在该快捷键可以获取建议的处理方式
    	M:F3 可以查看类或者方法的源码,前提是,该原码已经关联。
    	N: Ctrl + Alt + 下键 拷贝一行
    

    5.代码生成的快捷键
    出现source
    1:在区域中右键
    2:alt+shift+s
    (1)私有字段的get/set 重点
    (2)构造方法
    (3)重写父类方法 重点
    @Override 注解 表明此方法是重写父类的.
    (4)添加注释 /** 回车
    6.Debug 调试程序(重点)

    注释找错误
    输出打印调试程序
    
    程序不是写出来的,是改出来的.
    
    (1)让我们调试程序更加方便
    (2)想要调试,需要在程序中加入断点
    (3)运行debug as,打开debug视图
    (4)快捷键
    	f5:跳入
    	f6:跳过
    	f7:跳出
    	drop to frame 调到方法的第一行
    (5)清除断点
    	在Breakpoints视窗中清除指定断点或者所有断点。
    

    7.包的管理
    1:打jar包。
    选中项目–右键–Export–Java–jar–next–自己写jar包的名字和选择路径–finish.
    2:jar包的使用。
    导入jar包
    1:单独添加jar,
    把jar复制,然后粘贴到项目路径下
    一定要把jar添加至classpath路径中.
    怎么添加呢?
    直接把依赖包拷贝到我们的项目的src下,然后右键jar包add BuildPath
    如果删除,首先remove BuildPath再删除src下的jar
    8.导入已有的项目

    1. 空白区域–右键–import–General–Existing Project into Workspace–选中你的项目目录–finish—OK

    2. 删除项目中有两种。
      选中和不选中删除硬盘上的项目.

      请不要选中删除硬盘上的项目。

    9.异常
    在我们写程序的时候难免会出现错误,java中的异常机制为了提高我们程序的健壮性和容错性而存在。
    1.异常体系
    Throwable:Throwable 类是 Java 语言中所有错误或异常的超类。

    1.错误
    Error是throwable的子类,他是程序出现了严重的问题,这种问题程序解决不了。
    如:因为内存溢出或没有可用的内存提供给垃圾回收器时,Java 虚拟机无法分配一个对象,这时抛出该异常。
    错误都是以Error为结尾
    package com.rl.exception;
    public class ExceptionDemo {
    public static void main(String[] args) {
    //发生java.lang.OutOfMemoryError错误,是因为jvm的内存不足了
    int [] array = new int[102410241024];
    }
    }
    输出:
    Exception in thread “main” java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at com.rl.exception.ExceptionDemo.main(ExceptionDemo.java:7)

    2.异常
    Exception

    异常都是以Exception为结尾。
    1.编译期异常
    编译期的异常我们必须处理,如果不处理就会编译失败。
    我们两种解决方案:抛出异常,把异常抛给调用当前方法的层
    内部处理,catch来处理

    除了RuntimeException都是编译期的异常。
    2.运行时异常
    编译的时候没有异常,但是程序执行过程中产出的异常就是运行时异常。这种异常我们需要通过程序来容错提高代码的健壮性。

    package com.rl.exception;
    public class ExceptionDemo1 {
    public static void main(String[] args) {
    int a = 20;
    //抛出java.lang.ArithmeticException:
    int b = 0;
    System.out.println(a/b);
    }
    }
    输出:
    Exception in thread “main” java.lang.ArithmeticException: / by zero
    at com.rl.exception.ExceptionDemo1.main(ExceptionDemo1.java:8)

    2.异常处理
    1.运行时异常处理
    第一种方式是自行处理
    我们通过
    try{
    有可能发生运行时异常的代码
    }catch(异常对象){
    //处理或者向外抛出
    }finally{
    释放资源
    }
    上述代码可以如下组合:
    (1)try ……catch
    (2)try….finally
    (3)try…catch…catch
    (4) try…catch…catch…finally
     Try…catch
    我们通过try…catch来自己处理异常,那么程序就会走到catch代码块,处理完毕后程序会继续执行。
    package com.rl.exception;
    public class ExceptionDemo2 {
    public static void main(String[] args) {
    int a = 20;
    int b = 0;
    try{
    //可以能发生运行时异常的代码
    System.out.print(a/b);
    //如果发生异常ArithmeticException就捕捉到它
    }catch(ArithmeticException e){
    //处理异常的代码
    System.out.println(“被0整除了”);
    }
    System.out.println(“ccc”);
    }
    /public static void divide(int a, int b){
    System.out.print(a/b);
    }
    /
    }

    异常中的方法:
    public String getMessage() 返回此 throwable 的详细消息字符串。
    public String toString() 返回此 throwable 的简短描述。结果是以下字符串的串联
    public void printStackTrace()打印出异常的详细信息。
     try…catch…catch

    package com.rl.exception;
    public class ExceptionDemo4 {
    public static void main(String[] args) {
    int a = 20;
    int b = 0;
    int [] array = {1,2,3};
    /try{
    System.out.println(a/b);
    System.out.println(array[2]);
    }catch(ArithmeticException e){
    System.out.println(“被0除”);
    }catch(ArrayIndexOutOfBoundsException ae){
    System.out.println(“数组越界了,请检查数组长度”);
    }
    /
    try{
    System.out.println(a/b);
    System.out.println(array[3]);
    }catch(RuntimeException e){
    //e.printStackTrace();
    if(e instanceof ArrayIndexOutOfBoundsException){
    System.out.println(“数组越界异常”);
    }else{
    System.out.println(“被0除”);
    }
    }
    System.out.println(“ccc”);
    }
    }

    第二种向上抛出
    如果被调用的方法发生了运行时的异常,那么如果被调用的方法不去处理(不try…catch)jvm默认就会把这个运行时的异常抛到上一层,上一层函数可以对这个异常来处理,如果上一层函数依然没办法处理那么就不处理,就会接着向上抛出,总有一层方法会处理它。
    package com.rl.exception;
    public class ExceptionDemo3 {
    public static void main(String[] args) {
    int a = 20;
    int b = 0;
    //在可能发生异常的代码上加try…catch快捷键 Shift+Alt+z
    try {
    divide(a, b);
    //不会运行
    System.out.println(“ccc”);
    } catch (ArithmeticException e) {
    //处理方案代码
    System.out.println(“由经理来处理”);
    }
    //会运行
    System.out.println(“aaa”);
    }
    /**
    * jvm默认对运行时异常的默认处理是向上抛出
    * @author renliang
    * @param a
    * @param b
    /
    public static void divide(int a, int b){
    System.out.print(a/b);
    // 不会运行
    System.out.println(“bbb”);
    }
    }
    /
    *
    由经理来处理
    aaa
    /
     try….finally
    finally内部的代码不管是否发生异常一定会被执行,finally主要是来做一些资源的释放。
    package com.rl.exception;
    public class ExceptionDemo5 {
    public static void main(String[] args) {
    int a = 20;
    int b = 0;
    try{
    System.out.println(a/b);
    }finally{
    System.out.println(“finally执行”);
    }
    }
    }
     Try…catch…finally
    /
    *
    * 异常处理形式的finally执行
    /
    try {
    System.out.println(a/b);
    } catch (Exception e) {
    System.out.println(“被0除了”);
    }finally{
    System.out.println(“执行finally”);
    }
    注意:finally可以在return后面执行
    Finally
    package com.rl.exception;
    public class ExceptionDemo6 {
    public static void main(String[] args) {
    int a = 20;
    int b = 2;
    //System.out.println(divide(a,b));
    System.out.println(getNum());
    }
    public static int divide(int a, int b){
    int i = 0;
    try {
    i = a/b;
    return i;
    } catch (Exception e) {
    System.out.println(“发生异常”);
    return i;
    }finally{
    //finally可以在return后面执行
    System.out.println(“finally执行”);
    }
    }
    /
    *
    * 容易出面试题
    * @author renliang
    * @return
    */
    public static int getNum(){
    int i = 0;
    try {
    i = 30;
    return i;//return 后的语句 返回值再使用变量修改没有意义,修改不了返回值。
    } catch (Exception e) {
    i = 40;
    return i;
    }finally{
    i = 50;
    //return i;//return的语句会把上一个return给覆盖掉
    //finally可以在return后面执行
    //System.out.println(“finally执行”);
    }
    }
    }

    2.编译期异常处理
    编译期的异常我们必须处理或者抛出,否则没有办法编译通过。
    处理:
    public static void method(){
    try {
    ServerSocket s = new ServerSocket(8888);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    抛出:在方法后面加上throws Exception
    public static void method() throws IOException{
    ServerSocket s = new ServerSocket(8888);
    }
    编译期的异常和运行时的异常的区别:
    编译期异常:
    我们必须要处理或者抛出,否则无法编译通过,继承于Exception的所有异常除了RuntimeException以外都是编译期的异常。
    运行时异常:
    运行时异常可以编译通过,它是发生在程序的运行阶段,在运行的阶段如果发生了运行时异常,如果我们当前方法不处理就会自动抛出,我们也可以手动通过代码来捕捉来处理,建议向上抛出。
    3.自定义异常
    在实际的项目中,我们需要跟业务相关的异常,javaAPI中是没有的,所以我们要自定义。

    如:在电商系统中,在提交订单的时候如果出现了库存不足,我们要抛出自定义的异常。
    自定义的异常只要继承javaAPI中的异常类即可,通常情况下我们会自定义运行时异常。
    所以我们自定义异常就去继承RuntimeException。

    package com.rl.exception;
    /**

    • 自定义运行时异常
    • @author renliang

    */
    public class StockException extends RuntimeException {
    public StockException() {
    super();
    }
    public StockException(String message, Throwable cause,
    boolean enableSuppression, boolean writableStackTrace) {
    super(message, cause, enableSuppression, writableStackTrace);
    }
    public StockException(String message, Throwable cause) {
    super(message, cause);
    }
    public StockException(String message) {
    super(message);
    }
    public StockException(Throwable cause) {
    super(cause);
    }
    }

    测试:
    package com.rl.exception;
    public class ExceptionDemo8 {
    public static void main(String[] args){
    try {
    submitOrder();
    } catch (StockException e) {
    String mess = e.getMessage();
    System.out.println(“提示给用户:”+mess);
    }
    }
    public static void submitOrder(){
    //商品的库存
    int stock = 0;
    if(stock == 0){
    throw new StockException(“库存不足”);
    }
    }
    }
    JAVASE第11天字符串
    1.字符串概述
    整数类型(byte,short,int,long)
    数值型
    浮点类型(float, double)
    基本数据类型 字符型 (char)

    数据类型 布尔类型(boolean)
    类(class)
    引用数据类型 接口(interface)

    							数组([])
    

    String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。字符串是常量;它们的值在创建之后不能更改

    package com.rl.string;
    public class StringDemo {
    public static void main(String[] args) {
    //定义一个字符类型的常量,这个常量是个对象"ren",字符串的常量需要使用""来引起来
    String str = “ren”;
    str += “liang”;
    System.out.println(str);
    }
    }

    栈空间 堆

    					str
    
    
    							数据共享区
    					 str1
    							数据共享区
    

    数据共享区里面的字符串是被共享的。
    2.字符串的构造器
    构造方法摘要
    String()
    初始化一个新创建的 String 对象,使其表示一个空字符序列。
    String(byte[] bytes)
    通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
    String(byte[] bytes, int offset, int length)
    通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
    String(char[] value)
    分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。
    String(char[] value, int offset, int count)
    分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
    String(String original)
    初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
    3.面试题
    String s1 = new String (“abc”);
    String s2 = “abc”;
    有什么区别?
    前者创建了两个对象,后者创建一个对象。
    == :
    比较基本类型,比较值是否相同。
    比较引用类型,比较地址值是否相同。
    equals();
    比较引用类型默认比较的是地址是否相同,对于string引用类型都会重写该方法,一个类具体比较的是什么我们就得分析源码。

    S1和s2的地址是不同的,但是值是相同的
    package com.rl.string;
    public class StringDemo2 {

    public static void main(String[] args) {
    	
    	String s1 = new String("abc");
    	String s2 = "abc";
    	System.out.println(s1 == s2);//false
    	//String类对equals方法的重写就是比较字符串的值
    	System.out.println(s1.equals(s2));//true
    }
    

    }

    				S1
    
    				S2
    								数据共享区
    

    字符串的比较
    package com.rl.string;
    public class StringDemo3 {
    public static void main(String[] args) {
    String s1 = new String(“renliang”);
    String s2 = new String(“renliang”);
    System.out.println(s1 == s2);//false
    System.out.println(s1.equals(s2));//true
    System.out.println("---------------------------");
    String s3 = “renliang”;
    String s4 = “renliang”;
    System.out.println(s3 == s4);//true
    System.out.println(s3.equals(s4));//true
    System.out.println("---------------------------");
    String s5 = “ren”;
    String s6 = “liang”;
    String s7 = “renliang”;
    System.out.println(s7 == s5 + s6);//false变量相加产生的字符串是个新字符串,有新的地址
    System.out.println(s7 == “ren”+“liang”);//true常量相加的结果会去数据共享区中去找和加之后的结果相等的字符串如果找到了就不去创建了
    }
    }
    4.字符串的判断方法
    boolean endsWith(String suffix)
    测试此字符串是否以指定的后缀结束。
    boolean equals(Object anObject)
    将此字符串与指定的对象比较。
    boolean equalsIgnoreCase(String anotherString)
    将此 String 与另一个 String 比较,不考虑大小写。
    boolean contains(CharSequence s)
    当且仅当此字符串包含指定的 char 值序列时,返回 true。
    boolean startsWith(String prefix)
    测试此字符串是否以指定的前缀开始。
    boolean isEmpty()
    当且仅当 length() 为 0 时返回 true。

    代码:
    package com.rl.string;
    public class StringDemo4 {
    public static void main(String[] args) {
    String s1 = “renliang”;
    String s2 = “RenLiang”;
    //判断字符串是否相等但是忽略大小写
    System.out.println(s1.equalsIgnoreCase(s2));
    String s3 = “ren”;
    //判断某个字符串中是否包含另一个字符串,区分大小写
    System.out.println(s1.contains(s3));
    System.out.println(s2.contains(s3));
    //测试此字符串是否以指定的前缀开始
    System.out.println(s1.startsWith(s3));
    System.out.println(s1.startsWith(“renl”));
    //测试此字符串是否以指定的后缀结束
    System.out.println(s1.endsWith(“ang”));
    //当且仅当 length() 为 0 时返回 true。
    System.out.println(s1.isEmpty());
    //判断一个空字符串是否是空串
    String s4 = “”;
    System.out.println(s4.isEmpty());
    String s5 = new String();
    System.out.println(s5.isEmpty());
    String s6 = null;
    System.out.println(s6.isEmpty());
    }
    }
    5.字符串的获取功能
    int length()
    返回此字符串的长度。
    char charAt(int index)
    返回指定索引处的 char 值。
    int indexOf(int ch)
    返回指定字符在此字符串中第一次出现处的索引
    int indexOf(String str)
    返回指定子字符串在此字符串中第一次出现处的索引。
    int indexOf(String str, int fromIndex)
    返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
    String
    substring(int beginIndex)
    返回一个新的字符串,它是此字符串的一个子字符串。
    String
    substring(int beginIndex, int endIndex)
    返回一个新字符串,它是此字符串的一个子字符串。
    代码:
    package com.rl.string;
    public class StringDemo5 {
    public static void main(String[] args) {
    String s1 = “hewolloworld”;
    System.out.println(“获得s1的长度:”+s1.length());
    char c = s1.charAt(5);
    System.out.println(“获得指定索引位置的字符:”+c);
    System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘h’));
    System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘l’));
    System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘o’));
    System.out.println(“获得指定的第一次出现字符串的索引:”+s1.indexOf(“ll”));
    System.out.println(“获得指定的第一次出现字符串的索引:”+s1.indexOf(“wo”));
    System.out.println(“获得从某个索引器指定的第一次出现字符串的索引:”+s1.indexOf(“wo”, 0));
    //所截取的字符串包括临界点
    System.out.println(“字符串单端截取:”+s1.substring(3));
    //注意双端字符串的截取,endIndex不包括临界点
    System.out.println(“字符串双端截取:”+s1.substring(3,7));
    }
    }
    字符串获取练习:
    package com.rl.string;
    import java.util.Scanner;
    public class StringDemo6 {
    public static void main(String[] args) {
    String str = “renliang”;
    //printChar(str);
    Scanner sc = new Scanner(System.in);
    String inputStr = sc.nextLine();
    //printChar(inputStr);
    countNum(inputStr);
    }
    /**
    * 遍历一个字符串
    * @author renliang
    * @param str
    /
    public static void printChar(String str){
    for(int i = 0; i < str.length(); i++){
    //根据索引获得每一个字符
    char c = str.charAt(i);
    System.out.print(c+"\t");
    }
    }
    /
    *
    * 计算一个字符串中大写字母和小写字母还有数字的数量
    * char c = ch
    *
    * ch >= ‘A’ && ch <= ‘Z’
    * ch >= ‘a’ && ch <= ‘z’
    * ch >= ‘0’ && ch <= ‘9’
    *
    *
    * @author renliang
    * @param str
    */
    public static void countNum(String str){
    int bigChar = 0;
    int smallChar = 0;
    int nums = 0;
    for(int i = 0; i < str.length(); i++){
    char ch = str.charAt(i);
    /if(ch >= 65 && ch <= 90){
    bigChar++;
    }else if(ch >= 97 && ch <= 122){
    smallChar++;
    }else if(ch >= 48 && ch <= 57){
    nums++;
    }
    /
    if(ch >= ‘A’ && ch <= ‘Z’){
    bigChar++;
    }else if(ch >= ‘a’ && ch <= ‘z’){
    smallChar++;
    }else if(ch >= ‘0’ && ch <= ‘9’){
    nums++;
    }
    }
    System.out.println(“大写字母有:”+bigChar);
    System.out.println(“小写字母有:”+smallChar);
    System.out.println(“数字有:”+nums);
    }
    }
    6.字符串的转换

    byte[] getBytes()
    使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
    char[] toCharArray()
    将此字符串转换为一个新的字符数组。
    static String
    valueOf(boolean b)
    返回 boolean 参数的字符串表示形式。
    static String
    valueOf(char c)
    返回 char 参数的字符串表示形式。
    static String
    valueOf(char[] data)
    返回 char 数组参数的字符串表示形式。
    static String
    valueOf(char[] data, int offset, int count)
    返回 char 数组参数的特定子数组的字符串表示形式。
    static String
    valueOf(double d)
    返回 double 参数的字符串表示形式。
    static String
    valueOf(float f)
    返回 float 参数的字符串表示形式。
    static String
    valueOf(int i)
    返回 int 参数的字符串表示形式。
    static String
    valueOf(long l)
    返回 long 参数的字符串表示形式。
    String
    toUpperCase()
    使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
    String
    toUpperCase(Locale locale)
    使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。
    String
    concat(String str)
    将指定字符串连接到此字符串的结尾。

    测试代码:
    package com.rl.string;
    public class StringDemo7 {
    public static void main(String[] args) {
    String str = “renliang”;
    //获得字节数组
    byte[] bs = str.getBytes();
    for(int i = 0; i < bs.length; i++){
    System.out.print(bs[i]+"\t");
    }
    System.out.println();
    System.out.println("----------------------------------------------------------");
    //获得字符数组
    char[] cs = str.toCharArray();
    for(int i = 0; i < cs.length; i++){
    System.out.print(cs[i]+"\t");
    }
    System.out.println();
    System.out.println("----------------------------------------------------------");
    String bStr = String.valueOf(true);
    System.out.println(bStr);
    String cStr = String.valueOf(‘a’);
    System.out.println(cStr);
    char[] cs1 = {‘a’,‘b’,‘c’};
    String cs1Str = String.valueOf(cs1);
    System.out.println(cs1Str);
    char[] cs2 = {‘a’,‘b’,‘c’,‘d’,‘e’};
    //第二个参数是截取的开始索引,第三个参数是向后截取的长度
    String cs2Str = String.valueOf(cs2, 2, 2);
    System.out.println(cs2Str);
    String dStr = String.valueOf(0.12d);
    System.out.println(dStr);
    String fStr = String.valueOf(0.12f);
    System.out.println(fStr);
    String iStr = String.valueOf(10);
    System.out.println(iStr);
    //数值后面加上"l"就是代表这个数是long类型
    String lStr = String.valueOf(10l);
    System.out.println(lStr);
    //把字符串变成大写
    String upperStr = str.toUpperCase();
    System.out.println(upperStr);
    String str2 = “RENLIANG”;
    String lowerStr = str2.toLowerCase();
    System.out.println(lowerStr);
    String str3 = str2.concat(“helloworld”);
    System.out.println(str3);
    System.out.println(str2+“helloworld”);
    //字符串和任何基本数据类型相加都会转换成字符串
    System.out.println(“helloworld”+1);
    }
    }
    7.其他功能
    String[]
    split(String regex)
    根据给定正则表达式的匹配拆分此字符串。
    String
    replace(char oldChar, char newChar)
    返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
    String
    replace(CharSequence target, CharSequence replacement)
    使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
    String
    trim()
    返回字符串的副本,忽略前导空白和尾部空白。
    代码:
    package com.rl.string;
    /**
    *

    • @author renliang

    /
    public class StringDemo9 {
    public static void main(String[] args) {
    //String str = “10-9-7-12”;
    String str = “10.9.7.12”;
    //获得以"-“分隔的每一个字符串,注意对于特殊的字符的分隔要加\, 避免特殊字符
    String [] strArr = str.split(”\.");
    for(int i = 0; i< strArr.length; i++){
    System.out.println(strArr[i]);
    }
    System.out.println("--------------------------");
    String str1 = “helloworld”;
    str1 = str1.replace(‘l’, ‘o’);
    System.out.println(str1);
    System.out.println("--------------------------");
    //第一个参数是被替换的字符串,第二个参数是替换成的字符串
    str1 = str1.replace(“owo”, “xxx”);
    System.out.println(str1);
    String str2 = " renliang ";
    System.out.println("
    "+str2+"");
    str2 = str2.trim();
    System.out.println("
    "+str2+"*");
    }
    }
    8.练习
    package com.rl.string;
    /**
    *

    • @author renliang
    • 需求:找出下面字符串中li的数量
    • “liasdflihsdhllihsdflihsdfiligsdfglikhsdfklilisdflio”

    */
    public class StringDemo10 {
    public static void main(String[] args) {
    String str = “liasdflihsdhllihsdflihsdfiligsdfglikhsdfklilisdflioli”;
    int count = 0;
    //获得str字符串中第一个li的索引位置,如果在一个字符串中查找指定的字符串没有找到就返回-1
    String targetStr = “li”;
    //获得li的长度
    int liLength = targetStr.length();
    //定义索引位置
    int inIndex = 0;
    //获得第一个li的索引
    inIndex = str.indexOf(targetStr);
    //如果索引不等于-1就继续查询
    while(inIndex != -1){
    //计数器做累加
    count++;
    //获得每次迭代的开始索引号
    inIndex += liLength;
    //获得每次迭代后的某个开始索引号后的第一个li
    inIndex = str.indexOf(targetStr, inIndex);
    }
    System.out.println(targetStr+“的数量是:”+count);
    }
    }

    可变字符串包装类日期
    1.可变字符串
    1.StringBuffer概述
    StringBuffer:字符串缓冲区。
    StringBuffer和String区别呢?
    String一旦被创建后,值不能改变,如果参与了操作,引用发生了变化,不是在原有的字符串上操作,而是新产生了一个字符串
    String s = “hello”;
    s += “world”;
    System.out.println(s)//helloworld
    StringBuffer:是线程安全的可变字符串。
    StringBuffer b = “hello”;
    b += “world”;//使用hello的空间追加world,不是新创建一个字符串。
    System.out.println(s)//helloworld
    b追加
    追加a

    StringBuffer是线程安全的,效率稍低。
    2.StringBuffer的构造器

    StringBuffer()
    构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
    StringBuffer(int capacity)
    构造一个不带字符,但具有指定初始容量的字符串缓冲区。
    StringBuffer(String str)
    构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
    代码:
    package com.rl.sbuffer;
    public class StringBufferDemo {
    public static void main(String[] args) {
    //创建可变字符串的对象
    StringBuffer sb = new StringBuffer();
    System.out.println(“可变字符串的长度是:”+sb.length()+ " 容量是:"+sb.capacity());
    System.out.println(“sb:”+sb);
    StringBuffer sb1 = new StringBuffer(20);
    System.out.println(“可变字符串的长度是:”+sb1.length()+ " 容量是:"+sb1.capacity());
    System.out.println(“sb1:”+sb1);
    StringBuffer sb2 = new StringBuffer(“renliang”);
    System.out.println(“可变字符串的长度是:”+sb2.length()+ " 容量是:"+sb2.capacity());
    System.out.println(“sb2:”+sb2);
    }
    }
    3StringBuffer字符串处理
     追加:
    StringBuffer
    append(boolean b)
    Appends the string representation of the boolean argument to the sequence.
    StringBuffer
    append(char c)
    Appends the string representation of the char argument to this sequence.
    StringBuffer
    append(char[] str)
    Appends the string representation of the char array argument to this sequence.
    StringBuffer
    append(char[] str, int offset, int len)
    Appends the string representation of a subarray of the char array argument to this sequence.
    StringBuffer
    append(double d)
    Appends the string representation of the double argument to this sequence.
    StringBuffer
    append(float f)
    Appends the string representation of the float argument to this sequence.
    StringBuffer
    append(int i)
    Appends the string representation of the int argument to this sequence.
    StringBuffer
    append(long lng)
    Appends the string representation of the long argument to this sequence.
    StringBuffer
    append(String str)
    Appends the specified string to this character sequence.
    StringBuffer
    append(StringBuffer sb)
    将指定的 StringBuffer 添加到此序列中。
     插入:
    StringBuffer
    insert(int offset, boolean b)
    Inserts the string representation of the boolean argument into this sequence.
    StringBuffer
    insert(int offset, char c)
    Inserts the string representation of the char argument into this sequence.
    StringBuffer
    insert(int offset, char[] str)
    Inserts the string representation of the char array argument into this sequence.
    StringBuffer
    insert(int index, char[] str, int offset, int len)
    Inserts the string representation of a subarray of the str array argument into this sequence.
    StringBuffer
    insert(int offset, double d)
    Inserts the string representation of the double argument into this sequence.
    StringBuffer
    insert(int offset, float f)
    Inserts the string representation of the float argument into this sequence.
    StringBuffer
    insert(int offset, int i)
    Inserts the string representation of the second int argument into this sequence.
    StringBuffer
    insert(int offset, long l)
    Inserts the string representation of the long argument into this sequence.
    StringBuffer
    insert(int offset, String str)
    Inserts the string into this character sequence.
    实例代码:
    package com.rl.sbuffer;
    public class StringBufferDemo1 {
    public static void main(String[] args) {
    //创建可变字符串的对象
    StringBuffer sb = new StringBuffer();
    StringBuffer sb1 = sb.append(true);//sb追加后字符串的地址不变
    System.out.println(sb == sb1);//true
    sb.append(‘a’);
    //追加字符的数组
    char[] chs = {‘b’,‘c’,‘d’};
    sb.append(chs);
    //追加字符数组的指定位置的和指定长度的部分
    char[] chs1 = {‘l’,‘o’,‘v’,‘e’};
    sb.append(chs1, 1, 3);
    //对double数据类型追加
    sb.append(10.19d);
    //追加float类型
    sb.append(12.34f);
    //追加int类型
    sb.append(99);
    //追加long类型
    sb.append(222l);
    //追加String类型
    sb.append(“zhangsan”);
    StringBuffer sb2 = new StringBuffer(“lisi”);
    sb.append(sb2);
    System.out.println(sb);

    	System.out.println("----------------------------");
    	StringBuffer sb3 = new StringBuffer();
    	sb3.append(false)
    	   .append('a')
    	   .append(10)
    	   .append("wangwu");
    	System.out.println(sb3);	
    	System.out.println("------------------------------");
    	StringBuffer sb4 = new StringBuffer("helloworld");
    	//在指定位置插入字符串
    	//sb4.insert(3, true);
    	char[] chs2 = {'x','y','z'};
    	//sb4.insert(3, chs2);
    	sb4.insert(3, chs2, 1, 2);
    	System.out.println(sb4);
    }
    

    }
     删除
    StringBuffer
    delete(int start, int end)
    Removes the characters in a substring of this sequence.
    StringBuffer
    deleteCharAt(int index)
    Removes the char at the specified position in this sequence.
    实例代码:
    package com.rl.sbuffer;
    public class StringBufferDemo2 {
    public static void main(String[] args) {
    //创建可变字符串的对象
    StringBuffer sb = new StringBuffer(“helloworld”);
    //删除的索引包括开始不包括结束
    sb.delete(2, 4);
    System.out.println(sb);
    //删除指定索引的字符
    sb.deleteCharAt(4);
    System.out.println(sb);
    //清空缓存区
    sb.delete(0, sb.length());
    System.out.println(sb);
    }
    }

     替换
    StringBuffer
    replace(int start, int end, String str)
    Replaces the characters in a substring of this sequence with characters in the specified String.
     字符串的反转
    StringBuffer
    reverse()
    Causes this character sequence to be replaced by the reverse of the sequence.
     某个字符串的倒序索引
    int lastIndexOf(String str)
    Returns the index within this string of the rightmost occurrence of the specified substring.
    int lastIndexOf(String str, int fromIndex)
    Returns the index within this string of the last occurrence of the specified substring.
    实例代码:
    package com.rl.sbuffer;
    public class StringBufferDemo3 {
    public static void main(String[] args) {
    //创建可变字符串的对象
    StringBuffer sb = new StringBuffer(“helloworld”);
    //替换指定的字符串,指定开始索引和结束索引,替换时包括开始的索引,不包括结束的索引
    sb.replace(2, 4, “xxx”);
    System.out.println(sb);
    //可变字符串反转
    sb.reverse();
    System.out.println(sb);
    StringBuffer sb1 = new StringBuffer(“helloworld”);
    int index = sb1.indexOf(“l”);
    System.out.println(index);
    //从后向前数第一个字符串
    int lastIndex = sb1.lastIndexOf(“l”);
    System.out.println(lastIndex);
    //获得从某个索引开始向前数第一个字符串
    int lastIndex1 = sb1.lastIndexOf(“l”, 5);
    System.out.println(lastIndex1);
    }
    }
    2.Random随机数产生类
    1.Random的构造器

    构造方法摘要
    Random()
    创建一个新的随机数生成器。
    Random(long seed)
    使用单个 long 种子创建一个新的随机数生成器。
    常用的方法
    int nextInt()
    返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
    int nextInt(int n)
    返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
    示例代码:
    package com.rl.random;
    import java.util.Random;
    public class RandomDemo {
    public static void main(String[] args) {
    //创建随机数产生的对象
    Random random = new Random();
    int num = 0;
    for(int i = 0; i < 10; i++){
    //获得在int范围内的一个随机数
    //num = random.nextInt();
    //我们的随机数只能产生在100之内
    num = random.nextInt(100);
    System.out.println(num);
    }
    //创建一个以指定的数值为种子的随机数,可以生成不变的序列
    Random random1 = new Random(99);
    for(int i = 0; i < 10; i++){
    //获得在int范围内的一个随机数
    //num = random.nextInt();
    //我们的随机数只能产生在100之内
    num = random1.nextInt(100);
    System.out.println(num);
    }
    }
    }

    3.System类
    常用的属性:
    static InputStream
    in
    “标准”输入流。
    static PrintStream
    out
    “标准”输出流。
    常用方法:
    static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
    从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
    static long currentTimeMillis()
    返回以毫秒为单位的当前时间。
    static void exit(int status)
    终止当前正在运行的 Java 虚拟机。
    static void gc()
    运行垃圾回收器。
    static String
    getProperty(String key)
    获取指定键指示的系统属性。
    实例代码:
    package com.rl.system;
    public class SystemDemo {
    public static void main(String[] args) {
    int [] arr1 = {1, 2, 3, 4, 5};
    int [] arr2 = {11, 22, 33, 44, 55, 0, 0};
    //第一个参数:源数组,第二个参数:要拷贝的源数组的起始索引, 第三个参数是目标数组,第四个是目标数据的起始位置,第五个参数拷贝的长度
    System.arraycopy(arr1, 2, arr2, 5, 2);
    for(int i = 0 ; i < arr2.length; i++){
    System.out.println(arr2[i]);
    }
    //long timeMillis = System.currentTimeMillis();
    //System.out.println("1970年1月1日距离现在 "+timeMillis+“毫秒”);
    long startTime = System.currentTimeMillis();
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    long endTime = System.currentTimeMillis();
    System.out.println(“程序运行了:”+(endTime - startTime)+“毫秒”);
    //退出虚拟机
    //System.exit(0);
    //手动调用垃圾回收器
    System.gc();
    //获得系统属性
    String value = System.getProperty(“java.home”);
    System.out.println(value);
    }
    }
    4.包装类
    1.概述
    把基本数据类型转换成类,我们使用基本数据类型做进制转换很麻烦,对于临界值也不好判断,我们的包装类提供了很多方法供我们使用,这样会方便很多。
    基本数据类型 byte short int long float double char boolean
    包装类 Byte Short Integer Long Float Double Character Boolean
    Integer 类在对象中包装了一个基本类型 int 的值。
    2.Integer的构造器
    Integer(int value)
    构造一个新分配的 Integer 对象,它表示指定的 int 值。
    Integer(String s)
    构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
    3.数据转换
    int或Integer转换string
    第一种:
    String类的类方法
    static String
    valueOf(int i)
    返回 int 参数的字符串表示形式。
    第二种Integer类里面
    static String
    toString(int i)
    返回一个表示指定整数的 String 对象。
    第三种:直接用int的值加空字符串:如100+“”

    String转换int或Integer
    Integer(String s)
    构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
    static Integer
    valueOf(String s)
    返回保存指定的 String 的值的 Integer 对象。

    static int parseInt(String s)
    将字符串参数作为有符号的十进制整数进行解析。

    Integer转换成字符串
    static String
    valueOf(Object obj)
    返回 Object 参数的字符串表示形式。
    注意:8种基本数据类型和其相应的包装类之间可以自动的转换(自动装箱拆箱)
    package com.rl.integer;
    public class IntegerDemo2 {
    public static void main(String[] args) {
    //int转换成String
    int num = 100;
    //任何基本数据类型和字符串相加都能得到字符串类型的结果
    String s = num + “”;
    System.out.println(s);
    String s1 = String.valueOf(num);
    System.out.println(s1);
    String s2 = Integer.toString(num);
    System.out.println(s2);
    //字符串转换成int和Integer
    System.out.println("---------------------------------------");
    String numStr = “99”;
    //字符串一定是数值形式的
    Integer i = new Integer(numStr);
    int intVal = i.intValue();
    System.out.println(i);
    System.out.println(intVal);
    Integer i2 = Integer.valueOf(numStr);
    int i2Val = i2.intValue();
    System.out.println(i2);
    System.out.println(i2Val);

    	Integer i3 = Integer.parseInt(numStr);
    	int i3Val = i3.intValue();
    	System.out.println(i3);
    	System.out.println(i3Val);
    	//Integer转换String
    	System.out.println("-----------------------------");
    	Integer i4 = new Integer(66);
    	String i4Str = String.valueOf(i4);
    	System.out.println(i4Str);
    	String i4Str1 = i4 +"";
    	System.out.println(i4Str1);
    	//同样可以使用Integer.toString(int i);来转换
    	String i4Str2 = Integer.toString(i4);
    	System.out.println(i4Str2);
    }
    

    }
    4.自动装箱和拆箱
    装箱:把int类型转换正Integer--------------》new Integer(int i)
    拆箱:把Integer转换成int------------》intValue()对象方法
    装箱和拆箱是不需要我们主动调用的,是jvm自动给我们完成的。

    Integer数据类型的默认值:null
    int数据类型的默认值:0
    建议大家在实际做项目时都使用Integer数据类型
    package com.rl.integer;
    public class IntegerDemo3 {
    public static void main(String[] args) {
    //自动的装箱
    Integer i = 1;
    System.out.println(i);
    Integer i2 = new Integer(100);
    //拆箱
    int i3 = i2;
    System.out.println(i3);
    System.out.println("--------------------------");
    /Integer数据类型的默认值:null
    int数据类型的默认值:0
    建议大家在实际做项目时都使用Integer数据类型
    /
    Person p = new Person();
    System.out.println(“Integer数据类型的默认值:”+p.getPersonId());
    System.out.println(“int数据类型的默认值:”+p.getAge());
    String str = String.valueOf(p.getPersonId());
    System.out.println(str);
    //出现null+100;
    //java.lang.NullPointerException, 使用null值计算或者取值时就会报空指针异常。
    int i1 = p.getPersonId() + 100;
    System.out.println(i1);
    String s = null;
    //字符串在使用之前一定要做判空
    //java.lang.NumberFormatException
    Integer i4 = new Integer(s);
    System.out.println(i4);
    }
    }
    5.日期处理
    1.Date类
    1.date的构造器
    构造方法摘要
    Date()
    分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
    Date(long date)
    分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
    2.date的方法
    long getTime()
    返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
    实例代码:
    package com.rl.date;
    import java.util.Date;
    public class DateDemo {
    public static void main(String[] args) {
    //创建时间对象
    Date date = new Date();
    System.out.println(date);
    //从1970年到现在的毫秒数
    long timeSeconds = System.currentTimeMillis();
    Date date1 = new Date(timeSeconds);
    System.out.println(date1);
    long hourSeconds = 60
    60
    1000;
    Date date2 = new Date(timeSeconds - hourSeconds);
    System.out.println(date2);
    //获得一个指定的日期到1970年的毫秒数
    long seconds = date2.getTime();
    //当前时间1个小时之前的毫秒数
    System.out.println(seconds);
    //当前时间的毫秒数
    System.out.println(timeSeconds);
    }
    }
    2.日期的格式化
    掌握:
     日期转换String
    要求我们掌握DateFormat是抽象类,我们要学习的是它的子类SimpleDateFormat
    SimpleDateFormat()
    用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
    SimpleDateFormat(String pattern)
    用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
    掌握的方法
    String
    format(Date date)
    将一个 Date 格式化为日期/时间字符串。

     String转换日期

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

    package com.rl.date;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class SimpleDateFormatDemo {
    public static void main(String[] args) {
    //把时间转换成字符串
    //创建时间格式化的对象
    SimpleDateFormat sdf = new SimpleDateFormat();
    //我们获得格式化之后的字符串
    String dateStr = sdf.format(new Date());
    System.out.println(dateStr);
    //根据自己的定义模板来展示时间
    SimpleDateFormat sdf1 = new SimpleDateFormat(“yyyy年MM月dd日 HH:mm:ss:SSS a E”);
    SimpleDateFormat sdf2 = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
    String dateStr1 = sdf1.format(new Date());
    String dateStr2 = sdf2.format(new Date());
    System.out.println(dateStr1);
    System.out.println(dateStr2);
    System.out.println("--------------------------------");
    try {
    //把字符串转换成日期,前提一定是字符串符合format的pattern
    Date date = sdf2.parse(“1985-04-22 23:12:22”);
    System.out.println(date);
    } catch (ParseException e) {
    e.printStackTrace();
    }
    }
    }

    3.Calendar日历类
    获得日历类的实例
    static Calendar
    getInstance()
    使用默认时区和语言环境获得一个日历。
    实例代码:掌握如果获得时间和设置时间
    package com.rl.date;
    import java.util.Calendar;
    import java.util.Date;
    public class CalendarDemo {
    public static void main(String[] args) {
    //获得日历类的一个子类
    Calendar c = Calendar.getInstance();
    //java.util.GregorianCalendar
    /[time=1446281927642,
    areFieldsSet=true,
    areAllFieldsSet=true,
    lenient=true,
    zone=sun.util.calendar.ZoneInfo[id=“Asia/Shanghai”,
    offset=28800000,dstSavings=0,useDaylight=false,
    transitions=19,lastRule=null],
    firstDayOfWeek=1,
    minimalDaysInFirstWeek=1,
    ERA=1,
    YEAR=2015,
    MONTH=9, //计算国内的月份需要加1
    WEEK_OF_YEAR=44,
    WEEK_OF_MONTH=5,
    DAY_OF_MONTH=31,
    DAY_OF_YEAR=304,
    DAY_OF_WEEK=7, //计算国内的星期需要加1
    DAY_OF_WEEK_IN_MONTH=5,
    AM_PM=1,HOUR=4,
    HOUR_OF_DAY=16,
    MINUTE=58,
    SECOND=47,
    MILLISECOND=642
    ,ZONE_OFFSET=28800000,
    DST_OFFSET=0]
    /
    System.out.println©;
    //获得日期的具体时间,通过get方法来指定日历的常量
    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+“日”);
    System.out.println("-------------------------------");
    //设置年月日
    c.set(2008, 8, 18);
    c.set(Calendar.HOUR_OF_DAY, 10);
    int year1 = c.get(Calendar.YEAR);
    int month1 = c.get(Calendar.MONTH)+1;
    int day1 = c.get(Calendar.DAY_OF_MONTH);
    int hour = c.get(Calendar.HOUR_OF_DAY);
    System.out.println(year1+“年”+month1+“月”+day1+“日” +hour);
    }
    }
    集合上
    1.数组回顾
    需求:把一个你班级的学生存储起来,使用数组。
    数组的长度是固定的,无法满足动态的数据添加。
    面试题:数组和集合的区别?

    数组:长度固定,
    可以存储基本数据类型,也能存储对象
    只能存储同一种数据类型的数据

    集合:长度可变
    只能存储对象类型。
    在集合中可以存储任意类型
    2.集合
    1.集合的体系结构
    集合也叫容器用于存储对象。
    我们根据不同的需求和不同的数据结构来对集合做了不同的抽象。

    2.集合的方法
    添加:
    boolean add(E e)
    确保此 collection 包含指定的元素(可选操作)。
    boolean addAll(Collection<? extends E> c)
    将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
    删除:
    void clear()
    移除此 collection 中的所有元素(可选操作)。
    boolean remove(Object o)
    从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
    boolean removeAll(Collection<?> c)
    移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。

    判断:
    boolean contains(Object o)
    如果此 collection 包含指定的元素,则返回 true。
    boolean containsAll(Collection<?> c)
    如果此 collection 包含指定 collection 中的所有元素,则返回 true。
    boolean isEmpty()
    如果此 collection 不包含元素,则返回 true。
    数组的转换:
    Object[]
    toArray()
    返回包含此 collection 中所有元素的数组。
    添加删除代码:
    package com.rl.coll;
    import java.util.ArrayList;
    import java.util.Collection;
    public class CollectionDemo {
    public static void main(String[] args) {
    //创建ArrayList集合
    Collection c = new ArrayList();
    System.out.println©;
    c.add(“renliang”);
    c.add(“lisi”);
    c.add(“zhangsan”);
    System.out.println©;
    Collection c1 = new ArrayList();
    c1.add(“wangwu”);
    c1.add(“xueliu”);
    //把c这个集合的内容加在c1中,并且在后面追加
    c1.addAll©;
    System.out.println(c1);
    Collection c2 = new ArrayList();
    //对于基本类型的添加自动做了装箱,所以其实添加的是Integer
    c2.add(1);
    c2.add(2);
    //集合中可以存储不同类型的数据,但是在实际项目中都是存储同一类型的数据。
    c2.add(“renliang”);
    System.out.println(c2);

    	System.out.println("---------------------------------");
    	//c2.clear();
    	//System.out.println(c2);
    	c2.remove("renliang");
    	System.out.println(c2);
    	c1.removeAll(c);
    	System.out.println(c1);
    }
    

    }
    判断代码:
    package com.rl.coll;
    import java.util.ArrayList;
    import java.util.Collection;
    public class CollectionDemo1 {
    public static void main(String[] args) {
    //创建ArrayList集合
    Collection c = new ArrayList();
    System.out.println©;
    c.add(“renliang”);
    c.add(“lisi”);
    c.add(“zhangsan”);
    System.out.println©;
    Collection c1 = new ArrayList();
    c1.add(“wangwu”);
    c1.add(“xueliu”);
    //把c这个集合的内容加在c1中,并且在后面追加
    c1.addAll©;
    System.out.println(c1);
    boolean isExist = c.contains(“renliang”);
    System.out.println(isExist);
    //c.add(“aa”);
    //一个集合是否包含某个集合
    boolean isExistColl = c1.containsAll©;
    System.out.println(isExistColl);
    //c.clear();
    //判断集合中是否有元素
    boolean isEmpty = c.isEmpty();
    System.out.println(isEmpty);
    //把集合转换成数组
    Object[] objArray = c.toArray();
    for(int i = 0; i < objArray.length; i++){
    System.out.println(objArray[i]);
    }
    }
    }
    3.集合的遍历
    遍历:
    Iterator
    iterator()
    返回在此 collection 的元素上进行迭代的迭代器。

    A
    B
    C
    D
    E

    实例代码:
    package com.rl.coll;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    public class CollectionDemo2 {
    public static void main(String[] args) {
    //创建ArrayList集合
    Collection c = new ArrayList();
    c.add(“renliang”);
    c.add(“lisi”);
    c.add(“zhangsan”);
    //创建迭代器,迭代器是依赖于集合的,不能给别的集合使用
    Iterator iter = c.iterator();
    //判断是否有下一个元素
    while(iter.hasNext()){
    //区下一个元素
    Object obj = iter.next();
    System.out.println(obj);
    }
    //不能二次使用,迭代器的指针已经走到底部了
    /while(iter.hasNext()){
    //区下一个元素
    Object obj = iter.next();
    System.out.println(obj);
    }
    /
    }
    }

    练习:通过集合来存储Student并且遍历
    public class Student {
    private String name;
    private Integer age;
    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 Student(String name, Integer age) {
    super();
    this.name = name;
    this.age = age;
    }
    @Override //必须要重写,,要不然就会输出类名加上哈希个码
    public String toString() {
    return “Student [name=” + name + “, age=” + age + “]”;
    }

    }
    package com.rl.coll;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    public class CollectionDemo3 {
    public static void main(String[] args) {
    //创建ArrayList集合
    Collection c = new ArrayList();
    Student s = new Student(“林冲”, 34);
    Student s1 = new Student(“武松”, 30);
    Student s2 = new Student(“柴进”, 40);
    Student s3 = new Student(“李逵”, 28);
    Student s4 = new Student(“鲁智深”, 30);
    c.add(s);
    c.add(s1);
    c.add(s2);
    c.add(s3);
    c.add(s4);
    Iterator it = c.iterator();
    while(it.hasNext()){
    //获得集合中一个元素
    Object obj = it.next();
    Student stu = (Student)obj;
    System.out.println(stu);
    /* 注意使用迭代器的时候一次取一个元素即可。
    * java.util.NoSuchElementException
    * Student stu1 = (Student)it.next();
    System.out.println(stu1);*/
    }
    }
    }
    4.List
    有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
    1.要掌握的方法
    存储:
    boolean add(E e)
    向列表的尾部添加指定的元素(可选操作)。
    void add(int index, E element)
    在列表的指定位置插入指定元素(可选操作)。
    boolean addAll(Collection<? extends E> c)
    添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
    代码:
    package com.rl.list;
    import java.util.ArrayList;
    import java.util.List;
    public class ListDemo {
    public static void main(String[] args) {
    //定义List的集合
    List list = new ArrayList();
    //添加
    list.add(“任亮”);
    list.add(“吕布”);
    list.add(“董卓”);
    System.out.println(list);
    //[任亮, 吕布, 董卓]
    // 0 1 2 List集合的索引号
    //在指定的位置插入元素,后续的元素都向后顺移一位。
    //在根据索引添加的时候,如果要添加的索引没有前一个值则不能添加,中间不允许有空位。
    list.add(3, “貂蝉”);
    System.out.println(list);
    //定义List的集合
    List list1 = new ArrayList();
    list1.add(“王允”);
    //该方法继承与Collection
    list1.addAll(list);
    System.out.println(list1);
    }
    }

    获取:
    E
    get(int index)
    返回列表中指定位置的元素。
    int size()
    返回列表中的元素数。
    代码:
    package com.rl.list;
    import java.util.ArrayList;
    import java.util.List;
    public class ListDemo1 {
    public static void main(String[] args) {
    //定义List的集合
    List list = new ArrayList();
    //添加
    list.add(“任亮”);
    list.add(“吕布”);
    list.add(“董卓”);
    System.out.println(list);
    //[任亮, 吕布, 董卓]
    // 0 1 2 List集合的索引号
    //根据索引来获得list中的指定的元素
    //注意java.lang.IndexOutOfBoundsException
    Object obj = list.get(2);
    String str = (String)obj;
    System.out.println(str);
    //获得list的元素的个数
    Integer length = list.size();
    System.out.println(length);
    //使用for循环来遍历List
    for(int i = 0; i < list.size(); i++){
    String result = (String)list.get(i);
    System.out.println(result);
    }
    }
    }

    遍历:
    ListIterator
    listIterator()
    返回此列表元素的列表迭代器(按适当顺序)。
    代码:
    package com.rl.list;
    import java.util.ArrayList;
    import java.util.List;
    public class ListDemo2 {
    public static void main(String[] args) {
    //定义List的集合
    List list = new ArrayList();
    //添加
    list.add(“任亮”);
    list.add(“吕布”);
    list.add(“董卓”);
    System.out.println(list);
    //[任亮, 吕布, 董卓]
    // 0 1 2 List集合的索引号
    //根据索引删除list的元素,返回的结果是删除的元素
    /*Object obj = list.remove(2);
    System.out.println(obj);
    System.out.println(list);
    */
    /boolean isDelete = list.remove(“任亮”);
    System.out.println(isDelete);
    System.out.println(list);
    /
    //定义List的集合
    List list1 = new ArrayList();
    //添加
    list1.add(“任亮”);
    list1.add(“吕布”);
    //删除多个元素
    list.removeAll(list1);
    System.out.println(list);
    //清空list
    list.clear();
    System.out.println(list);
    }
    }

    删除:
    E
    remove(int index)
    移除列表中指定位置的元素(可选操作)。
    boolean remove(Object o)
    从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
    boolean removeAll(Collection<?> c)
    从列表中移除指定 collection 中包含的其所有元素(可选操作)。
    void clear()
    移除此 collection 中的所有元素(可选操作)。
    代码:
    package com.rl.list;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    public class ListDemo3 {
    public static void main(String[] args) {
    //定义List的集合
    List list = new ArrayList();
    //添加
    list.add(“任亮”);
    list.add(“吕布”);
    list.add(“董卓”);
    //[任亮, 吕布, 董卓]
    // 0 1 2 List集合的索引号
    ListIterator iter = list.listIterator();
    while(iter.hasNext()){
    String result = (String) iter.next();
    System.out.println(result);
    }
    System.out.println("------------------------");
    //获得前一个元素
    /String str = (String) iter.previous();
    Integer pIndex = iter.previousIndex();
    System.out.println(str + " "+pIndex);
    String str1 = (String) iter.previous();
    Integer pIndex1 = iter.previousIndex();
    System.out.println(str1 + " "+pIndex1);
    /
    while(iter.hasPrevious()){
    String result = (String) iter.previous();
    System.out.println(result);
    }
    }
    }

    2.遍历的并发
    添加或删除
    遍历

    多个线程对同一个集合操作时会产生并发安全性问题。java.util.ConcurrentModificationException,Iterator依赖于list,只要是list发生了变化Iterator就没有用了,就会发生并发修改异常。
    package com.rl.list;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    public class ListDemo4 {
    public static void main(String[] args) {
    //定义List的集合
    List list = new ArrayList();
    //添加
    list.add(“任亮”);
    list.add(“吕布”);
    list.add(“董卓”);
    //[任亮, 吕布, 董卓]
    // 0 1 2 List集合的索引号
    /Iterator iter = list.iterator();
    while(iter.hasNext()){
    String result = (String) iter.next();
    list.add(“王允”);
    System.out.println(result);
    }
    /
    /ListIterator iter = list.listIterator();
    while(iter.hasNext()){
    String result = (String) iter.next();
    //在迭代器中来添加数据,其实就是添加到了list中
    if(“任亮”.equals(result)){
    //新添加的数据不会被当前的这次循环遍历出来
    iter.add(“王允”);
    }
    System.out.println(result);
    }
    System.out.println(list);
    /
    /**
    * 在存在并发访问集合的时候建议使用for
    */
    for(int i = 0; i < list.size(); i++){
    String result = (String) list.get(i);
    if(“任亮”.equals(result)){
    //新添加的数据会被当前的这次循环遍历出来
    list.add(“王允”);
    }
    System.out.println(result);
    }
    }
    }
    javase集合下
    1.List的子类
    1.ArrayList
    List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
    特点:ArrayList中的元素和可以重复
    是有序的集合,长度不固定。
    不是线程安全的。
    效率高。
    package com.rl.listson;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.ListIterator;
    public class ArrayListDemo {
    public static void main(String[] args) {
    //method1();
    //curr();
    currFor();
    }
    public static void method(){
    ArrayList al = new ArrayList();
    al.add(“张三”);
    al.add(“李四”);
    al.add(“王五”);

    	Iterator iter = al.iterator();
    	while(iter.hasNext()){
    		String result = (String) iter.next();
    		System.out.println(result);
    	}
    }
    public static void method1(){
    	ArrayList al = new ArrayList();
    	al.add(new Student("林冲",30));
    	al.add(new Student("鲁智深",32));
    	al.add(new Student("史文恭",35));
    	al.add(new Student("卢俊义",35));	
    	Iterator iter = al.iterator();
    	while(iter.hasNext()){
    		Student result = (Student) iter.next();
    		System.out.println(result);
    	}
    }
    /**
     * ListIterator当前的遍历不能输出变化后的集合
     * @author renliang
     */
    public static void curr(){
    	ArrayList al = new ArrayList();
    	al.add(new Student("林冲",30));
    	al.add(new Student("鲁智深",32));
    	al.add(new Student("史文恭",35));
    	al.add(new Student("卢俊义",35));
    	
    	ListIterator iter = al.listIterator();
    	while(iter.hasNext()){
    		Student result = (Student) iter.next();
    		String stuName = result.getName();
    		if("史文恭".equals(stuName)){
    			iter.remove();
    		}
    		System.out.println(result);
    	}	
    	System.out.println(al);
    }
    /**
     * 在并发的时候for可以遍历变化后的集合
     * @author renliang
     */
    public static void currFor(){
    	ArrayList al = new ArrayList();
    	al.add(new Student("林冲",30));
    	al.add(new Student("鲁智深",32));
    	al.add(new Student("史文恭",35));
    	al.add(new Student("卢俊义",35));	
    	for(int i = 0; i < al.size(); i++){
    		Student result = (Student) al.get(i);
    		String stuName = result.getName();
    		if("史文恭".equals(stuName)){
    			al.remove(i);
    		}
    		System.out.println(result);
    	}		
    }
    

    }

    2.LinkList(了解)
    List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
    不是线程安全的。
    栈:

    “林冲”
    “武松”
    “鲁智深”

    Push:压栈
    Pop:出栈
    栈的特点是先进后出,后进先出
    队列:

    武松 “杨志” 林冲 “鲁智深”

    队列的特点是:先进先出。
    链表:

    0x999					0x998				0x997
    

    void addFirst(E e)
    将指定元素插入此列表的开头。
    void addLast(E e)
    将指定元素添加到此列表的结尾。
    E
    removeFirst()
    移除并返回此列表的第一个元素。
    E
    removeLast()
    移除并返回此列表的最后一个元素。
    E
    pop()
    从此列表所表示的堆栈处弹出一个元素。
    void push(E e)
    将元素推入此列表所表示的堆栈。

    3.Vector
    和ArrayList功能类似,最主要的区别就在于vector是线程并发安全的。但是缺点是效率比较低。
    B添加(刘唐)
    A添加(白胜)

    2.泛型
    我们在项目中使用集合基本99%都是在集合中存储同一种数据类型。既然我们在集合中存储同一种数据类型,我们事先一定知道这个集合中要存储什么数据类型。我们就可以预先去指定要存储的数据类型。
    1.泛型在集合中的使用
    泛型:就是提前指定要操作的数据类型。
    在集合使用的语法:

    在定义集合的时候
    List<数据类型> 变量名 = new ArrayList<数据类型>();
    示例代码:
    package com.rl.generic;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;

    public class ArrayListDemo1 {
    public static void main(String[] args) {
    method1();
    }
    public static void method(){
    //al集合中只允许存储字符串的数据类型。
    List al = new ArrayList();
    al.add(“张三”);
    al.add(“李四”);
    al.add(“王五”);
    /al.add(1);
    al.add(new Student(“李逵”,25));
    /
    //集合的迭代器也要指定泛型
    Iterator iter = al.iterator();
    while(iter.hasNext()){
    //java.lang.ClassCastException:
    //如果已经指定了泛型,从集合中取值时就不需要强制转换了
    String result = iter.next();
    System.out.println(result);
    }
    }
    public static void method1(){
    //al集合中只允许存储字符串的数据类型。
    List al = new ArrayList();
    al.add(new Student(“李逵”,25));
    al.add(new Student(“张飞”,35));

    	Iterator<Student> iter = al.iterator();
    	while(iter.hasNext()){
    		//java.lang.ClassCastException:
    		Student result = iter.next();
    		System.out.println(result);
    	}
    }
    

    }
    2.自定义泛型
    在自定义泛型时
    语法:class/interface 类名/接口名 {

    }
    T只是泛型的一个标准,使用什么字符都可以,但是都要大写,不要使用特殊字符,建议用T。
    泛型定义代码:
    package com.rl.generic;
    public class GenericTest {
    private E t;
    public E getT() {
    return t;
    }
    public void setT(E t) {
    this.t = t;
    }
    }
    实现代码:
    package com.rl.generic;
    import java.util.ArrayList;
    import java.util.List;
    public class StudentDaoImpl implements BaseDao {
    List sList = new ArrayList();
    public void save(Student t) {
    sList.add(t);
    }
    public Student getT(Integer id) {
    return sList.get(id);
    }
    public List listT() {
    return sList;
    }
    }
    测试:
    package com.rl.generic;
    public class Test {
    public static void main(String[] args) {
    //设置泛型为Integer
    GenericTest gt = new GenericTest();
    gt.setT(20);
    Integer num = gt.getT();
    System.out.println(num);
    System.out.println("--------------------------");
    //设置泛型为String
    GenericTest gt1 = new GenericTest();
    gt1.setT(“张三”);
    String result = gt1.getT();
    System.out.println(result);
    }
    }

    3.增强的For循环
    在Jdk1.5以后出现了增强的for
    对数组,集合来做遍历
    语法:
    for(数据类型 变量:集合变量){
    ///
    }
    package com.rl.forp;
    import java.util.ArrayList;
    import java.util.List;
    public class ForDemo {
    public static void main(String[] args) {
    String[] ss = {“张三”,“李四”,“王五”};
    for(int i = 0; i < ss.length; i++){
    System.out.println(ss[i]);
    }
    System.out.println("-------------------------");
    //冒号左边是集合或者数组中的数据类型和变量,冒号右边是数组或者集合的变量
    for(String str:ss){
    System.out.println(str);
    }
    System.out.println("-------------------------");
    List iList = new ArrayList();
    iList.add(1);
    iList.add(2);
    iList.add(3);
    for(Integer i : iList){
    System.out.println(i);
    }
    System.out.println("--------------------------");
    List sList = new ArrayList();
    sList.add(new Student(“李逵”,30));
    sList.add(new Student(“李鬼”,40));
    for(Student s : sList){
    System.out.println(s);
    }
    System.out.println("-------------------------");
    List ss1 = new ArrayList();
    ss1.add(“鲁智深”);
    ss1.add(“史进”);
    ss1.add(“李忠”);
    //冒号左边是集合或者数组中的数据类型和变量,冒号右边是数组或者集合的变量
    for(String str:ss1){
    //java.util.ConcurrentModificationException
    if(“李忠”.equals(str)){
    ss1.add(“周通”);
    }
    System.out.println(str);
    }
    }
    }
    特点:遍历时存在并发问题。
    4.Set集合

    一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。

    Set里面的方法绝大多数都是继承于Collection,所以set基本学完。
    Set的特点:
    元素不可重复
    元素无序的(跟添加的顺序无关)
    package com.rl.set;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    import com.rl.listson.Student;
    public class SetDemo {
    public static void main(String[] args) {
    method2();
    }
    public static void method(){
    //定义一个set集合
    Set set = new HashSet();
    set.add(“任亮”);
    set.add(“孙坚”);
    set.add(“孙坚”);
    set.add(“袁绍”);
    //set可以去除重复的元素,无序的
    System.out.println(set);
    Iterator iter = set.iterator();
    while(iter.hasNext()){
    String result = iter.next();
    System.out.println(result);
    }
    }
    public static void method1(){
    //定义一个set集合
    Set set = new HashSet();
    set.add(new Student(“林冲”,30));
    set.add(new Student(“鲁智深”,32));
    set.add(new Student(“史文恭”,35));
    set.add(new Student(“卢俊义”,35));
    //set可以去除重复的元素,无序的
    System.out.println(set);
    Iterator iter = set.iterator();
    while(iter.hasNext()){
    Student result = iter.next();
    System.out.println(result);
    }
    }
    public static void method2(){
    //定义一个set集合
    Set set = new HashSet();
    set.add(new Student(“林冲”,30));
    set.add(new Student(“鲁智深”,32));
    set.add(new Student(“史文恭”,35));
    set.add(new Student(“卢俊义”,35));
    for(Student stu : set){
    System.out.println(stu);
    }
    }
    }

    1.Set的实现类HashSet
    此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

    HashSet的唯一性:
    在HashSet做添加的时候会逐个来判断当前集合中的对象和要添加的对象的比较
    通过以下的条件判断两个对象是否相等
    * e.hash == hash && ((k = e.key) == key || key.equals(k))
    * hash值必须相等并且两个对象的地址值相等或者equals返回true
    注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

    package com.rl.set;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    import com.rl.listson.Student;
    public class HashSetDemo {
    public static void main(String[] args) {
    method2();
    }
    /**
    * 通过以下的条件判断两个对象是否相等
    * e.hash == hash && ((k = e.key) == key || key.equals(k))
    * hash值必须相等并且两个对象的地址值相等或者equals返回true
    * @author renliang
    */
    public static void method2(){
    //定义一个set集合
    HashSet set = new HashSet();
    set.add(new Student(“林冲”,30));
    set.add(new Student(“鲁智深”,32));
    set.add(new Student(“史文恭”,35));
    set.add(new Student(“卢俊义”,35));
    set.add(new Student(“林冲”,30));
    set.add(new Student(“林冲”,30));
    set.add(null);
    set.add(null);
    for(Student stu : set){
    System.out.println(stu);
    }
    }
    }

    Student
    package com.rl.listson;
    public class Student {
    private String name;
    private Integer age;
    public Student(String name, Integer age) {
    super();
    this.name = name;
    this.age = age;
    }
    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 toString() {
    return “Student [name=” + name + “, age=” + age + “]”;
    }
    public boolean equals(Object obj) {
    if(!(obj instanceof Student)){
    return false;
    }
    Student stu = (Student) obj;
    if(stu != null && stu.getName().equals(this.name) && stu.getAge() == this.age){
    return true;
    }
    return false;
    }
    public int hashCode() {
    return 1;
    }
    }

    特点:
    1.元素唯一性
    2.无序行
    3.允许null存在一个
    4.不是线程安全(效率高)
    2.set的实现类LinkedHashSet
    具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
    有序
    package com.rl.set;
    import java.util.LinkedHashSet;
    import com.rl.listson.Student;
    public class LinkedHashSetDemo {
    public static void main(String[] args) {
    method2();
    }
    /**
    * 使用LinkedHashSet可以保证添加的顺序
    * @author renliang
    */
    public static void method2(){
    //定义一个set集合
    LinkedHashSet set = new LinkedHashSet();
    set.add(new Student(“林冲”,30));
    set.add(new Student(“鲁智深”,32));
    set.add(new Student(“史文恭”,35));
    set.add(new Student(“卢俊义”,35));
    for(Student stu : set){
    System.out.println(stu);
    }
    }
    }
    输出:
    Student [name=林冲, age=30]
    Student [name=鲁智深, age=32]
    Student [name=史文恭, age=35]
    Student [name=卢俊义, age=35]
    特点:
    1.元素唯一性
    2.有序的
    3.允许null存在一个
    4.不是线程安全(效率高)

    3.Set的实现类TreeSet
    TreeSet可以支持自定义排序,如果TreeSet所存储的对象的类没有实现Comparable接口就会报错ClassCastException。所以我们如果想要使用TreeSet来对自定义的对象来排序必须实现Comparable接口。
    示例:代码
    package com.rl.set;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.TreeSet;
    import com.rl.listson.Student;
    public class TreeSetDemo {
    public static void main(String[] args) {
    method1();
    }
    public static void method(){
    TreeSet set = new TreeSet();
    //TreeSet在做添加的时候会比较字符串的大小,调用String中的compareTo的方法来比较
    set.add(“zhangsan”);
    set.add(“lisi”);
    set.add(“wangwu”);
    set.add(“zhangming”);

    	System.out.println(set);
    }
    /**
     * TreeSet唯一性的规则使用的是compareTo的方式
     * @author renliang
     */
    public static void method1(){
    	TreeSet<Student> set = new TreeSet<Student>();
    	//TreeSet在做添加的时候会比较字符串的大小,调用String中的compareTo的方法来比较
    	set.add(new Student("zhangsan", 30));
    	set.add(new Student("lisi", 25));
    	set.add(new Student("wangwu",40));
    	set.add(new Student("zhangming", 25));		
    	for(Student stu : set){
    		System.out.println(stu);
    	}
    }
    

    }
    代码Student:
    package com.rl.listson;
    public class Student implements Comparable{
    private String name;
    private Integer age;
    public Student(String name, Integer age) {
    super();
    this.name = name;
    this.age = age;
    }
    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 toString() {
    return “Student [name=” + name + “, age=” + age + “]”;
    }
    public boolean equals(Object obj) {
    if(!(obj instanceof Student)){
    return false;
    }
    Student stu = (Student) obj;
    if(stu != null && stu.getName().equals(this.name) && stu.getAge() == this.age){
    return true;
    }
    return false;
    }
    public int hashCode() {
    return 1;
    }
    public int compareTo(Student o) {
    int num = this.age - o.getAge();
    if(num == 0){
    num = this.getName().compareTo(o.getName());
    }
    return num;
    }
    }
    特点:
    1.元素唯一性
    2.可自定义排序的
    3.不允许null存在
    4.不是线程安全
    5.可变参数
    可变参数的语法:
    修饰符 返回值类型 方法名(数据类型…变量){

    }
    public static int sum(int … p){
    return 0;
    }
    注意:参数p实际是一个数组,p都是同一种类型
    package com.rl.dynamic.param;
    public class DynamicParamTest {

    public static void main(String[] args) {
    	System.out.println(sum(1,2, 2, 8));
    }
    /*public static int sum(int a , int b){
    	return a + b;
    }
    public static int sum(int a , int b, int c){
    	return a + b +c;
    }
    public static int sum(int a , int b, int c, int d){
    	return a + b +c +d;
    }*/	
    /**
     * 可变参数方法的定义
     * @author renliang
     * @param p
     * @return
     */
    public static int sum(int ... p){
    	int sumNum = 0;
    	for(int i = 0; i < p.length; i++){
    		sumNum += p[i];
    	}
    	return sumNum;
    }
    

    }
    6.工具类Arrays
    数组的工具类,这里的方法都是静态的
    要掌握的功能:
    1.把数组转换成字符串
    static String
    toString(boolean[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(byte[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(char[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(double[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(float[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(int[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(long[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(Object[] a)
    返回指定数组内容的字符串表示形式。
    static String
    toString(short[] a)
    返回指定数组内容的字符串表示形式
    2.对任意数组排序
    static void sort(byte[] a)
    对指定的 byte 型数组按数字升序进行排序。
    static void sort(byte[] a, int fromIndex, int toIndex)
    对指定 byte 型数组的指定范围按数字升序进行排序。
    static void sort(char[] a)
    对指定的 char 型数组按数字升序进行排序。
    static void sort(char[] a, int fromIndex, int toIndex)
    对指定 char 型数组的指定范围按数字升序进行排序。
    static void sort(double[] a)
    对指定的 double 型数组按数字升序进行排序。
    static void sort(double[] a, int fromIndex, int toIndex)
    对指定 double 型数组的指定范围按数字升序进行排序。
    static void sort(float[] a)
    对指定的 float 型数组按数字升序进行排序。
    static void sort(float[] a, int fromIndex, int toIndex)
    对指定 float 型数组的指定范围按数字升序进行排序。
    static void sort(int[] a)
    对指定的 int 型数组按数字升序进行排序。
    static void sort(int[] a, int fromIndex, int toIndex)
    对指定 int 型数组的指定范围按数字升序进行排序。
    static void sort(long[] a)
    对指定的 long 型数组按数字升序进行排序。
    static void sort(long[] a, int fromIndex, int toIndex)
    对指定 long 型数组的指定范围按数字升序进行排序。
    static void sort(Object[] a)
    根据元素的自然顺序对指定对象数组按升序进行排序。

    static void sort(Object[] a, int fromIndex, int toIndex)
    根据元素的自然顺序对指定对象数组的指定范围按升序进行排序。
    static void sort(short[] a)
    对指定的 short 型数组按数字升序进行排序。
    static void sort(short[] a, int fromIndex, int toIndex)
    对指定 short 型数组的指定范围按数字升序进行排序。
    static
    void
    sort(T[] a, Comparator<? super T> c)
    根据指定比较器产生的顺序对指定对象数组进行排序。
    static
    void
    sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
    根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。
    3.对任意的数组做二分法的查找
    static int binarySearch(byte[] a, byte key)
    使用二分搜索法来搜索指定的 byte 型数组,以获得指定的值。
    static int binarySearch(byte[] a, int fromIndex, int toIndex, byte key)
    使用二分搜索法来搜索指定的 byte 型数组的范围,以获得指定的值。
    static int binarySearch(char[] a, char key)
    使用二分搜索法来搜索指定的 char 型数组,以获得指定的值。
    static int binarySearch(char[] a, int fromIndex, int toIndex, char key)
    使用二分搜索法来搜索指定的 char 型数组的范围,以获得指定的值。
    static int binarySearch(double[] a, double key)
    使用二分搜索法来搜索指定的 double 型数组,以获得指定的值。
    static int binarySearch(double[] a, int fromIndex, int toIndex, double key)
    使用二分搜索法来搜索指定的 double 型数组的范围,以获得指定的值。
    static int binarySearch(float[] a, float key)
    使用二分搜索法来搜索指定的 float 型数组,以获得指定的值。
    static int binarySearch(float[] a, int fromIndex, int toIndex, float key)
    使用二分搜索法来搜索指定的 float 型数组的范围,以获得指定的值。
    static int binarySearch(int[] a, int key)
    使用二分搜索法来搜索指定的 int 型数组,以获得指定的值。
    static int binarySearch(int[] a, int fromIndex, int toIndex, int key)
    使用二分搜索法来搜索指定的 int 型数组的范围,以获得指定的值。
    static int binarySearch(long[] a, int fromIndex, int toIndex, long key)
    使用二分搜索法来搜索指定的 long 型数组的范围,以获得指定的值。
    static int binarySearch(long[] a, long key)
    使用二分搜索法来搜索指定的 long 型数组,以获得指定的值。
    static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
    使用二分搜索法来搜索指定数组的范围,以获得指定对象。
    static int binarySearch(Object[] a, Object key)
    使用二分搜索法来搜索指定数组,以获得指定对象。
    static int binarySearch(short[] a, int fromIndex, int toIndex, short key)
    使用二分搜索法来搜索指定的 short 型数组的范围,以获得指定的值。
    static int binarySearch(short[] a, short key)
    使用二分搜索法来搜索指定的 short 型数组,以获得指定的值。
    static
    int
    binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
    使用二分搜索法来搜索指定数组的范围,以获得指定对象。
    static
    int
    binarySearch(T[] a, T key, Comparator<? super T> c)
    使用二分搜索法来搜索指定数组,以获得指定对象。
    把数组转换成List
    static
    List

    asList(T... a) 
          返回一个受指定数组支持的固定大小的列表。
    

    实例代码:
    package com.rl.arrays;
    import java.util.Arrays;
    import java.util.List;
    import com.rl.listson.Student;
    public class ArraysTest1 {
    public static void main(String[] args) {
    //toSortTest();
    toConverterTest();
    }
    public static void toSortTest(){
    Student [] ss = new Student[3];
    ss[0] = new Student(“唐僧”, 30);
    ss[1] = new Student(“悟空”, 500);
    ss[2] = new Student(“八戒”, 200);
    //对自定义对象的数组排序需要自定义对象来定义排序规则,实现comparable接口,实现toCompare方法
    Arrays.sort(ss);
    for(Student s : ss){
    System.out.println(s);
    }
    }
    /**
    * static List asList(T… a)
    * 数组转换成List后,这个list无法删除和新增。
    * @author renliang
    /
    public static void toConverterTest(){
    Integer [] arr = {13, 44, 41, 8, 10};
    //从数组转换成list时候int自动装箱失效了
    List iList = Arrays.asList(arr);
    //java.lang.UnsupportedOperationException
    //iList.add(99);
    //iList.remove(0);
    iList.set(1, 55);
    System.out.println(iList);
    }
    }
    7.工具类Collections
    面试题:
    问:Collection和Collections的区别:
    前者是集合的接口
    后者操作集合的工具类
    package com.rl.collections;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    public class CollectionsDemo {
    public static void main(String[] args) {
    //sortTest();
    //binarySearchTest();
    //maxOrMinTest();
    //reverseTest();
    shuffleTest();
    }
    /
    *
    * 对list的排序
    * @author renliang
    /
    public static void sortTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    Collections.sort(list);
    System.out.println(list);
    }
    /
    *
    * 二分法查找
    * @author renliang
    /
    public static void binarySearchTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    Collections.sort(list);
    System.out.println(list);
    Integer index = Collections.binarySearch(list, 33);
    System.out.println(index);
    }
    /
    *
    * 在集合中找极值
    * @author renliang
    */
    public static void maxOrMinTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    //Integer maxNum = Collections.max(list);
    Integer minNum = Collections.min(list);
    System.out.println(minNum);
    }
    public static void reverseTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    System.out.println(list);
    Collections.reverse(list);
    System.out.println(list);
    }
    public static void shuffleTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    System.out.println(list);
    Collections.shuffle(list);
    System.out.println(list);
    }
    public static void synTest(){
    List list = new ArrayList();
    list.add(33);
    list.add(19);
    list.add(24);
    list.add(45);
    //把list集合变成线程安全的,效率会变低。
    List iList = Collections.synchronizedList(list);
    }
    }
    Javase中Map集合
    1.Map概述
    Map即使键值对的集合的接口抽象。

    Key1 Key2 Key3
    Value1 Value2 Value3
    我们可以通过key的值来获得相应的值,将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。键只允许有一个空值,值可以有多个空值。

    Map集合和之前学过的Collection接口无关。

    Map的特点:
    1.数据成对出现
    2.数据的键是唯一的
    3.一个键只能对应一个值
    4.值可以重复
    5.键允许有一个为空,值可以多个是空。

    面试题:
    问:map集合和Collection集合的区别?
    答:1.Map集合是键值对的集合,Collection是单一出现的数据的集合
    2.Map的键唯一的,而Collection的子接口List集合中的元素是可以重复的,set是唯一的
    3.map是夫妻对,Collection是光棍。
    2.map的功能

    添加功能
    V
    put(K key, V value)
    将指定的值与此映射中的指定键关联(可选操作)。
    void putAll(Map<? extends K,? extends V> m)
    从指定映射中将所有映射关系复制到此映射中(可选操作)。

    2.删除功能
    void clear()
    从此映射中移除所有映射关系(可选操作)。
    V
    remove(Object key)
    如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

    3.获取功能
    V
    get(Object key)
    返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
    Set
    keySet()
    返回此映射中包含的键的 Set 视图。
    Collection
    values()
    返回此映射中包含的值的 Collection 视图。

    int size()
    返回此映射中的键-值映射关系数。

    4.判断功能
    boolean containsKey(Object key)
    如果此映射包含指定键的映射关系,则返回 true。
    boolean containsValue(Object value)
    如果此映射将一个或多个键映射到指定值,则返回 true。
    boolean isEmpty()
    如果此映射未包含键-值映射关系,则返回 true
    5.遍历
    Set<Map.Entry<K,V>>
    entrySet()
    返回此映射中包含的映射关系的 Set 视图。

    实例代码:
    package com.rl.map;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    public class MapTest {
    public static void main(String[] args) {
    //deleteTest();
    //getTest();
    //keySetTest();
    //valuesTest();
    //updateTest();
    //isTest();
    loopTest();
    }
    public static void putTest(){
    //创建map的实例的集合对象
    Map<String, String> map = new HashMap<String, String>();
    map.put(“1000”, “王伦”);
    map.put(“2000”, “杜迁”);
    map.put(“3000”, “朱贵”);
    System.out.println(map);
    Map<String, String> map1 = new HashMap<String, String>();
    map.put(“4000”, “晁盖”);
    map.put(“5000”, “吴用”);
    map.put(“6000”, “阮氏三雄”);
    //把map1集合的内容加入到map中
    map.putAll(map1);
    System.out.println(map);
    }
    /**
    * put的修改
    * @author renliang
    /
    public static void updateTest(){
    //创建map的实例的集合对象
    Map<String, String> map = new HashMap<String, String>();
    map.put(“1000”, “王伦”);
    map.put(“2000”, “杜迁”);
    map.put(“3000”, “朱贵”);
    //如果做重复的key的put就会覆盖前面的数据
    map.put(“2000”, “摸着天”);
    System.out.println(map);
    }
    /
    *
    * map的删除
    * @author renliang
    */
    public static void deleteTest(){
    //创建map的实例的集合对象
    Map<String, String> map = new HashMap<String, String>();
    map.put(“1000”, “王伦”);
    map.put(“2000”, “杜迁”);
    map.put(“3000”, “朱贵”);

    	System.out.println(map);
    	//情况map
    	/*map.clear();
    	System.out.println(map);*/
    	String value = map.remove("1000");
    	System.out.println("删除的元素:"+value);
    	System.out.println(map);
    }
    /**
     * 获取功能
     * @author renliang
     */
    public static void getTest(){
    	//创建map的实例的集合对象
    	Map<String, String> map = new HashMap<String, String>();
    	map.put("1000", "王伦");
    	map.put("2000", "杜迁");
    	map.put("3000", "朱贵");
    	//在map中根据key来查询值
    	/*String value = map.get("4000");
    	System.out.println("获得的值:"+value);*/
    }
    public static void keySetTest(){
    	//创建map的实例的集合对象
    	Map<String, String> map = new HashMap<String, String>();
    	map.put("1000", "王伦");
    	map.put("2000", "杜迁");
    	map.put("3000", "朱贵");
    	//获得指定的集合的每一个键
    	Set<String> set = map.keySet();
    	System.out.println(set);
    	//根据键的集合来遍历map
    	for(String key : set){
    		String value = map.get(key);
    		System.out.println("键是:"+key+" 值是:"+value);
    	}
    }
    public static void valuesTest(){
    	//创建map的实例的集合对象
    	Map<String, String> map = new HashMap<String, String>();
    	map.put("1000", "王伦");
    	map.put("2000", "杜迁");
    	map.put("3000", "朱贵");
    	//map集合中的元素个数
    	int length = map.size();
    	System.out.println("map的长度:"+length);
    	Collection<String> coll = map.values();
    	System.out.println(coll);
    }
    /**
     * map的判断功能
     * @author renliang
     */
    public static void isTest(){
    	//创建map的实例的集合对象
    	Map<String, String> map = new HashMap<String, String>();
    	map.put("1000", "王伦");
    	map.put("2000", "杜迁");
    	map.put("3000", "朱贵");
    	//map集合中的元素个数
    	boolean isExist = map.containsKey("4000");
    	System.out.println(isExist);
    	//判断map中是否存在某个值
    	boolean isExistVal = map.containsValue("林冲");
    	System.out.println(isExistVal);
    	map.clear();
    	//判断map中的内容是不是空
    	boolean isEmpty = map.isEmpty();
    	System.out.println(isEmpty);
    }
    public static void loopTest(){
    	//创建map的实例的集合对象
    	Map<String, String> map = new HashMap<String, String>();
    	map.put("1000", "王伦");
    	map.put("2000", "杜迁");
    	map.put("3000", "朱贵");
    	/*Set<String> set = map.keySet();
    	for(String key : set){
    		String value = map.get(key);
    		System.out.println("key:"+key+ " value:"+value);
    	}*/
    	//获得 的Entry映射想的集合
    	Set<Entry<String, String>> set = map.entrySet();
    	//如果在Map.Entry它的后面对集合进行修改,那么就会同步到Entry中
    	//map.put("4000", "杨志");
    	map.remove("1000");
    	for(Entry<String, String> entry : set){
    		
    		
    		//获得键
    		String key = entry.getKey();
    		/*if("3000".equals(key)){
    			map.put("4000", "杨志");
    		}*/	
    		//根据映射想来获得的值
    		String value = entry.getValue();
    		System.out.println("key: "+key+ "  value:"+value);
    	}	
    }
    

    }

    3.map的实现类HashMap
    HashMap的特点
    1.HashMap是map的实现类
    2.允许多个null值和一个null键
    3.HashMap中的元素没有顺序(跟添加的顺序无关)
    4.HashMap不是线程安全的。
    package com.rl.map.impl;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map.Entry;
    import java.util.Set;
    public class HashMapDemo {
    public static void main(String[] args) {
    //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
    //HashMap<String, Object> hm = new HashMap<String,Object>();
    HashMap<String, Person> hm = new HashMap<String,Person>();
    hm.put(“神行太保”, new Person(“戴宗”, 32));
    hm.put(“浪里白条”, new Person(“张顺”, 25));
    hm.put(“及时雨”, new Person(“宋江”, 30));
    //只允许一个null键
    hm.put(null, new Person(“李鬼”, 40));
    hm.put(null, new Person(“张三”, 15));
    hm.put(“白衣秀士”, null);
    hm.put(“活阎罗”, null);
    Set<Entry<String, Person>> set = hm.entrySet();
    Iterator<Entry<String, Person>> iter = set.iterator();
    while(iter.hasNext()){
    Entry<String, Person> entry = iter.next();
    String key = entry.getKey();
    Person value = entry.getValue();
    System.out.println(“绰号:”+key + " 真人:"+value);
    }
    }
    }
    4.map的实现类TreeMap
    TreeMap可以参考TreeSet,TreeMap可以支持Map的排序。
    package com.rl.map.impl;
    import java.util.Iterator;
    import java.util.Map.Entry;
    import java.util.Set;
    import java.util.TreeMap;
    public class TreeMapDemo {
    public static void main(String[] args) {
    //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
    //HashMap<String, Object> hm = new HashMap<String,Object>();
    TreeMap<Person, String> hm = new TreeMap<Person,String>();
    hm.put(new Person(“戴宗”, 32), “神行太保”);
    hm.put(new Person(“张顺”, 25),“浪里白条”);
    hm.put(new Person(“宋江”, 30),“及时雨”);
    //只允许一个null键
    Set<Entry<Person, String>> set = hm.entrySet();
    Iterator<Entry<Person, String>> iter = set.iterator();
    while(iter.hasNext()){
    Entry<Person, String> entry = iter.next();
    Person key = entry.getKey();
    String value = entry.getValue();
    System.out.println(“绰号:”+value + " 真人:"+key);
    }
    }
    }
    5.map的实现类HashTable
    HashTable的特点

    1. HashTable是map的实现类
      2.不允许任何null值和null键

    2. HashTable中的元素没有顺序(跟添加的顺序无关)

    3. HashTable是线程安全的。
      package com.rl.map.impl;
      import java.util.Hashtable;
      import java.util.Iterator;
      import java.util.Map.Entry;
      import java.util.Set;
      public class HashTableDemo {
      public static void main(String[] args) {
      //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
      //HashMap<String, Object> hm = new HashMap<String,Object>();
      Hashtable<String, Person> hm = new Hashtable<String,Person>();
      hm.put(“神行太保”, new Person(“戴宗”, 32));
      hm.put(“浪里白条”, new Person(“张顺”, 25));
      hm.put(“及时雨”, new Person(“宋江”, 30));
      //只允许一个null键
      //hm.put(null, new Person(“李鬼”, 40));
      //hm.put(null, new Person(“张三”, 15));
      //hm.put(“白衣秀士”, null);
      //hm.put(“活阎罗”, null);
      Set<Entry<String, Person>> set = hm.entrySet();
      Iterator<Entry<String, Person>> iter = set.iterator();
      while(iter.hasNext()){
      Entry<String, Person> entry = iter.next();
      String key = entry.getKey();
      Person value = entry.getValue();
      System.out.println(“绰号:”+key + " 真人:"+value);
      }
      }
      }
      6.map的实现类LinkedHashMap
      LinkedHashMap
      的特点

    4. LinkedHashMap是map的实现类
      2.允许多个null值和一个null键

    5. LinkedHashMap有顺序(添加的顺序)

    6. LinkedHashMap不是线程安全的。
      package com.rl.map.impl;
      import java.util.Iterator;
      import java.util.LinkedHashMap;
      import java.util.Map.Entry;
      import java.util.Set;
      public class LinkedHashMapDemo {
      public static void main(String[] args) {
      //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
      //HashMap<String, Object> hm = new HashMap<String,Object>();

       LinkedHashMap<String, Person> hm = new LinkedHashMap<String,Person>();
       hm.put("神行太保", new Person("戴宗", 32));
       hm.put("浪里白条", new Person("张顺", 25));
       hm.put("及时雨", new Person("宋江", 30));
       hm.put(null, new Person("李鬼", 40));
       hm.put(null, new Person("张三", 15));
       hm.put("白衣秀士", null);
       hm.put("活阎罗", null);
       
       Set<Entry<String, Person>> set = hm.entrySet();
       Iterator<Entry<String, Person>> iter =  set.iterator();
       while(iter.hasNext()){
       	Entry<String, Person> entry = iter.next();
       	String key = entry.getKey();
       	Person value = entry.getValue();
       	System.out.println("绰号:"+key + "   真人:"+value);
       }
      

      }
      }
      Javase中文件详解和IO流
      1.IO概述
      IO(Input/Output):输入和输出,指的是某个设备或环境进行数据的输入或者输出。例如:键盘的输入,再比如显示器就是输出设备,输出图像。
      对于java来说输入输出问题,java将它抽象成流对象来解决。
      以游戏程序为中心读取文件就是输入,写入文件是输出。

       					读取文件(输入)
      
      
      
       					写入文件(输出)
      

    IO流在java中从输入输出角度分类:
    1.输入流
    2.输出流
    IO流在java中从数据的角度来分类:
    1.字符流
    文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
    2.字节流
    二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。
    2.File类
    1.File的构造器
    我们操作系统中所有的设备的体现都是文件(包含文件夹),java对文件做了抽象,在java中IO包提供了文件的操作的功能。
    1.File的构造器
    File(File parent, String child)
    根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
    File(String pathname)
    通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
    File(String parent, String child)
    根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
    File(URI uri)
    通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
    实例代码:
    package com.rl.file;
    import java.io.File;
    public class FileDemo {
    public static void main(String[] args) {
    //如果使用正/来指定文件的路径需要使用\
    File file = new File(“d:\demo.txt”);
    File file1 = new File(“d:/demo.txt”);
    System.out.println(file1);
    System.out.println("------------------");
    //创建文件的第二种方式,第一个参数是文件所在的路径,第二个是文件名
    File file2 = new File(“d:/”, “demo.txt”);
    System.out.println(file2);
    System.out.println("---------------------");
    //在java中把文件和文件夹都抽象为File
    //创建一个文件夹的File对象
    File fileDir = new File(“d:/”);
    File file3 = new File(fileDir, “demo.txt”);
    System.out.println(file3);
    }
    }
    2.文件的创建
    创建文件
    boolean createNewFile()
    当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
    创建目录
    boolean mkdir()
    创建此抽象路径名指定的目录。
    boolean mkdirs()
    创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

    示例代码:
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    public class FileDemo1 {
    public static void main(String[] args) throws IOException {
    createDir();
    }
    /**
    * 创建文件
    * @author renliang
    * @throws IOException
    /
    public static void createFile() throws IOException{
    //使用绝对路径来创建File对象
    File file = new File(“d:/a.txt”);
    //创建文件,如果当前目录下的文件不存在的时候可以创建,如果文件已经存在则会创建失败
    boolean isSuccess = file.createNewFile();
    System.out.println(“a文件创建是否成功:”+isSuccess);
    System.out.println("----------------------------");
    //使用相对路径来创建文件,不指定绝对路径,在eclipse的工程中所创建的文件就直接在当前的工程目录下
    File file1 = new File(“b.txt”);
    boolean isSuccessb = file1.createNewFile();
    System.out.println(“b文件创建是否成功:”+isSuccessb);
    //可以根据相对路径来在我们项目工程中来创建文件
    File file2 = new File(“src/com/rl/file/c.txt”);
    boolean isSuccessc = file2.createNewFile();
    System.out.println(“b文件创建是否成功:”+isSuccessc); System.out.println("---------------------------------------------");
    }
    /
    *
    * 创建文件夹
    * @author renliang
    * @throws IOException
    /
    public static void createDir() throws IOException{
    //创建文件夹
    /File filed = new File(“a”);
    boolean isSuccessd = filed.mkdir();
    System.out.println(“创建目录是否成功:”+isSuccessd);
    /
    /
    //创建文件夹
    File filed = new File(“a/b”);
    //mkdir是单级目录的创建,如果是多级前面的目录必须存在:如a目录必须存在,才可能创建b
    boolean isSuccessd = filed.mkdir();
    System.out.println(“创建目录是否成功:”+isSuccessd);*/

    	//创建文件夹
    	File filed1 = new File("c/d/e");
    	//mkdir是单级目录的创建,如果是多级前面的目录必须存在:如a目录必须存在,才可能创建b
    	boolean isSuccessd1 = filed1.mkdirs();
    	System.out.println("创建多级目录是否成功:"+isSuccessd1);
    }
    

    }
    3.文件的删除
    boolean delete()
    删除此抽象路径名表示的文件或目录。
    这个方法可以删除文件和目录
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    public class FileDemo2 {
    public static void main(String[] args) throws IOException {
    deleteDir();
    }
    /**
    * 删除文件
    * @author renliang
    * @throws IOException
    /
    public static void deleteFile() throws IOException{
    File fileb = new File(“src/com/rl/file/c.txt”);
    //如果本身b文件不存在或者这个文件正在被使用那么就false,否则是true
    boolean isDelete = fileb.delete();
    System.out.println(“文件是否删除:”+isDelete);
    }
    /
    *
    * 删除目录
    * @author renliang
    * @throws IOException
    /
    public static void deleteDir() throws IOException{
    File file = new File(“c/a.txt”);
    file.delete();
    //目录删除时,如果目录中有文件则必须先删除文件再删除目录
    File fileb = new File(“c”);
    //如果本身b文件不存在或者这个文件正在被使用那么就false,否则是true
    boolean isDelete = fileb.delete();
    System.out.println(“文件夹是否删除:”+isDelete);
    }
    }
    4.文件的重命名和判断功能
    1.重命名
    2.判断
    boolean exists()
    测试此抽象路径名表示的文件或目录是否存在。
    boolean isFile()
    测试此抽象路径名表示的文件是否是一个标准文件。
    boolean isDirectory()
    测试此抽象路径名表示的文件是否是一个目录。
    boolean isAbsolute()
    测试此抽象路径名是否为绝对路径名。
    boolean canRead()
    测试应用程序是否可以读取此抽象路径名表示的文件。
    boolean canWrite()
    测试应用程序是否可以修改此抽象路径名表示的文件。
    boolean isHidden()
    测试此抽象路径名指定的文件是否是一个隐藏文件。
    示例代码:
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    public class FileDemo3 {
    public static void main(String[] args) throws IOException {
    //renameFile();
    justfy();
    }
    /
    *
    * 文件重命名
    * @author renliang
    * @throws IOException
    /
    public static void renameFile() throws IOException{
    File fileb = new File(“c.txt”);
    fileb.createNewFile();
    File fileNew = new File(“b.txt”);
    System.out.println(“重命名:”+fileb.renameTo(fileNew));
    }
    /
    *
    *
    * @author renliang
    * @throws IOException
    /
    public static void justfy() throws IOException{
    File file = new File(“d:/aa.txt”);
    if(!file.exists()){
    file.createNewFile();
    }
    System.out.println(“是否存存在:”+file.exists());
    System.out.println(“是否存是文件:”+file.isFile());
    System.out.println(“是否存是目录:”+file.isDirectory());
    System.out.println(“是否存是绝对路径:”+file.isAbsolute());
    System.out.println(“是否存是可读:”+file.canRead());
    System.out.println(“是否存是可写:”+file.canWrite());
    System.out.println(“是否存是隐藏:”+file.isHidden());
    }
    }
    5.文件的获取功能
    1.文件的属性获取
    String
    getAbsolutePath()
    返回此抽象路径名的绝对路径名字符串。
    String
    getPath()
    将此抽象路径名转换为一个路径名字符串。
    String
    getName()
    返回由此抽象路径名表示的文件或目录的名称。
    long length()
    返回由此抽象路径名表示的文件的长度。
    long lastModified()
    返回此抽象路径名表示的文件最后一次被修改的时间。
    示例代码:
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class FileDemo4 {
    public static void main(String[] args) throws IOException {
    //renameFile();
    getTest();
    }
    /
    *
    *
    * @author renliang
    * @throws IOException
    */
    public static void getTest() throws IOException{
    File file = new File(“aa.txt”);
    if(!file.exists()){
    file.createNewFile();
    }
    System.out.println(“文件的绝对路径:”+file.getAbsolutePath());
    System.out.println(“文件的相对路径:”+file.getPath());
    System.out.println(“文件的名字:”+file.getName());
    System.out.println(“文件的大小:”+file.length());
    long lasttimes = file.lastModified();
    //创建时间的对象
    Date date = new Date(lasttimes);
    //创建时间格式化的对象
    SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
    //格式化时间
    String lastModifyTime = sdf.format(date);
    System.out.println(“文件的最后修改时间:”+lastModifyTime);
    }
    }

    2.目录的子文件获取
    static File[]
    listRoots()
    列出可用的文件系统根。
    File[]
    listFiles()
    返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
    String[]
    list()
    返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
    示例代码:
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class FileDemo5 {
    public static void main(String[] args) throws IOException {
    //getRoot();
    //getList();
    getFile();
    }
    /**
    *
    * @author renliang
    * @throws IOException
    /
    public static void getRoot() throws IOException{
    //获得系统的跟目录
    File[] files = File.listRoots();
    for(File file : files){
    System.out.println(file.isDirectory());
    System.out.println(file.getAbsolutePath());
    }
    }
    public static void getList() throws IOException{
    File file = new File(“E:\我的课程\任亮”);
    if(file.isAbsolute()){
    //获得文件夹下的每一个文件和文件夹的名字
    String [] names = file.list();
    for(String name : names){
    System.out.println(name);
    }
    }
    }
    public static void getFile() throws IOException{
    File file = new File(“E:\我的课程\任亮”);
    if(file.isAbsolute()){
    //获得文件夹下的每一个文件和文件夹的名字
    File [] files = file.listFiles();
    for(File file1 : files){
    System.out.println(“文件名:”+file1.getName()+ “\t 绝对路径:”+file1.getAbsolutePath());
    }
    }
    }
    }
    3.递归查询文件夹的内部所有文件
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class FileDemo7 {
    //文件夹的级别
    static int level = 0;
    public static void main(String[] args) throws IOException {
    File file = new File(“E:\我的课程\任亮\任亮-1-java基础阶段2\第13天集合”);
    listFile(file);
    }
    public static void listFile(File file){
    File [] files = file.listFiles();
    level++;
    for(File file1 : files){
    for(int i = 0; i < level; i++){
    System.out.print("\t");
    }
    System.out.println(file1.getName());
    //如果当前的文件是目录
    if(file1.isDirectory()){
    //递归调用我们函数自己
    listFile(file1);
    }
    }
    level–;
    }
    }
    如何使用递归的方式计算阶乘?
    5!= 5
    4321

    N!= n
    (n-1)!
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class DiGuiDemo7 {
    public static void main(String[] args) throws IOException {
    int num = f(5);
    System.out.println(num);
    }
    /**
    * 递归要有跳出的条件
    * @author renliang
    * @param n
    * @return
    /
    public static int f(int n){
    if(n == 1){
    return 1;
    }else{
    //5
    4321
    return n
    f(n-1);
    }
    }
    }

    如何删除一个文件夹下的所有文件(不包括目录)?
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class FileDemo9 {
    public static void main(String[] args) {
    File file = new File(“d:/wsCode/a”);
    deleteFileAll(file);
    System.out.println(“deleted”);
    }
    /**
    * 删除指定文件夹下的所有文件(不包括目录)
    * @author renliang
    * @param file
    /
    public static boolean deleteFileAll(File file){
    if(!file.exists()){
    return false;
    }
    if(file.isFile()){
    return false;
    }else{
    //获得目录下的所有文件对象
    File[] files = file.listFiles();
    for(File file1 : files){
    if(file1.isDirectory()){
    //如果是目录就递归
    deleteFileAll(file1);
    }else{
    //如果是文件就删除
    file1.delete();
    }
    }
    return true;
    }
    }
    }
    如何删除一个文件夹下的所有文件(包括目录)?
    package com.rl.file;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class FileDemo10 {
    public static void main(String[] args) {
    File file = new File(“d:/wsCode/a”);
    deleteFolder(file);
    System.out.println(“deleted”);
    }
    /
    *
    * 删除空文件夹
    * @author renliang
    * @param file
    /
    public static void deleteFolder(File file){
    //删除文件夹内的所有文件和文件夹
    deleteFileAll(file);
    //删除空文件夹
    file.delete();
    }
    /
    *
    * 删除指定文件夹下的所有文件(不包括目录)
    * @author renliang
    * @param file
    */
    public static boolean deleteFileAll(File file){
    if(!file.exists()){
    return false;
    }
    if(file.isFile()){
    return false;
    }else{
    //获得目录下的所有文件对象
    File[] files = file.listFiles();
    for(File file1 : files){
    if(file1.isDirectory()){
    //如果是目录就递归
    deleteFileAll(file1);
    //删除file1下的说有文件后就可以删除file1了
    deleteFolder(file1);
    }else{
    //如果是文件就删除
    file1.delete();
    }
    }
    return true;
    }
    }
    }

    3.IO流
    IO流在java中从输入输出角度分类:
    1.输入流:从文件中读取数据,或者从键盘输入数据都属于输入流
    2.输出流:向文件中写入数据。
    IO流在java中从数据的角度来分类:
    1.字符流
    文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
    字符输入流的超类:
    Reader: 子类FileReader,BufferedReader
    字符输出流的超类
    Writer:子类FileWriter,BufferedWriter
    2.字节流
    二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件。

    字节输入流的超类:
    InputStream: 子类FileInputStream
    字节输出流的超类
    OutputStream:子类FileOutputStream
    1.字符流
    1.输出流
    使用字符流向一个文件输入helloworld。
    分析:
    步骤:1.创建文件
    2.创建输出流对象
    3.把流指向指定的文件
    4.释放资源
    1.FileWriter的普通构造器
    输出字符流的FileWriter的构造器
    FileWriter(File file)
    根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(String fileName)
    根据给定的文件名构造一个 FileWriter 对象。
    实例代码:
    package com.rl.io.cha;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    public class IOCharDemo {
    public static void main(String[] args) {
    writerFile1();
    }
    public static void writerFile(){
    //创建文件
    File file = new File(“a.txt”);
    FileWriter fw = null;
    try {
    //创建输出流的对象
    fw = new FileWriter(file);
    //把内容写入文件
    fw.write(“helloworld”);
    //字符流的特点:清空缓存区,把内容写入到文件中
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void writerFile1(){
    FileWriter fw = null;
    try {
    //创建输出流的对象
    fw = new FileWriter(“b.txt”);
    //把内容写入文件
    fw.write(“helloworld”);
    //字符流的特点:清空缓存区,把内容写入到文件中
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }

    向一个文件中输出100个HelloWorld
    package com.rl.io.cha;
    import java.io.FileWriter;
    import java.io.IOException;
    public class IOCharDemo1 {
    public static void main(String[] args) {
    writerFile1();
    }
    public static void writerFile1(){
    FileWriter fw = null;
    try {
    //创建输出流的对象
    fw = new FileWriter(“b.txt”);
    for(int i = 0; i < 100; i++){
    //把内容写入文件
    fw.write(“helloworld”);
    if(i%10 == 0){
    //清空缓存区,把内容写入到文件中
    fw.flush();
    }
    }
    //把 缓冲区中残留的数据写入文件
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    2.FileWriter的追加构造器
    FileWriter(File file, boolean append)
    根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(String fileName, boolean append)
    根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
    示例代码:
    package com.rl.io.cha;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    public class IOCharDemo2 {
    public static void main(String[] args) {
    writerFile1();
    }
    public static void writerFile1(){
    FileWriter fw = null;
    try {
    //创建输出流的追加对象
    //fw = new FileWriter(“b.txt”, true);
    fw = new FileWriter(new File(“b.txt”), true);
    for(int i = 0; i < 100; i++){
    //把内容写入文件
    fw.write(“我爱你”);
    if(i%10 == 0){
    //清空缓存区,把内容写入到文件中
    fw.flush();
    }
    }
    //把 缓冲区中残留的数据写入文件
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    输出换行
    把文本写入文件中\n代表换行
    问题是不同的环境下换行的方式也不一样
    Windows: \r\n
    Linux:\n
    Mac:\r
    package com.rl.io.cha;
    import java.io.FileWriter;
    import java.io.IOException;
    public class IOCharDemo3 {
    public static void main(String[] args) {
    writerFile1();
    }
    public static void writerFile1(){
    FileWriter fw = null;
    try {
    //创建输出流的追加对象
    fw = new FileWriter(“b.txt”);
    for(int i = 0; i < 100; i++){
    //内容换行为了兼容记事本我们建议使用\r\n
    fw.write(“我爱你”+i+"\r\n");
    if(i%10 == 0){
    //清空缓存区,把内容写入到文件中
    fw.flush();
    }
    }
    //把 缓冲区中残留的数据写入文件
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    3.FileWriter的写入功能
    void write(char[] cbuf)
    写入字符数组。
    abstract void write(char[] cbuf, int off, int len)
    写入字符数组的某一部分。
    void write(int c)
    写入单个字符。
    void write(String str)
    写入字符串。
    void write(String str, int off, int len)
    写入字符串的某一部分。

    示例代码:
    package com.rl.io.cha;
    import java.io.FileWriter;
    import java.io.IOException;
    public class IOCharDemo4 {
    public static void main(String[] args) {
    writerFile1();
    }
    public static void writerFile1(){
    FileWriter fw = null;
    try {
    //创建输出流的追加对象
    fw = new FileWriter(“test.txt”);
    char[] chs = {‘a’,‘b’,‘c’,‘d’};
    fw.write(chs);
    //把一部分的字符的数组来写入到文件中,第一个参数是字符数组,第二个是开始索引, 第三个是从开始索引开始取得字符串的长度
    fw.write(chs, 1, 3);
    //通过int值来写入相应的字符
    fw.write(100);
    //写入字符串
    fw.write(“100”);
    //把一部分的字符串来写入到文件中,第一个参数是字符数组,第二个是开始索引, 第三个是从开始索引开始取得字符串的长度
    fw.write(“helloworld”, 2, 2);
    //把 缓冲区中残留的数据写入文件
    fw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    //close关闭输出流时会先清理缓存区
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    2.输入流
    1.FileReader的构造器和读取
    FileReader的爷爷类是Reader
    FileReader(File file)
    在给定从中读取数据的 File 的情况下创建一个新 FileReader。
    FileReader(String fileName)
    在给定从中读取数据的文件名的情况下创建一个新 FileReader。
    范例:读取文件helloworld.txt打印到控制台
    分析:
    1.创建出入流对象FileReader
    2.读取数据
    3.关闭输入流
    package com.rl.io.cha.reader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    public class IOCharReaderDemo {
    public static void main(String[] args) {
    readFile();
    }
    public static void readFile(){
    FileReader fr = null;
    try {
    //创建fileReader对象
    fr = new FileReader(new File(“helloworld.txt”));
    //fr = new FileReader(“helloworld.txt”);
    //读取单个字符,返回的是字符的ascii码
    /int num = fr.read();
    System.out.println((char)num);
    num = fr.read();
    System.out.println(num);
    /
    //如果文本读取完毕,最后没有字符会返回-1
    int num = 0;
    //通过循环来读取字符,判断的跳出循环的标志是num = -1
    while((num = fr.read()) != -1){
    //打印字符
    System.out.print((char)num);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch(IOException e){
    e.printStackTrace();
    }finally{
    if(fr != null){
    try {
    //释放资源
    fr.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    int read(char[] cbuf)
    将字符读入数组。
    通过字符数组来读取数据
    f f s a d
    示例代码:
    package com.rl.io.cha.reader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    public class IOCharReaderDemo1 {
    public static void main(String[] args) {
    readFile();
    }
    public static void readFile(){
    FileReader fr = null;
    try {
    //创建fileReader对象
    fr = new FileReader(“helloworld.txt”);
    //创建一个字符的数组
    /char[] chs = new char[5];
    //读取5个字符放入字符数组中,返回的数值是读取到的字符数量
    int num = fr.read(chs);
    //String str = new String(chs);
    String str = new String(chs, 0, num);
    System.out.println(num);
    System.out.println(str);
    System.out.println("---------------");
    num = fr.read(chs);
    //str = new String(chs);
    str = new String(chs, 0, num);
    System.out.println(num);
    System.out.println(str);
    System.out.println("---------------");
    //读取到的是一个字符
    num = fr.read(chs);
    str = new String(chs, 0, num);
    System.out.println(num);
    System.out.println(str);
    System.out.println("---------------");
    //读取到的是一个字符
    num = fr.read(chs);
    System.out.println(num);
    str = new String(chs, 0, num);
    System.out.println(str);
    /
    //如果num的值是-1说明文件中的数据已经读完
    char [] chs1 = new char[1024];
    int len = -1;
    //循环条件的判断的边界是fr.read(char[])如果返回-1说明文件已经读取完毕
    while((len = fr.read(chs1)) != -1){
    System.out.println(new String(chs1, 0, len));
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch(IOException e){
    e.printStackTrace();
    }finally{
    if(fr != null){
    try {
    //释放资源
    fr.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    3.使用字符流来做文件的拷贝

    范例:把一个java文件拷贝到项目根目录。
    分析:1.创建字符输入流的对象
    2.创建字符输出流对象
    3.把输出流输入的数据写入输出流中
    4.关闭资源
    示例代码:
    package com.rl.io.cha.copyfile;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.Writer;
    public class CopyFile {
    public static void main(String[] args) {
    copy1();
    System.out.println(“done”);
    }
    /**
    * 拷贝一个java文件方式1
    * @author renliang
    */
    public static void copy(){
    Reader reader = null;
    Writer writer = null;
    try {
    //创建文件读取对象
    reader = new FileReader(“src/com/rl/io/cha/reader/IOCharReaderDemo.java”);
    //创建写文件的对象
    writer = new FileWriter(“IOCharReaderDemo.java”);
    int num = -1;
    while( (num = reader.read()) != -1){
    writer.write(num);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    //释放资源
    try {
    if(writer != null)
    writer.close();
    if(reader != null)
    reader.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    	}
    }
    public static void copy1(){
    	Reader reader = null;
    	Writer writer = null;
    	try {
    		//创建文件读取对象
    		reader = new FileReader("src/com/rl/io/cha/reader/IOCharReaderDemo.java");
    		//创建写文件的对象
    		writer = new FileWriter("IOCharReaderDemo.java");
    		//定义每次的读取的长度的对象
    		int len = -1;
    		//定义存储读取内容字符的数组
    		char[] chs = new char[1024];
    		//当len不等于-1就一直读取
    		while((len = reader.read(chs)) != -1){
    			//把读取的文件写入到目标文件中
    			writer.write(chs, 0, len);
    		}
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	}catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		//释放资源
    		try {
    			if(writer != null)
    				writer.close();
    			if(reader != null)
    				reader.close();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    }
    

    }
    3.高效缓存区输入输出流
    1.BufferedReader
    从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
    BufferedReader(Reader in)
    创建一个使用默认大小输入缓冲区的缓冲字符输入流。
    范例:使用高效缓冲区输入流来读取文件中的内容。

    package com.rl.io.cha.buffer;
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    public class BufferedReaderDemo {
    public static void main(String[] args) {
    read1();
    }
    /**
    * 使用高效缓存区输入流来读取文件
    * @author renliang
    /
    public static void read(){
    //创建创建文件输出流
    FileReader fr = null;
    BufferedReader br = null;
    try {
    fr = new FileReader(“d.txt”);
    //创建高效缓冲区的流对象
    br = new BufferedReader(fr);
    int num = -1;
    while((num = br.read()) != -1){
    System.out.print((char)num);
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally{
    if(br != null){
    try {
    //关闭缓存区的流就会自动的关闭FileWriter
    br.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /
    *
    * 建议使用如下的方式读取文件
    * @author renliang
    */
    public static void read1(){
    //创建创建文件输出流
    FileReader fr = null;
    BufferedReader br = null;
    try {
    fr = new FileReader(“d.txt”);
    //创建高效缓冲区的流对象
    br = new BufferedReader(fr);
    char[] chs = new char[1024];
    int len = -1;
    while((len = br.read(chs)) != -1){
    System.out.print(new String(chs, 0, len));
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally{
    if(br != null){
    try {
    //关闭缓存区的流就会自动的关闭FileWriter
    br.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }

    扩展方法readLine读取一行数据

    package com.rl.io.cha.buffer;
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    public class BufferedReaderDemo1 {
    public static void main(String[] args) {
    read1();
    }
    /**
    * 建议使用如下的方式读取文件
    * @author renliang
    */
    public static void read1(){
    //创建创建文件输出流
    FileReader fr = null;
    BufferedReader br = null;
    try {
    fr = new FileReader(“d.txt”);
    //创建高效缓冲区的流对象
    br = new BufferedReader(fr);
    String line = null;
    //使用高效输入流可以读取一行数据
    while((line = br.readLine()) != null){
    System.out.println(line);
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally{
    if(br != null){
    try {
    //关闭缓存区的流就会自动的关闭FileWriter
    br.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }

    2.BufferWriter
    将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
    构造器
    BufferedWriter(Writer out)
    创建一个使用默认大小输出缓冲区的缓冲字符输出流。
    范例1:使用高效缓冲区流来向文件中写入一句话
    package com.rl.io.cha.buffer;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    public class BufferedWriterDemo {
    public static void main(String[] args) {
    writer();
    }
    /**
    * 使用高效缓存区流来降d.txt的文件中写入,java太好学了,真简单。
    * @author renliang
    /
    public static void writer(){
    //创建创建文件输出流
    FileWriter fw = null;
    BufferedWriter bw = null;
    try {
    fw = new FileWriter(“d.txt”);
    //创建高效缓冲区的流对象
    bw = new BufferedWriter(fw);
    //输出数据
    bw.write(“java太好学了,真简单。”);
    //清空缓冲区
    bw.flush();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally{
    if(bw != null){
    try {
    //关闭缓存区的流就会自动的关闭FileWriter
    bw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    高效缓冲区的输出流的扩展方法:
    newline()可以换行
    package com.rl.io.cha.buffer;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    public class BufferedWriterDemo1 {
    public static void main(String[] args) {
    writer();
    }
    /
    *
    * 使用高效缓存区流来降d.txt的文件中写入,java太好学了,真简单。
    * @author renliang
    /
    public static void writer(){
    //创建创建文件输出流
    FileWriter fw = null;
    BufferedWriter bw = null;
    try {
    fw = new FileWriter(“d.txt”);
    //创建高效缓冲区的流对象
    bw = new BufferedWriter(fw);
    for(int i = 0; i < 10; i++){
    //输出数据
    bw.write(“java太好学了,真简单。”);
    //换行,相当于\r\n
    bw.newLine();
    }
    //清空缓冲区
    bw.flush();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }finally{
    if(bw != null){
    try {
    //关闭缓存区的流就会自动的关闭FileWriter
    bw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    范例:使用高效缓冲流来复制文本文件
    package com.rl.io.cha.copyfile;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.Writer;
    public class CopyFile1 {
    public static void main(String[] args) {
    copy();
    System.out.println(“done”);
    }
    /
    *
    * 拷贝一个java文件方式1
    * @author renliang
    */
    public static void copy(){
    Reader reader = null;
    BufferedReader br = null;
    Writer writer = null;
    BufferedWriter bw = null;
    try {
    //创建文件读取对象
    reader = new FileReader(“src/com/rl/io/cha/reader/IOCharReaderDemo.java”);
    //创建高效缓冲区的输入流
    br = new BufferedReader(reader);
    //创建写文件的对象
    writer = new FileWriter(“IOCharReaderDemo.java”);
    //创建高效缓冲区的输出流
    bw = new BufferedWriter(writer);
    String line = null;
    //读取数据并且写入另一个文件中
    while((line = br.readLine()) != null){
    bw.write(line);
    //换行
    bw.newLine();
    }
    bw.flush();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    //释放资源
    try {
    if(writer != null)
    writer.close();
    if(reader != null)
    reader.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    }
    Javase中IO字节流
    1.字节流概述
    字节输入流:InputStream:常用子类FileInputStream
    字节输出流:OutputStream:常用子类FileOutputStream

    2.OutputStream
    FileOutputStream(File file)
    创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(File file, boolean append)
    创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    FileOutputStream(String name)
    创建一个向具有指定名称的文件中写入数据的输出文件流。
    FileOutputStream(String name, boolean append)
    创建一个向具有指定 name 的文件中写入数据的输出文件流。

    范例:使用字节流向文件中写入”helloworld”
    分析:使用三种写入方法

    void write(byte[] b)
    将 b.length 个字节从指定 byte 数组写入此文件输出流中。
    void write(byte[] b, int off, int len)
    将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
    void write(int b)
    将指定字节写入此文件输出流。
    示例代码:
    package com.rl.byt.out;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    public class OutputStreamDemo {
    public static void main(String[] args) {
    writeFile();
    }
    public static void writeFile(){
    //创建字节输出流的对象
    OutputStream out = null;
    try {
    //out = new FileOutputStream(“a.txt”);
    //out = new FileOutputStream(new File(“a.txt”));
    //out = new FileOutputStream(new File(“a.txt”), true);
    out = new FileOutputStream(“a.txt”, true);
    String str = “helloworld”;
    //把字符串变成字节数组
    byte[] bs = str.getBytes();
    for(byte b : bs){
    //写单个字节
    out.write(b);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(out != null){
    try {
    out.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void writeFile1(){
    //创建字节输出流的对象
    OutputStream out = null;
    try {
    out = new FileOutputStream(“a.txt”);
    String str = “helloworld”;
    //把字符串变成字节数组
    byte[] bs = str.getBytes();
    //一次性把整个字节数组写入到文件中。
    out.write(bs);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(out != null){
    try {
    out.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void writeFile2(){
    //创建字节输出流的对象
    OutputStream out = null;
    try {
    out = new FileOutputStream(“a.txt”);
    String str = “helloworld”;
    //把字符串变成字节数组
    byte[] bs = str.getBytes();
    //把一部分的字节写到文件中。
    out.write(bs, 0, 5);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(out != null){
    try {
    out.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    3.InputStream
    因为InputStream是抽象类,我们要学习的是它的子类。
    构造器
    FileInputStream(File file)
    通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    FileInputStream(String name)
    通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
    读取方法:
    int read()
    从此输入流中读取一个数据字节。
    int read(byte[] b)
    从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
    int read(byte[] b, int off, int len)
    从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
    范例:使用字节输入流来读取文件并且输出到控制台。
    package com.rl.byt.out;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    public class InputStreamDemo {
    public static void main(String[] args) {
    readFile2();
    }
    /**
    * 单个字节读取的效率低
    * @author renliang
    /
    public static void readFile(){
    //创建字节输入流的对象
    InputStream in = null;
    try {
    in = new FileInputStream(“a.txt”);
    //从文件中读取一个字节
    int num = in.read();
    System.out.println(num);
    System.out.println((char)num);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(in != null){
    try {
    in.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /
    *
    * 向整个的数组中去存储数据
    * @author renliang
    /
    public static void readFile1(){
    //创建字节输入流的对象
    InputStream in = null;
    try {
    in = new FileInputStream(“a.txt”);
    //定义一个字节数组
    byte[] bs = new byte[1024];
    //向字节数组中存储数据,返回读取的长度
    int len = in.read(bs);
    System.out.println(len);
    System.out.println(new String(bs, 0, len));
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(in != null){
    try {
    in.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void readFile2(){
    //创建字节输入流的对象
    InputStream in = null;
    try {
    in = new FileInputStream(“a.txt”);
    //定义一个字节数组
    byte[] bs = new byte[1024];
    //从输入字节流的对象中读取指定的字节数, 从字节输入流的来取三个字节,放入字节数组的从索引1的位置开始放
    //0104101108
    //[0, 104, 101, 108, 0, …]
    int len = in.read(bs, 1, 3);
    /for(byte b : bs){
    System.out.print(b);
    }
    /
    System.out.println(new String(bs, 1, len));
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(in != null){
    try {
    in.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    范例2:使用字节流来拷贝文件。
    package com.rl.byt.out;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    public class CopyFileDemo {
    public static void main(String[] args) {
    copyFile1();
    }
    /
    *
    * 1.创建输入字节流的对象,输出流的对象
    * 2.读取数据并且写入数据
    * 3.关闭资源
    * @author renliang
    */
    public static void copyFile(){
    InputStream in = null;
    OutputStream out = null;
    //创建文件输入流的对象
    try {
    in = new FileInputStream(“src/com/rl/byt/out/OutputStreamDemo.java”);
    //创建文件输出流的对象
    out = new FileOutputStream(“OutputStreamDemo.java”);
    byte[] bs = new byte[1024];
    //定义返回的读取的长度
    int len = -1;
    while((len = in.read(bs)) != -1){
    //把字节数组中的数据写入到文件中
    out.write(bs, 0, len);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    try {
    if(out != null)
    out.close();

    			if(in != null)
    				in.close();
    			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    /**
     * 1.创建输入字节流的对象,输出流的对象
     * 2.读取数据并且写入数据
     * 3.关闭资源
     * @author renliang
     */
    public static void copyFile1(){
    	InputStream in = null;
    	OutputStream out = null;
    	//创建文件输入流的对象
    	try {
    		in = new FileInputStream("d:/1.jpg");
    		//创建文件输出流的对象
    		out = new FileOutputStream("d:/wsCode/1.jpg");
    		byte[] bs = new byte[1024];
    		//定义返回的读取的长度
    		int len = -1;
    		while((len = in.read(bs)) != -1){
    			//把字节数组中的数据写入到文件中
    			out.write(bs, 0, len);
    		}	
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(out != null)
    				out.close();
    				
    			if(in != null)
    				in.close();			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

    }

    4.字节流的高效缓冲区
    BufferedInputStream(InputStream in)
    创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
    BufferedOutputStream(OutputStream out)
    创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

    范例:使用高效缓冲区来复制文件来比较性能

    package com.rl.byt.out;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    public class BufferedCopyFileDemo {
    public static void main(String[] args) {
    long startTime = System.currentTimeMillis();
    copyFile3();
    long endTime = System.currentTimeMillis();
    System.out.println(“耗时:”+(endTime - startTime)+“毫秒”);
    }
    /**
    *耗时:8986毫秒
    * 单个字符的复制
    * @author renliang
    */
    public static void copyFile(){
    InputStream in = null;
    OutputStream out = null;
    //创建文件输入流的对象
    try {
    in = new FileInputStream(“d:/1.pdf”);
    //创建文件输出流的对象
    out = new FileOutputStream(“d:/wsCode/1.pdf”);
    //定义返回的读取的长度
    int len = -1;
    while((len = in.read()) != -1){
    //把字节数组中的数据写入到文件中
    out.write(len);
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    try {
    if(out != null)
    out.close();

    			if(in != null)
    				in.close();
    			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    /**
     * 耗时:42毫秒
     * 使用字节数组的方式的复制
     * @author renliang
     */
    public static void copyFile1(){
    	InputStream in = null;
    	OutputStream out = null;
    	//创建文件输入流的对象
    	try {
    		in = new FileInputStream("d:/1.pdf");
    		//创建文件输出流的对象
    		out = new FileOutputStream("d:/wsCode/1.pdf");
    		byte[] bs = new byte[1024];
    		//定义返回的读取的长度
    		int len = -1;
    		while((len = in.read(bs)) != -1){
    			//把字节数组中的数据写入到文件中
    			out.write(bs, 0, len);
    		}		
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(out != null)
    				out.close();		
    			if(in != null)
    				in.close();		
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    /**
     * 耗时:79毫秒
     * 使用高效缓冲区单个复制字符的方式
     * @author renliang
     */
    public static void copyFile2(){
    	InputStream in = null;
    	OutputStream out = null;	
    try {
    		//创建文件高效缓冲区输入流的对象
    		in = new BufferedInputStream(new FileInputStream("d:/1.pdf"));
    		//创建文件输出流的对象
    		out = new BufferedOutputStream(new FileOutputStream("d:/wsCode/1.pdf"));
    		//返回的单个字符
    		int len = -1;
    		while((len = in.read()) != -1){
    			//把字节数组中的数据写入到文件中
    			out.write(len);
    		}		
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(out != null)
    				out.close();				
    			if(in != null)
    				in.close();			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    /**
     * 耗时:6毫秒
     * 使用高效缓冲区复制字节数组的形式的方式
     * @author renliang
     */
    public static void copyFile3(){
    	InputStream in = null;
    	OutputStream out = null;
    	try {
    		//创建文件高效缓冲区输入流的对象
    		in = new BufferedInputStream(new FileInputStream("d:/1.pdf"));
    		//创建文件输出流的对象
    		out = new BufferedOutputStream(new FileOutputStream("d:/wsCode/1.pdf"));
    		byte[] bs = new byte[1024];
    		//定义返回的读取的长度
    		int len = -1;
    		while((len = in.read(bs)) != -1){
    			//把字节数组中的数据写入到文件中
    			out.write(bs, 0, len);
    		}		
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(out != null)
    				out.close();	
    			if(in != null)
    				in.close();		
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

    }
    范例:从键盘输入学生信息存储到文件中,学生按着年龄排序。
    Student:
    package com.rl.byt.model;
    public class Student implements Comparable {
    private String name;
    private Integer age;
    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 int compareTo(Student o) {
    int num = this.age - o.getAge();
    if(num == 0){
    num = this.name.compareTo(o.getName());
    }
    return num;
    }
    }
    ScannerTest
    package com.rl.byt.model;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Scanner;
    import java.util.TreeSet;
    public class ScannerTest {
    public static void main(String[] args) {
    //定义学生的集合
    TreeSet ts = new TreeSet();
    //创建键盘输入对象
    Scanner sc = new Scanner(System.in);
    System.out.println(“请输入你要录入几个学生”);
    //获得要输入的学生数量
    int count = sc.nextInt();
    for(int i = 0; i < count; i++){
    sc = new Scanner(System.in);
    System.out.println(“请输入学生的姓名:”);
    //获得学生的姓名
    String name = sc.nextLine();
    System.out.println(“请输入学生的年龄:”);
    //获得学生的年龄
    Integer age = sc.nextInt();
    //创建一个学生的对象
    Student s = new Student();
    s.setName(name);
    s.setAge(age);
    //把学生加入到集合中
    ts.add(s);
    }
    //定义高效缓冲区的字符输出流
    BufferedWriter bw = null;
    try {
    bw = new BufferedWriter(new FileWriter(“student.txt”));
    for(Student s : ts){
    bw.write(s.getName()+"-----"+s.getAge());
    bw.newLine();
    }
    bw.flush();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    try {
    if(bw != null)
    bw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    System.out.println(“已写入”);
    }
    }
    5.设计模式之装饰者模式
    装饰者模式的目的是给类的功能增强。
    继承也能给类的功能增强
    Writer类是写文件的类,有三个子类TxtWriter,MP3Writer,AVIWriter
    在writer中定义了写文件的标准,三个子类分别去实现Writer中的写方法
    使用继承方式来对类增强
    Writer
    |——TxtWriter
    |——MP3Writer
    |——AVIWriter
    通过继承方式加入高效缓冲区
    Writer
    |——TxtWriter
    |——BufferedTxtWriter
    |——MP3Writer
    |——BufferedMP3Writer
    |——AVIWriter
    |——BufferedAVIWriter
    |——RMWriter
    |——BufferedRMWriter
    如果想继续添加写文件的子类,如果想要对它做增强,还需要创建相应的缓冲区。
    装饰器的设计模式可以解决我们使用高效缓冲区,但是不需要每一个写文件的类都添加高效缓冲区。
    如果写文件的缓冲区是同样的原理,那么我们就可以把缓冲区抽取出来作为装饰器。
    角色:
    1.抽象构件角色(定义写文件标准):Writer
    2.具体的构件角色(实现写文件标准):三个子类TxtWriter,MP3Writer,AVIWriter
    3.装饰角色[抽象](高效缓冲区):注意:也可定义成抽象的,如果是抽象的就必须要有具体抽象角色
    4.具体的装饰角色:来实现抽象装饰器中的增强方法。

    抽象构件角色
    public abstract class Writer {

    /**
     * 写文件的方法
     * @author renliang
     */
    public abstract void writeFile();
    

    }
    具体构件角色:
    package com.rl.byt.decorator;
    public class TxtWriter extends Writer {
    public void writeFile() {
    System.out.println(“写入文本文件”);
    }
    }
    装饰器:
    package com.rl.byt.decorator;
    public class BufferedWriterFile extends Writer {
    private Writer writer;
    public BufferedWriterFile(Writer writer){
    this.writer = writer;
    }
    public void writeFile() {
    this.bufferedWrite();
    writer.writeFile();
    }
    public void bufferedWrite(){
    System.out.println(“加入高效缓冲区”);
    }
    }

    抽象装饰角色:
    package com.rl.byt.decorator;
    public abstract class BufferedWriterFile extends Writer {
    private Writer writer;
    public BufferedWriterFile(Writer writer){
    this.writer = writer;
    }
    public void writeFile() {
    this.bufferedWrite();
    writer.writeFile();
    this.clean();
    }
    /**
    * 高效缓存的方法
    * @author renliang
    */
    public abstract void bufferedWrite();
    public abstract void clean();
    }

    具体装饰角色:
    package com.rl.byt.decorator;
    public class BufferedWriterFileImpl extends BufferedWriterFile {
    public BufferedWriterFileImpl(Writer writer) {
    super(writer);
    }
    public void bufferedWrite() {
    System.out.println(“加入高效缓冲区”);
    }
    public void clean() {
    System.out.println(“做清理工作”);
    }
    }
    6.字符流和字节流的转换桥梁
    1.字节流转换字符流
    InputStreamReader
    范例:把从键盘输入的文本写入到文件中
    InputStreamReader(InputStream in)
    创建一个使用默认字符集的 InputStreamReader。
    InputStreamReader(InputStream in, Charset cs)
    创建使用给定字符集的 InputStreamReader。

    package com.rl.tyt.convert;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Scanner;
    public class ScannerDemo {
    public static void main(String[] args) {
    //创建Scanner对象
    Scanner sc = new Scanner(System.in);
    BufferedWriter bw = null;
    try {
    bw = new BufferedWriter(new FileWriter(“c.txt”));
    String line = null;
    while((line = sc.nextLine())!= null){
    if(“exit”.equals(line)){
    break;
    }
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(bw != null){
    try {
    bw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }

    InputStreamReader用于InputStreamReader 是字节流通向字符流的桥梁
    package com.rl.tyt.convert;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    public class ConverterInDemo {
    public static void main(String[] args) {
    InputStream is = System.in;
    //要想使用字符流的高效缓冲区来操作字节流需要转换
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    //定义要入的文件流
    BufferedWriter bw = null;
    String line = null;
    try {
    bw = new BufferedWriter(new FileWriter(“d.txt”));
    while((line = br.readLine()) != null){
    if(“exit”.equals(line)){
    break;
    }
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    }
    

    }
    2.字符流转换成字节流
    OutputStreamWriter 是字符流通向字节流的桥梁
    OutputStreamWriter(OutputStream out)
    创建使用默认字符编码的 OutputStreamWriter。
    OutputStreamWriter(OutputStream out, Charset cs)
    创建使用给定字符集的 OutputStreamWriter。

    范例:从一个文件中读取内容使用标准字节流来输出到控制台(使用字符串操作)
    package com.rl.tyt.convert;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    public class ConverterOutDemo {
    public static void main(String[] args) {
    BufferedReader br = null;
    BufferedWriter bw = null;
    try {
    br = new BufferedReader(new FileReader(“c.txt”));
    //创建字符流向字节流转换的对象
    bw = new BufferedWriter(new OutputStreamWriter(System.out));
    String line = null;
    while((line = br.readLine()) != null){
    bw.write(line);
    bw.newLine();
    bw.flush();
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }catch (IOException e) {
    e.printStackTrace();
    }finally{
    try {
    if(bw != null){
    bw.close();
    }
    if(br != null){
    bw.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    }
    

    }
    7.打印流
    打印流:只做输出没有输入
    打印流分为字节打印流和字符打印流
    PrintWriter:字符打印流
    特点
    1.可以打印各种数据类型。
    2.封装了字符输出流,还可以字符流和字节流的转换
    3.可以使用自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
    4.可以直接向文件中写数据
    范例:使用打印流向文件中打印数据
    package com.rl.byt.print;
    import java.io.BufferedWriter;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;

    public class PrintDemo {
    public static void main(String[] args) throws IOException {
    //System.out.println(“helloworld”);
    //BufferedWriter bw = new BufferedWriter(new FileWriter(“e.txt”));
    PrintWriter pw = null;
    try {
    pw = new PrintWriter(“e.txt”);
    pw.print(true);
    pw.print(‘a’);
    pw.print(12);
    pw.print(“renliang”);
    pw.flush();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }finally{
    if(pw != null){
    pw.close();
    }
    }
    }
    }
    范例:从文件总读取数据并且打印在控制台
    package com.rl.byt.print;
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class PrintDemo1 {
    public static void main(String[] args) {
    BufferedReader br = null;
    PrintWriter pw = null;
    try {
    //定义缓冲区输入流对象
    br = new BufferedReader(new FileReader(“student.txt”));

    		//pw = new PrintWriter(System.out);
    		//设置自动刷新的打印流
    		pw = new PrintWriter(System.out, true);
    		String line = null;
    		while((line = br.readLine()) != null){
    			pw.println(line);
    			//pw.flush();
    		}
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(pw != null){
    				pw.close();
    			}
    			if(br != null){
    				br.close();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}	
    }
    

    }
    范例:使用打印流来复制文本文件
    package com.rl.byt.print;
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class PrintDemo2 {
    public static void main(String[] args) {
    BufferedReader br = null;
    PrintWriter pw = null;
    try {
    //定义缓冲区输入流对象
    br = new BufferedReader(new FileReader(“student.txt”));

    		//pw = new PrintWriter(System.out);
    		//设置自动刷新的打印流
    		pw = new PrintWriter(new FileWriter("student1.txt"), true);
    		String line = null;
    		while((line = br.readLine()) != null){
    			pw.println(line);
    		}
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		try {
    			if(pw != null){
    				pw.close();
    			}
    			if(br != null){
    				br.close();
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}	
    }
    

    }
    8.Properties类
    Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
    特点:
    1.继承于HashTable,是线程安全的键值对存储结构
    2. Properties 可保存在流中或从流中加载
    3. 只能保存字符串的键值对。
    构造器:

    Properties()
    创建一个无默认值的空属性列表。

    常用方法:
    String
    getProperty(String key)
    用指定的键在此属性列表中搜索属性。
    Object
    setProperty(String key, String value)
    调用 Hashtable 的方法 put。
    void list(PrintWriter out)
    将属性列表输出到指定的输出流。
    void load(InputStream inStream)
    从输入流中读取属性列表(键和元素对)。
    void load(Reader reader)
    按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
    void store(OutputStream out, String comments)
    以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
    void store(Writer writer, String comments)
    以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
    范例:使用Properties类存取
    package com.rl.byt.prop;
    import java.util.Properties;
    public class PropTest {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    prop.setProperty(“name”, “zhangsan”);
    prop.setProperty(“age”, “10”);
    prop.setProperty(“gender”, “male”);
    System.out.println(prop);
    String name = prop.getProperty(“name”);
    String age = prop.getProperty(“age”);
    String gender = prop.getProperty(“gender”);
    System.out.println(name);
    System.out.println(age);
    System.out.println(gender);
    }
    }
    范例:把属性类的对象数据写入文件
    package com.rl.byt.prop;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Properties;
    import java.util.Set;
    public class PropTest1 {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    prop.setProperty(“name”, “zhangsan”);
    prop.setProperty(“age”, “10”);
    prop.setProperty(“gender”, “male”);
    PrintWriter pw = null;
    try {
    pw = new PrintWriter(new FileWriter(“prop.txt”), true);
    Set keys = prop.keySet();
    for(Object obj : keys){
    String key = (String) obj;
    String value = prop.getProperty(key);
    pw.println(key+"="+value);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(pw != null){
    pw.close();
    }
    }
    }
    }
    范例:把属性类的对象数据写入文件方式2
    package com.rl.byt.prop;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Properties;
    import java.util.Set;
    public class PropTest2 {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    prop.setProperty(“name”, “zhangsan”);
    prop.setProperty(“age”, “10”);
    prop.setProperty(“gender”, “male”);
    PrintWriter pw = null;
    try {
    pw = new PrintWriter(“prop1.txt”);
    prop.list(pw);
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(pw != null){
    pw.close();
    }
    }
    }
    }
    范例:把属性类的对象数据写入文件方式3
    package com.rl.byt.prop;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    public class PropTest5 {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    prop.setProperty(“name”, “zhangsan”);
    prop.setProperty(“age”, “10”);
    prop.setProperty(“gender”, “male”);
    FileWriter fw = null;
    try {
    fw = new FileWriter(“prop2.txt”);
    prop.store(fw, null);
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fw != null){
    try {
    fw.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    范例:从txt文件中加载属性信息
    package com.rl.byt.prop;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.Properties;
    public class PropTest3 {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    FileReader fr = null;
    try {
    fr = new FileReader(“prop.txt”);
    //把字符流数据读到prop对象中
    prop.load(fr);
    //获得数据
    String name = prop.getProperty(“name”);
    String age = prop.getProperty(“age”);
    String gender = prop.getProperty(“gender”);
    System.out.println(name);
    System.out.println(age);
    System.out.println(gender);
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fr != null){
    try {
    fr.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    范例:从txt文件中加载属性信息
    package com.rl.byt.prop;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.Properties;
    public class PropTest4 {
    public static void main(String[] args) {
    //属性集类不支持泛型
    Properties prop = new Properties();
    FileReader fr = null;
    try {
    //实际项目中使用Properties的文件来存储数据,不使用txt
    fr = new FileReader(“src/prop.properties”);
    //把字符流数据读到prop对象中
    prop.load(fr);
    //获得数据
    String name = prop.getProperty(“name”);
    String age = prop.getProperty(“age”);
    String gender = prop.getProperty(“gender”);
    System.out.println(name);
    System.out.println(age);
    System.out.println(gender);
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(fr != null){
    try {
    fr.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    9.序列化流(对象流)
    把对象以流的形式存储在硬盘上或者数据库中的过程就是写序列化流
    序列化流:
    对象输出流:
    ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
    对象输入流:
    ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

    ObjectOutputStream的构造器
    构造方法摘要
    ObjectOutputStream(OutputStream out)
    创建写入指定 OutputStream 的 ObjectOutputStream。
    ObjectInputStream的构造器
    构造方法摘要
    ObjectInputStream(InputStream in)
    创建从指定 InputStream 读取的 ObjectInputStream。

    如果想序列化某个对象,那么这个对象所对应的类必须实现
    类通过实现 java.io.Serializable 接口以启用其序列化功能,在序列化的过程中要手动指定要序列化的类的的serialVersionUID,这样可以在类改变后依然可以反序列化,否则会报错。
    示例代码:
    package com.rl.byt.seril;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.ArrayList;
    public class SerilDemo1 {
    public static void main(String[] args) {
    //writeObject1();
    readObject1();
    }
    public static void writeObject(){
    ObjectOutputStream oos = null;
    try {
    //创建序列化的流对象
    oos = new ObjectOutputStream(new FileOutputStream(“person.txt”));
    Person p = new Person();
    p.setName(“任亮”);
    p.setAge(30);
    Person p1 = new Person();
    p1.setName(“张三”);
    p1.setAge(31);
    Person p2 = new Person();
    p2.setName(“李四”);
    p2.setAge(29);
    //调用序列化对象流的写入方法
    oos.writeObject§;
    oos.writeObject(p1);
    oos.writeObject(p2);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(oos != null){
    try {
    oos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /**
    * 反序列化
    * @author renliang
    /
    public static void readObject(){
    ObjectInputStream oos = null;
    try {
    //创建序列化的流对象
    oos = new ObjectInputStream(new FileInputStream(“person.txt”));
    //从反序列化的流中来读取数据
    Object obj = oos.readObject();
    Object obj1 = oos.readObject();
    Object obj2 = oos.readObject();
    Person p = (Person) obj;
    System.out.println§;
    System.out.println(obj1);
    System.out.println(obj2);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch(ClassNotFoundException e){
    e.printStackTrace();
    }finally{
    if(oos != null){
    try {
    oos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void writeObject1(){
    ObjectOutputStream oos = null;
    try {
    //创建序列化的流对象
    oos = new ObjectOutputStream(new FileOutputStream(“person.txt”));
    ArrayList al = new ArrayList();
    Person p = new Person();
    p.setName(“任亮”);
    p.setAge(30);
    Person p1 = new Person();
    p1.setName(“张三”);
    p1.setAge(31);
    Person p2 = new Person();
    p2.setName(“李四”);
    p2.setAge(29);
    al.add§;
    al.add(p1);
    al.add(p2);
    //调用序列化对象流的写入方法
    oos.writeObject(al);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(oos != null){
    try {
    oos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /
    *
    * 反序列化
    * @author renliang
    */
    public static void readObject1(){
    ObjectInputStream oos = null;
    try {
    //创建序列化的流对象
    oos = new ObjectInputStream(new FileInputStream(“person.txt”));
    Object obj = oos.readObject();
    ArrayList al = (ArrayList) obj;
    for(Person p : al){
    System.out.println§;
    }
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch(ClassNotFoundException e){
    e.printStackTrace();
    }finally{
    if(oos != null){
    try {
    oos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    }
    10.字符编码
    存储:
    在计算机中存储字符都是存储的字符所对应的数值以二进制的形式表示。
    展示:
    去相关的编码表中去查找该值(存储的值)所对应的字符。

    常见的:
    ASCII表:
    用7bit来表示存储数据
    ISO-8859-1:拉丁码表
    用8bit来表示
    GB2312:
    简体中文编码(国标码)
    GBK:
    gb2312做了增强
    GB18030:
    对GBK做了增强
    BIG5:
    支持繁体
    Unicode:
    支持多种国家的语言,这是国际标准。用2个字节来存储。
    不管是什么字符都用2个字节,会有浪费。
    UTF-8:
    支持多种国家的语言,针对不同的字符的范围给出不同的字节表示。
    0,a,A用一个字符存储
    中间的范围用二个字节
    中文就使用3个字节。

    	写入的编码和读取的编码必须要一致,否则会有乱码。
    

    范例:使用GBK的编码方式来写入文件。
    package com.rl.byt.charset;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.UnsupportedEncodingException;
    public class CharsetDemo {
    public static void main(String[] args) {
    //printCharset();
    readCharset();
    }
    public static void printCharset(){
    OutputStreamWriter ow = null;
    try {
    ow = new OutputStreamWriter(new FileOutputStream(“2.txt”), “UTF-8”);
    ow.write(“中国”);
    } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }finally{
    if(ow != null){
    try {
    ow.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    public static void readCharset(){
    InputStreamReader ow = null;
    try {
    ow = new InputStreamReader(new FileInputStream(“2.txt”), “UTF-8”);
    char[] chs = new char[1024];
    int len = ow.read(chs);
    System.out.println(new String(chs, 0, len));

    	} catch (UnsupportedEncodingException e) {
    		e.printStackTrace();
    	} catch (FileNotFoundException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}finally{
    		if(ow != null){
    			try {
    				ow.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

    }
    字符串的编码问题:
    package com.rl.byt.charset;
    import java.io.UnsupportedEncodingException;
    public class CharsetDemo1 {
    public static void main(String[] args) throws UnsupportedEncodingException {
    String str = “中国”;
    //使用默认的编码来编码(gbk)
    byte[] bsGbk = str.getBytes();
    //使用UTF-8来编码
    byte[] bsTtf8 = str.getBytes(“UTF-8”);
    //打印编码值
    printByte(bsGbk);
    //打印编码值对应的字符(默认编码)
    System.out.println(new String(bsGbk));
    //打印用UTF-8编码后的编码值
    printByte(bsTtf8);
    //打印UTF-8编码对应的字符串
    System.out.println(new String(bsTtf8, “UTF-8”));
    }

    public static void printByte(byte[] bs){
    	for(byte b : bs){
    		System.out.print(b+"  ");
    	}
    }
    

    }
    javase线程详解
    1.线程概述
    进程:计算机中特定功能的程序在数据集上的一次运行。
    线程:线程是进程的一个单元。
    多线程:一个进程中有多个线程在同时运行,如迅雷下载,迅雷软件的一次运行就是一个进程,那么在迅雷中可以同时下载多个电影,这就是多线程(每一个下载都是一个线程)
    Jvm是多线程的,在我们运行jvm的时候后台会运行垃圾回收的线程,来清理没有被引用的对象。

    2.线程的实现
    1.线程实现的第一种方式
    创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。
    线程启动的 时候使用线程的start方法而不是run
    package com.rl.thread;
    public class CountThread extends Thread {
    /**
    * 线程的执行体
    */
    public void run() {
    for(int i = 0; i < 50; i++){
    System.out.println(this.getName()+"-----hello"+i);
    }
    }
    }
    测试线程
    package com.rl.thread;
    public class ThreadDemo {
    public static void main(String[] args) {
    //创建线程的实例对象
    CountThread ct = new CountThread();
    CountThread ct1 = new CountThread();

    	//启动线程
    	ct.start();
    	ct1.start();	
    }
    

    }
    2.线程实现的第二种方式
    创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。
    示例代码:
    package com.rl.thread;
    public class CountThread1 implements Runnable {
    public void run() {
    for(int i = 0; i < 50; i++){
    //输出线程名字 System.out.println(Thread.currentThread().getName()+"-----hello"+i);
    }
    }
    }
    测试代码:
    package com.rl.thread;
    public class ThreadDemo1 {
    public static void main(String[] args) {
    /**
    * 创建两个线程
    */
    CountThread1 ct = new CountThread1();
    //Thread t1 = new Thread(ct, “线程1”);
    Thread t1 = new Thread(ct);

    	CountThread1 ct1 = new CountThread1();
    	//Thread t2 = new Thread(ct1, "线程2");
    	Thread t2 = new Thread(ct1);
    	
    	t1.start();
    	t2.start();
    }
    

    }
    3.线程的执行原理

    线程的并发执行通过多个线程不断的切换CPU的资源,这个速度非常快,我们感知不到,我们能感知到的就是三个线程在并发的执行。
    4.线程的生命周期
    1.新建: 线程被new出来
    2.准备就绪:线程具有执行的资格,即线程调用了start(),没有执行的权利
    3.运行:具备执行的资格和具备执行的权利
    4.阻塞:没有执行的资格和执行权利
    5.销毁: 线程的对象变成垃圾,释放资源。

    					Start()
    
    		sleep时间到	        等CPU	抢到CPU
    		notify()									run()结束
    					sleep()
    					wait()						stop()
    

    5.并发
    互联网的项目中存在着大量的并发的案例,如卖火车票,电商网站。
    范例:火车站有100张票,4个窗口同时买票。
    分析:4个窗口是4个线程同时在运行,100票是4个线程的共享资源。
    采用继承Thread来实现

    并发安全性问题:
    线程1 线程2

    解决方案:

    针对线程的安全性问题,我们需要使用同步(就是要加锁,共享资源只能一个人同时访问)锁。
    语法:
    synchronized(锁对象){
    //操作共享资源的代码
    }
    同步代码加在什么地方?
    1.代码被多个线程访问
    2.代码中有共享的数据
    3.共享数据被多条语句操作。
    代码:
    package com.rl.tickets;
    /**

    • 买票的窗口
    • @author renliang

    /
    public class SaleTicket extends Thread{
    private String name;
    public SaleTicket(String name) {
    super(name);
    }
    /
    *
    * 100张票是共享的数据
    /
    private static int tickets = 100;
    /
    *
    * 同步锁(同步钥匙)对象
    /
    private static Object obj = new Object();
    public void run() {
    while(true){
    //同步代码块
    synchronized (obj) {
    if(tickets > 0){
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(this.getName()+“正在卖第”+tickets–+“张票”);
    }else{
    System.out.println(“票已经售完”);
    break;
    }
    }
    }
    }
    }
    Synchronized同步代码块的锁对象可以是任意类对象(线程的实现方式是使用继承于Thread),这个对象必须是线程类共享(静态的)
    Synchronized是可以加在方法上,如果是静态方法Synchronized的所对象就是类的类对象,如果不是静态的方法,Synchronized如果加在对象方法上,那么他的锁是this
    示例代码:
    package com.rl.tickets1;
    /
    *

    • 买票的窗口
    • @author renliang

    /
    public class SaleTicket extends Thread{
    private String name;
    public SaleTicket(String name) {
    super(name);
    }
    /
    *
    * 100张票是共享的数据
    /
    private static int tickets = 100;
    /
    *
    * 同步锁(同步钥匙)对象
    /
    //private static Object obj = new Object();
    private static A a = new A();
    public void run() {
    while(true){
    int i = 0;
    if(i%2 == 0){
    //同步代码块
    synchronized (SaleTicket.class) {
    if(tickets > 0){
    try {
    Thread.sleep(50);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(this.getName()+“正在卖第”+tickets–+“张票”);
    }else{
    System.out.println(“票已经售完”);
    break;
    }
    }
    }else{
    //同步代码块
    saleTickets();
    }
    i++;
    }
    }
    /
    *
    * 静态方法的synchronized锁是当前类的类对象
    * @author renliang
    /
    public synchronized static void saleTickets(){
    if(tickets > 0){
    try {
    Thread.sleep(50);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+“正在卖第”+tickets–+“张票”);
    }else{
    System.out.println(“票已经售完”);
    }
    }
    }
    class A{
    }
    代码2:
    package com.rl.tickets2;
    /
    *

    • 买票的窗口
    • @author renliang

    /
    public class SaleTicket implements Runnable{
    /
    *
    * 100张票是共享的数据
    */
    private int tickets = 100;
    //private Object obj = new Object();
    public void run() {
    while(true){

    		int i = 0;
    		if(i%2 == 0){
    			//同步代码块
    			synchronized (this) {
    				if(tickets > 0){
    					try {
    						Thread.sleep(50);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");
    				}else{
    					System.out.println("票已经售完");
    					break;
    				}
    			}
    		}else{
    			//同步代码块
    			saleTickets();
    		}
    		i++;		
    	}
    }	
    /**
     * 非静态方法的synchronized锁是当前对象
     * @author renliang
     */
    public synchronized void saleTickets(){
    	if(tickets > 0){
    		try {
    			Thread.sleep(50);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");
    	}else{
    		System.out.println("票已经售完");
    	}
    }
    

    }
    6.线程的休眠
    线程的休眠是很必要的,在做服务端的时候为了减少服务器的压力我们需要休眠
    如果休眠是在同步代码块中执行,休眠不会让出锁对象。
    package com.rl.sleep;
    /**

    • 买票的窗口
    • @author renliang

    /
    public class SaleTicket implements Runnable{
    /
    *
    * 100张票是共享的数据
    */
    private int tickets = 100;
    //private Object obj = new Object();
    public void run() {
    while(true){
    //同步代码块
    synchronized (this) {
    if(tickets > 0){
    try {
    Thread.sleep(3000);
    System.out.println("------------");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+“正在卖第”+tickets–+“张票”);
    }else{
    System.out.println(“票已经售完”);
    break;
    }
    }
    }
    }
    }
    7.线程间的通信
    生产者和消费者

    生产者线程 消费者线程

    生产者生成水果,如果水果没有被买走那么就不生产处于等待状态,如果水果被消费者买走就的时候消费者会通知生产者告诉他我们已经把水果买走了请生产,消费者同理,如果水果已经生产出来那么就买走,买走之后再通知生产者水果已经没了请生产。
    注意:
    1.线程间的通信共享数据一定要有同步代码块synchronized
    2.一定要有wait和notify,而且二者一定是成对出现。
    3.生产者和消费者的线程实现一定是在while(true)里面
    示例代码:
    生产者:
    package com.rl.tx;
    public class ProductFruit implements Runnable{
    private Fruit fruit;
    public ProductFruit(Fruit fruit) {
    super();
    this.fruit = fruit;
    }
    public void run() {
    while(true){
    //有共享的数据,多个线程操作共享的数据,必须使用锁
    synchronized (fruit) {
    //如果水果已经存在那么生产者就不生成,等待着消费者买走水果在生成
    if(fruit.isExsit()){
    try {
    //当前生产水果的线程被挂起变成阻塞状态
    fruit.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(fruit.getName()+“水果被生产出来”);
    //把水果的状态变成存在
    fruit.setExsit(true);
    //唤醒等待买水果的线程
    fruit.notify();
    }
    }
    }
    }
    消费者
    package com.rl.tx;
    public class BuyFruit implements Runnable{
    private Fruit fruit;
    public BuyFruit(Fruit fruit) {
    super();
    this.fruit = fruit;
    }
    public void run() {
    while(true){
    //有共享的数据,多个线程操作共享的数据,必须使用锁
    synchronized (fruit) {
    if(!fruit.isExsit()){
    try {
    fruit.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(fruit.getName()+“水果被买走”);
    fruit.setExsit(false);
    //唤醒生产者线程
    fruit.notify();
    }
    }
    }
    }
    8.线程的优先级
    我们可以通过public final void setPriority(int newPriority)
    来设置线程的优先级,但是优先级并不是绝对的,只是先对来说比其他的线程得到CPU的资源机会多一些。
    示例代码:
    package com.rl.prio;
    public class PrioTest {
    public static void main(String[] args) {
    PrioThread pt = new PrioThread();
    PrioThread pt1 = new PrioThread();
    PrioThread pt2 = new PrioThread();

    	/*System.out.println(pt.getPriority());
    	System.out.println(pt1.getPriority());
    	System.out.println(pt2.getPriority());*/	
    	pt2.setPriority(10);	
    	pt.start();
    	pt1.start();
    	pt2.start();
    }
    

    }
    9.加入线程
    join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
    void join()
    等待该线程终止。
    package com.rl.join;
    public class JoinTest {
    public static void main(String[] args) {
    JoinThread pt = new JoinThread();
    JoinThread pt1 = new JoinThread();
    JoinThread pt2 = new JoinThread();
    pt2.start();
    try {
    //join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
    pt2.join();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    pt.start();
    pt1.start();
    }
    }
    10.等待线程
    static void yield()
    暂停当前正在执行的线程对象,并执行其他线程。
    当前的线程从运行阶段回到就绪阶段,目的是把CPU的资源让给其他的线程。
    package com.rl.yield;
    public class YieldThread extends Thread{
    public void run() {
    for(int i = 0; i < 50; i++){
    System.out.println(this.getName()+“正在运行”+i);
    //当前的线程回到就绪的状态,让出CPU
    Thread.yield();
    }
    }
    }
    11.守护线程
    void setDaemon(boolean on)
    将该线程标记为守护线程或用户线程。
    守护线程会随着主线程的结束而结束。
    package com.rl.daemon;
    public class DaemonTest {
    public static void main(String[] args) {
    DaemonThread pt = new DaemonThread();
    DaemonThread pt1 = new DaemonThread();
    pt.setDaemon(true);
    pt1.setDaemon(true);
    pt.start();
    pt1.start();
    for(int i = 0 ; i < 10; i++){
    System.out.println(Thread.currentThread().getName()+“主线程正在运行”+i);
    }
    }
    }
    12.线程死锁

    示例代码:
    package com.rl.dielock;
    public class DieLockDemo implements Runnable{
    private boolean flag;
    public DieLockDemo(boolean flag) {
    super();
    this.flag = flag;
    }
    public void run() {
    if(flag){
    synchronized (Lock.lock1) {
    System.out.println(“线程1执行拿到第一把所”);
    synchronized (Lock.lock2) {
    System.out.println(“线程1执行拿到第二把所”);
    }
    }
    }else{
    synchronized (Lock.lock2) {
    System.out.println(“线程2执行拿到第二把锁”);
    synchronized (Lock.lock1) {
    System.out.println(“线程2执行拿到第一把锁”);
    }
    }
    }
    }
    }
    在做线程开发的时候要避免出现死锁。
    网络编程
    1.计算机网络
    是指将地理位置不同的具有独立功能的多台计算机以及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件以及通信的协议的管理下,实现资源共享和信息传递的计算机系统。
    2.网络编程
    就是用来实现网络互通的不同计算机运行程序之间进行数据的交换的编程。
    3.网络模型
    OSI(模型):七层协议
    应用层 你好
    表示层
    会话层
    传输层
    网络层
    数据链路层
    物理层 01010010

    TCP/IP(模型)
    应用层
    传输层
    网际层
    主机至网络层

    2.网络通信的三要素
    1.IP地址

    Ip的最大值233.255.255.255
    可以设置的区间是1.0.0.0-233.255.255.255
    使用docs命令来查看ip地址:
    Ipconfig

    如果查看要通信的主机ip是否畅通:
    Ping [ip]

    2.端口号
    用于标识进程的逻辑地址,不同的进程端口不同。
    如何查看端口号:
    使用docs命令netstat –ano

    如果我们要和某一个计算的应用程序通信那就必须指定这台计算机的IP地址和这个应用程序的端口号
    Ip:port,如192.168.1.103:8080
    端口的值的范围:0—65535,其中0—1024是系统使用的端口,我们不要使用1024之前的端口。
    3.传输的协议

    协议:就是计算机通信的规则。

    常见的有两种协议:
    TCP和UDP协议
    UDP:
    将数据源和目的地封装到数据包中,不需要建立连接。
    每个数据包的大小限制在64k。
    因为不建立连接,所以安全性差,速度快。
    TCP:
    建立连接形成传输数据的通道,然后再传输数据,通过三次的握手。
    安全性高,效率低。
    3.InetAddress类
    InetAddress是用于管理IP的类
    没有构造器
    1.单例模式
    2.根据静态的方法来返回该对象

    static InetAddress
    getLocalHost()
    返回本地主机。
    String
    getHostAddress()
    返回 IP 地址字符串(以文本表现形式)。
    String
    getHostName()
    获取此 IP 地址的主机名。
    static InetAddress
    getByName(String host)
    在给定主机名的情况下确定主机的 IP 地址。
    示例代码:
    package com.rl.net;
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
    getOtherHost();
    }
    public static void getHost() throws UnknownHostException{
    InetAddress ia = InetAddress.getLocalHost();
    //返回主机的ip
    String ip = ia.getHostAddress();
    //返回主机名
    String name = ia.getHostName();
    System.out.println(“ip:”+ip);
    System.out.println(“主机名:”+name);
    /ip:192.168.1.103
    主机名:renliang-PC
    /
    }
    public static void getOtherHost() throws UnknownHostException{
    //InetAddress ia = InetAddress.getByName(“192.168.1.104”);
    InetAddress ia = InetAddress.getByName(“IGGWXT5GR5DT7WX”);
    //返回主机的ip
    String ip = ia.getHostAddress();
    //返回主机名
    String name = ia.getHostName();
    System.out.println(“ip:”+ip);
    System.out.println(“主机名:”+name);
    /ip:192.168.1.104
    主机名:IGGWXT5GR5DT7WX
    /
    }
    }
    4.Socket
    Socket是网络编程提供的一种机制,通信的两端都要有socket,网络通信其实就是socket间的通信,数据在两个socket间的io流上通信

    客户端 服务器端

    1.UDP的socket通信
     Udp服务器端的步骤:
    1.创建socket服务对象:
    Udp的服务端的构造器
    DatagramSocket(int port)
    创建数据报套接字并将其绑定到本地主机上的指定端口。
    2.接收数据:使用数据包的方式来接收,用到了DataGramPacket此类表示数据报包。
    DatagramPacket(byte[] buf, int length)
    构造 DatagramPacket,用来接收长度为 length 的数据包。

    3.解析数据
    解析数据包:

    InetAddress
    getAddress()
    返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
    byte[] getData()
    返回数据缓冲区。
    int getLength()
    返回将要发送或接收到的数据的长度。
    示例代码:
    package com.rl.udp;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class ServerDemo {
    public static void main(String[] args) throws IOException {
    //创建服务端的套接字对象
    DatagramSocket ds = new DatagramSocket(10000);
    System.out.println(“服务端正在运行…”);
    //接收数据包的字节数组
    byte[] bs = new byte[1024];
    //创建数据包
    DatagramPacket dp = new DatagramPacket(bs, bs.length);
    //接收
    ds.receive(dp);
    //解析数据
    InetAddress ia = dp.getAddress();
    String ip = ia.getHostAddress();
    //获得数据的长度
    int len = dp.getLength();
    //获得数据包中的数据
    byte[] bs1 = dp.getData();
    String result = new String(bs1, 0, len);
    System.out.println(“ip地址是:”+ip+" 数据是:"+result);
    //释放资源
    ds.close();
    }
    }

    4.释放资源
    关闭套接字。

     upd客户端的步骤
    1.创建服务端套接字
    DatagramSocket()
    构造数据报套接字并将其绑定到本地主机上任何可用的端口。
    2.创建数据包
    DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
    3.发送数据包
    void send(DatagramPacket p)
    从此套接字发送数据报包。
    客户端代码:
    package com.rl.udp;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class ClientDemo {
    public static void main(String[] args) throws IOException {
    //创建客户端的套接字对象
    DatagramSocket ds = new DatagramSocket();
    //准备数据(字节数组的方式)
    byte[] bs = “你好漂亮啊”.getBytes();
    InetAddress address = InetAddress.getByName(“192.168.1.103”);
    //创建数据包
    DatagramPacket dp = new DatagramPacket(bs, bs.length, address, 10000);
    //发送数据包
    ds.send(dp);
    System.out.println(“发送了:你好漂亮啊”);
    //释放资源
    ds.close();
    }
    }
    把UDP代码改造成可以从键盘录入数据:
    服务端:
    package com.rl.udp1;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class ServerDemo {
    public static void main(String[] args) throws IOException {
    //创建服务端的套接字对象
    DatagramSocket ds = new DatagramSocket(10000);
    System.out.println(“服务端正在运行…”);
    while(true){
    //接收数据包的字节数组
    byte[] bs = new byte[1024];
    //创建数据包
    DatagramPacket dp = new DatagramPacket(bs, bs.length);
    //接收
    ds.receive(dp);
    //解析数据
    InetAddress ia = dp.getAddress();
    String ip = ia.getHostAddress();
    //获得数据的长度
    int len = dp.getLength();
    //获得数据包中的数据
    byte[] bs1 = dp.getData();
    String result = new String(bs1, 0, len);
    System.out.println(“ip地址是:”+ip+" 数据是:"+result);
    if(“exit”.equals(result)){
    break;
    }
    }
    //释放资源
    ds.close();
    }
    }
    客户端:
    package com.rl.udp1;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    public class ClientDemo {
    public static void main(String[] args) throws IOException {
    //创建客户端的套接字对象
    DatagramSocket ds = new DatagramSocket();
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String line = null;
    while((line = br.readLine()) != null){
    //准备数据(字节数组的方式)
    byte[] bs = line.getBytes();
    InetAddress address = InetAddress.getByName(“192.168.1.103”);
    //创建数据包
    DatagramPacket dp = new DatagramPacket(bs, bs.length, address, 10000);
    //发送数据包
    ds.send(dp);
    System.out.println(“发送了:”+line);
    if(“exit”.equals(line)){
    break;
    }
    }
    //释放资源
    ds.close();
    }
    }
    聊天室程序:
    服务端:
    package com.rl.udp3;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    public class ServerThread implements Runnable{
    private int port;
    public ServerThread(int port) {
    super();
    this.port = port;
    }
    public void run() {
    //创建服务端的套接字对象
    DatagramSocket ds = null;
    try {
    ds = new DatagramSocket(port);
    } catch (SocketException e) {
    e.printStackTrace();
    }
    System.out.println(“服务端正在运行…”);
    while(true){
    //接收数据包的字节数组
    byte[] bs = new byte[1024];
    //创建数据包
    DatagramPacket dp = new DatagramPacket(bs, bs.length);
    //接收
    try {
    ds.receive(dp);
    } catch (IOException e) {
    e.printStackTrace();
    }
    //解析数据
    InetAddress ia = dp.getAddress();
    String ip = ia.getHostAddress();
    //获得数据的长度
    int len = dp.getLength();
    //获得数据包中的数据
    byte[] bs1 = dp.getData();
    String result = new String(bs1, 0, len);
    System.out.println(“ip地址是:”+ip+" 说:\r\n"+result);
    if(“exit”.equals(result)){
    break;
    }
    }
    //释放资源
    if(ds != null)
    ds.close();
    }
    }
    客户端:
    package com.rl.udp3;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    public class ClientThread implements Runnable{
    private int port;
    public ClientThread(int port) {
    super();
    this.port = port;
    }
    public void run() {
    //创建客户端的套接字对象
    DatagramSocket ds = null;
    try {
    ds = new DatagramSocket();
    } catch (SocketException e) {
    e.printStackTrace();
    }
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String line = null;
    try {
    while((line = br.readLine()) != null){

    			//准备数据(字节数组的方式)
    			byte[] bs = line.getBytes();
    			
    			InetAddress address =  InetAddress.getByName("192.168.1.103");
    			//创建数据包
    			DatagramPacket dp = new DatagramPacket(bs, bs.length, address, port);
    			//发送数据包
    			ds.send(dp);
    			System.out.println("我:\r\n"+line);
    			if("exit".equals(line)){
    				break;
    			}
    		}
    	} catch (UnknownHostException e) {
    		e.printStackTrace();
    	} catch (IOException e) {
    		e.printStackTrace();
    	}
    	if(ds != null)
    	ds.close();
    }
    

    }
    2.TCP的socket通信
    开发步骤:
    TCP服务端:
    1.创建服务器Socket对象,指定端口
    ServerSocket(int port)
    创建绑定到特定端口的服务器套接字。

    2.监听并获得客户端的对象socket
    Socket
    accept()
    侦听并接受到此套接字的连接。

    3.获得输入流
    InputStream
    getInputStream()
    返回此套接字的输入流。
    4.读取数据
    5.释放资源
    示例代码:
    package com.rl.tcp;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class TCPServer {
    public static void main(String[] args) throws IOException {
    //创建服务端的套接字
    ServerSocket ss = new ServerSocket(10000);
    //监听客户端的请求并且接受客户端的套接字
    Socket s = ss.accept();
    //获得输入流
    InputStream in = s.getInputStream();
    //获得数据
    byte[] bs = new byte[1024];
    int len = in.read(bs);
    String result = new String(bs, 0, len);
    System.out.println(“服务端接收的数据:”+result);
    //释放资源
    s.close();
    ss.close();
    }
    }
    TCP客户端:
    开发步骤:
    1.创建客户端socket对象
    Socket(String host, int port)
    创建一个流套接字并将其连接到指定主机上的指定端口号。
    2.获得输出流
    OutputStream
    getOutputStream()
    返回此套接字的输出流。
    3.写数据
    4.释放资源
    示例代码:
    package com.rl.tcp;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.UnknownHostException;
    public class TCPClient {
    public static void main(String[] args) throws UnknownHostException, IOException {
    //创建客户端的套接字
    Socket s = new Socket(“192.168.1.103”, 10000);
    //获得输出流
    OutputStream out = s.getOutputStream();
    out.write(“你好”.getBytes());
    out.close();
    s.close();
    }
    }
    TCP服务端的反馈
    服务端代码:
    package com.rl.tcp1;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    public class TCPServer {
    public static void main(String[] args) throws IOException {
    //创建服务端的套接字
    ServerSocket ss = new ServerSocket(10000);
    //监听客户端的请求并且接受客户端的套接字
    Socket s = ss.accept();
    //获得输入流
    InputStream in = s.getInputStream();
    //获得输出流
    OutputStream out = s.getOutputStream();
    //创建高效缓存区字符流
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
    String line = null;
    while((line = br.readLine()) != null){
    System.out.println(“接收到数据:”+line);
    bw.write(line.toUpperCase());
    bw.newLine();
    bw.flush();
    }
    bw.close();
    br.close();
    //释放资源
    s.close();
    ss.close();
    }
    }
    客户端代码:
    package com.rl.tcp1;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    public class TCPClient {
    public static void main(String[] args) throws UnknownHostException, IOException {
    //创建客户端的套接字
    Socket s = new Socket(“192.168.1.103”, 10000);
    //获得输出流
    OutputStream out = s.getOutputStream();
    InputStream in = s.getInputStream();
    //获得从控制台输入的流
    BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
    //服务器端返回的输入流
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
    //读取控制台的数据
    String line = null;
    while((line = br1.readLine()) != null){
    if(“exit”.equals(line)){
    break;
    }
    bw.write(line);
    bw.newLine();
    bw.flush();

    		String result = br.readLine();
    		System.out.println("服务端的反馈数据:"+result);
    	}
    	out.close();
    	s.close();
    }
    

    }

    展开全文
  • 不要小看JavaSE的这些基础章节,打好基础很重要!巧了,我这里涵盖了所有Java基础!

    所有知识体系文章,GitHub已收录,欢迎Star!再次感谢,愿你早日进入大厂!

    GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual

    搜索关注微信公众号“码出Offer”,送你学习福利资源!


    大家好,我是Ziph!🤗这篇文章记录了我学JavaSE阶段的所有内容与总结❗。整理出来,并分享在博客中!总结整理不易,不想被白嫖,大家多多点赞支持👍,评论留言!🙏


    首先👇,我还是要强调一下怎么去学习,要有一个怎样的学习习惯思想!这个对于初学编程语言来说很重要
    【专栏必读】来来来,让我教你怎么正确高效的去学JavaSE阶段学习内容(学习方法、心得与建议)


    👉JavaSE阶段章节目录(所有知识内容汇总)
    👉JavaSE阶段章节思维导图目录(所有知识内容对应的思维导图)
    👉JavaSE所有知识章节内容汇总思维导图(附:思维导图原processon地址可查大纲)
    👉JavaSE阶段学习资料下载(思维导图、习题和答案、各个阶段学习帮助文档API)
    👉Java8新特性(lambda表达式、函数式接口、方法引用、Stream API概论以及案例详解)


    JavaSE章节目录



    JavaSE思维导图目录



    Java8新特性

    如果学习完JavaSE阶段知识内容的童鞋们,可以选择学习一下Java8新特性哦!它能使你的代码更加精简化,而且还提升了你的知识储备和逼格~ 何乐而不为呢?是不是想想就香香的~

    【Java8新特性】让你的代码更加简单化(lambda表达式、函数式接口、方法引用、Stream API概论以及案例详解)


    学习资料下载

    正在将我总结的比较好的文章以及科班学习体系文章一个个的完善在GitHub中,我希望大家能到我的GitHub给上一个Star !现在我的GitHub虽然还没有完善多少技术文章,但是在你几个月后的今天,我的GitHub也将成为一个完整的Java学习体系!

    欢迎大家来GitHub下载思维导图帮助文档API练习题与答案

    GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual

    大家记得给我一个Star!笔芯!


    JavaSE阶段大结局

    总结不易,白嫖不香,点个赞👍再走呗!✔
    持续更新我的所学、所感、所知!😁我会在大家的目光下,一点点成长!大家一起加油!💪
    持续更新分享所有Java知识内容,我会不断的在博客里增加专栏内容🗯——从浅入深…👊

    附:JavaSE阶段知识路线图

    思维导图原processon工具地址:👉 JavaSE阶段知识路线图(地址内可查看思维导图大纲)

    JavaSE知识树


    展开全文
  • JavaSE基础总结(笔试面试题)

    万次阅读 多人点赞 2018-11-02 13:58:04
    JavaSE基础 1.对象实例化 2.类的重载: 3.不定长参数,本质是一个数组形式,int...a 4.方法中使用全局变量 this 5.形参列表中的变量是局部变量 6.构造方法的作用: 7.父类和子类中,静态代码块、代码块、构造...

    目录

    JavaSE基础

    1.对象实例化

    2.类的重载:

    3.不定长参数,本质是一个数组形式,int...a

    4.方法中使用全局变量 this

    5.形参列表中的变量是局部变量

    6.构造方法的作用:

    7.父类和子类中,静态代码块、代码块、构造方法、普通方法执行顺序

    8.修饰符修饰范围

    9.子类只能继承父类非private的方法

    10.instanceof

    11.抽象方法不可以被private修饰

    12.抽象类和接口的比较

    13.匿名内部类常用于实现接口或抽象类

    14.基本类型的包装类

    15.Integer.parseInt()和  Integer.valueOf()

    16.Object类中的方法:

    17.String,StringBuffer,StringBulider的区别

    18.BigDemail用于精确计算

    19.集合只能存放抽象数据类型

    20.两个对象相等,hashCode一定相同,但hashCode相同不一定是同一个对象

    21.equals 方法被覆盖之后,hashCode也一定会被覆盖

    22.ArrayList,Vector 使用数组实现,LinkedList使用的是双向链表

    23.ArrayList常用方法:

    24.解决ArrayList 线程不安全问题

    25.解决HashMap线程不安全问题

    26.堆和栈

    25.集合源码分析

    26.ArrayList和LinkedList区别

    27.Deque 中的LinkedList 和 ArrayDeque的区别

    29.final 、finally 、finalize

    30.IO体系中存在的设计模式:

    31.IO

    32.windows 系统中使用"\"表示的路径分隔符,但是 java 中"\"转义字符 ,所以"\\" 表示路径分割,或者"/"表示路径的分割建议使用这种形式

    33.集合和数据间的相互转化

    34.序列化和反序列化(对象流 ObjectInputStream和ObjectOutputStream)

    35.什么时候需要实现序列化,如何实现?

    36.深克隆和浅克隆

    37.标志性接口:

    38.进程和线程的区别

    39.多线程作用:

    40.多线程的实现方式

    42.多线程中不要调用run()方法,不然多线程会失效

    43.多线程的生命周期

    44.sleep(),wait()方法的区别 

    45.线程控制:加塞join()(插队)

    46.线程安全

    47.synchronized 锁对象的时候,可以使用任意的对象

    48.volatile关键字

    49.synchronized关键字

    50.并发和并行

    51.原子性问题解决方案

    52.Lock锁

    53.Lock锁和synchronized的区别

    54.条件锁 Condition  需要结合Lock锁

    54.线程池中的线程是由线程创建的,程序员只需要创建线程池就可以

    55.线程池创建的四种方式

    56.线程池的任务:Callable或者Runnable任务

    57.四种线程池的底层:ThreaPoolExecutor

    58.同步容器:synchronize修饰,产生性能影响

    59.并发容器:jdk1.5提出,改善同步容器性能,专门为并发环境设计

    60.HashMap、HashTable、ConcurrentHashMap的区别

    61.Java中的Callable和Runnable有什么区别

    62.Volatile

    63.如何在两个线程间共享数据?

    64.为什么wait, notify 和 notifyAll这些方法不在thread类里面

    65.什么是FutureTask

    66.为什么要使用线程池

    67.死锁现象

    68.死锁解决办法

    69.检测一个线程是否有锁

    70. 有三个线程T1,T2,T3,怎么确保它们按顺序执行

    71.泛型的作用

    72.如不指定泛型:集合中存放的数据默认为Obiect类型的

    补充

    1.构造方法不能被重写,但可以重载,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次声明。

    2.抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized

    3.静态变量、实例变量

    4. == 和 equale()区别

    5.switch 后类型

    6.数组中没有length方法,但是有length属性,字符串有length方法,javaScript中字符串长度使用length属性

    7.数据类型转换

    8.流的分类

    9.volatile 和 synchronized 的区别

    10.叙述对于线程池的理解

    11.对Java反射的理解

    12.谈谈JVM的内存结构和内存分配

    13.Java中的引用类型

    14.栈和堆的区别

    15.类的初始化

    16.垃圾回收算法

    17.垃圾收集算法

    18.JDBC连接数据库的步骤

    补充

    1.什么时候使用二叉树

    2.先序遍历规则

    4.三次握手和四次挥手  http://blog.51cto.com/jinlong/2065461

    5.HTTP请求/响应步骤

    6.折半查找:最多次数  log(2n)+1


    JavaSE基础

     

    1.对象实例化

        (1)Class.forName(“类的全名称”);

        (2)Person person = new Person();

    2.类的重载:

               类名相同,形参列表不同(类型,顺载序,个数),system.out.println();也是方法重

    3.不定长参数,本质是一个数组形式,int...a

    • 定义方法时不确定有几个入参时使用
    •  一个方法中只能有一个,位于形参末尾

    4.方法中使用全局变量 this

    1. 全局变量(成员变量/成员属性):编写在类中
    2. 局部变量:声明在方法或者代码块中

    5.形参列表中的变量是局部变量

    6.构造方法的作用:

         使用构造方法创建对象并且可以为类中的属性赋值(实例化对象)

    • 构造方法在创建的时候就给对象初始化; 一个对象建立构造方法只能运行一次;
    • 一般方法是对象调用才执行,给对象添加对象具备的功能; 一般方法可以被对象多次调用;

    注意:多态分类

    运行时多态(重写时多态)

         父类引用接收子类的对象

    编译时多态

        方法重载方法名相同形参列表不同

    7.父类和子类中,静态代码块、代码块、构造方法、普通方法执行顺序

     父类中的静态变量和静态代码块

     子类中的静态变量和静态代码块

     父类中的普通变量和代码块->构造方法

     子类中的普通变量和代码块->构造方法

     变量和代码块的执行与声明顺序有关,变量一般声明在代码块前

    8.修饰符修饰范围

                ​

    9.子类只能继承父类非private的方法

    10.instanceof

           instanceof是一个二元操作符,用法是:boolean result = a instanceof ClassA,即判断对象a是否是类Class A的实例,如果是的话,则返回true,否则返回false。向下转型,需要先向上转型,而且只能转化为本类对象

                             ​

    11.抽象方法不可以被private修饰

    12.抽象类和接口的比较

     

    抽象类

    接口

    构造方法

    可以有

    不可以有

    方法

    可以有抽象方法和普通方法

    只能有抽象方法,但1.8版本之后可以有默认方法

    实现

    子类用extend来实现

    用implments实现

    修饰符

    public、default、protected

    默认public

    变量

    可以有常量也可以有变量

    只能是静态常量默认有public static final修饰

    main方法

    可以有

    不可以有

    多继承

    单继承

    实现多个接口

    静态方法

    可以有

    不可以

    速度

    比较快

    比较慢

    13.匿名内部类常用于实现接口或抽象类

    14.基本类型的包装类

            int - Interger        char - character

           在-128~127之间的Integer值,用的是原生数据类型int,会在内存里供重用,也就是说这之间的Integer值进行==比较时只是进行int原生数 据类型的数值比较,而超出-128~127的范围,进行==比较时是进行地址及数值比较。

                              ​

    15.Integer.parseInt()和  Integer.valueOf()

         Integer.parseInt()返回值为基本数据类型

         Integer.valueOf()返回值为包装类型

    16.Object类中的方法:

        equals(),finalize(),clone(),getClass()(返回运行时的类,有且仅有一份,可用  对象.getClass()  或者  forName.getClass(),)wait(),notify(),notifyAll(),hashCode(),toString().

    17.String,StringBuffer,StringBulider的区别

           String只读字符串,意味着其引用的字符串内容不能发生改变

           StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改。

           StringBuilder 是 Jdk1.5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,

        因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比StringBuffer 要高。

    18.BigDemail用于精确计算

               ​

    19.集合只能存放抽象数据类型

    20.两个对象相等,hashCode一定相同,但hashCode相同不一定是同一个对象

    21.equals 方法被覆盖之后,hashCode也一定会被覆盖

    22.ArrayList,Vector 使用数组实现,LinkedList使用的是双向链表

    23.ArrayList常用方法:

     set(),get(),size(); HashMap常用方法:put():添加对象:get():获得对象的值;

     size():查看集合中的数据有多少个 

    迭代方式

    1. for循环
    2. foreach
    3. 迭代器(collection接口下的集合都可使用)

                       ​

    4.jdk1.8中出现了stream流

                    ​

       Map迭代  (1)将Map转化为Set集合,使用keySet

                      Set<String> keySet = mapkeySet();

                           (2)1.8新特性

                              map.forEach((k,v)->{

                                     system.out.println(k+"="+v);

                                 });

    24.解决ArrayList 线程不安全问题

        (1)转化为线程安全的类

                 ArrayList = Collection.synchronizedList(arrayList);

           (2)并发环境下可以使用CopyOnWriterList

    25.解决HashMap线程不安全问题

       (1)转化为线程安全类

             map = Collection.synchronizedMap(map);

           (2)并发环境下可以使用CurrentHashMap

    26.堆和栈

       堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。

       {堆是指程序运行是申请的动态内存,而栈只是指一种使用堆的方法(即先进后出)。}栈是先进后出的,但是于堆而言却没有这个特性,两者都是存放临时数据的地方。

        队列:先进先出,栈:先进后出  

    25.集合源码分析

      (1)ArrayList  

           List接口可变数组非同步实现,每次扩容扩为原来的1.5倍,线程不安全

      (2)Vector

           API与ArrayList相同,基于数组实现,可扩容,有synchronize修饰,线程安全 

      (3)LinkedList

           底层是双向链表,非同步,同时实现List和Deque,可以当队列使用,线程不安全

      (4)ArrayDeque

           使用数组实现的双端队列

      (5)HashSet

           底层使用哈希表实现(数组+链表),实际是由一个HashMap的实例支持的,允许使用NULL值

              使用该方法时,需要重写equals和hashCode方法。

      (6)LinkedHashSet

           哈希表+双向链表实现

      (7)HashMap

           底层使用哈希表(散列链表/数组+链表)实现,数组中每一项是个单向链表,即数组和链表的结合体,可以存储NUll值,1.8之后采用

              散列列表+红黑树的方式,线程不安全

      (8)HashTable

           底层使用数组实现,数组中每一项是个单链表,即数组和链表的结合体,key和value不能为NUll

    26.ArrayList和LinkedList区别

      ArrayList底层是用数组实现的顺序表,是随机存取类型,可自动扩增,并且在初始化时,数组的长度是0,只有在增加元素时,长度才会增加,默认是10,不能无限扩增,有上限,在查询操作的时候性能更好

      LinkedList底层是用链表来实现的,是一个双向链表,注意这里不是双向循环链表,顺序存取类型。在源码中,似乎没有元素个数的限制。应该能无限增加下去,直到内存满了在进行删除,增加操作时性能更好。      

    27.Deque 中的LinkedList 和 ArrayDeque的区别

            LinkedListDeque使用的是链表实现的双端队列

            ArrayDeque 使用的是数组实现双端队列

    28.catch 可以出现多次,首先捕获小异常,然后捕获大异常

    29.final 、finally 、finalize

       final 用于声明变量,方法,类,表示变量不可改变(引用不能改变,只可以改变),方法不能重写,类不可以被继承

       finally 用于异常处理中,表示,必须要执行的代码块,除非java虚拟机停止工作,否则一定会执行

       finalize() 是Object类中的一个方法,用于java虚拟机的垃圾回收

    30.IO体系中存在的设计模式:

      装饰模式 - 用于动态的给对象添加一些功能,类似于继承,但是比继承更加灵活

    31.IO

      BIO 传统IO,阻塞并同步    NIO,同步非阻塞   AIO 非同步非阻塞

    32.windows 系统中使用"\"表示的路径分隔符,但是 java 中"\"转义字符 ,所以"\\" 表示路径分割,或者"/"表示路径的分割建议使用这种形式

    33.集合和数据间的相互转化

     (1)集合转数组

               List list = new ArrayList();

               String [] arr = list.toArray(new arr[list.size()]);

     (2)数组转集合

               String [] arr;

                List list = Array.asLast(arr);

    34.序列化和反序列化(对象流 ObjectInputStream和ObjectOutputStream)

        对象序列化:将对象以二进制的形式保存到硬盘上

        对象反序列化:将硬盘上的二进制文件转化为对象输出      

    35.什么时候需要实现序列化,如何实现?

        把一个对象写入数据源或者将对象从数据源读出来,序列化对象要实现serializable接口(标志性接口,方法为空)      

    36.深克隆和浅克隆

      浅克隆:对象需要Cloneable 并重写 clone() 方法  

       深克隆:对象要实现Cloneable,Serialzable接口,引用要实现Serialzable接口,先将对象以流的方式写入,然后读出,完成深克隆

    37.标志性接口:

       接口中的内容为空,如Cloneable和Serialzable

    38.进程和线程的区别

       进程指得是操作系统对于某一事件的程序实例

       线程是微观的进程,进程有一个或者以上的线程组成

    39.多线程作用:

       降低开发和维护开销,并提高复杂应用的性能,提高资源利用率和吞吐量

    40.多线程的实现方式

        (1)继承Thread类并重写run()方法;

           (2)实现Runnable接口并重写run方法;

           (3)实现Callable接口由FeatureTask创建

           (4)通过线程池创建 如ExecutorService

    42.多线程中不要调用run()方法,不然多线程会失效

    43.多线程的生命周期

           新建:当通过new操作符创建一个线程时,处于新建状态

           就绪:使用start()方法之后处于就绪状态

           运行:真正执行run()方法

           阻塞:执行了sleep()、wait() 方法后

           死亡:当线程执行完或者因为异常退出run()方法后

    44.sleep(),wait()方法的区别 

       sleep() 属于Thread类,wait() 属于Object类

       sleep()执行后不会释放对象锁,wait()会释放对象锁,重新进入就绪状态需要notify()或者notifyAll方法

    45.线程控制:加塞join()(插队)

                 睡眠sleep()没有放弃CPU的执行权

                          让步yield()放弃CPU的执行权

    46.线程安全

       指的是多线程访问同一个方法、对象或代码时不会产生不确定的结果  

      引起线程安全的原因:存在多条线程共同操作的共享数据

    47.synchronized 锁对象的时候,可以使用任意的对象

    48.volatile关键字

          使用该关键字修饰变量  表示变量是多线程可见的。每一个线程在运行的时候自己的线程内存,线程内存中存放的是主内存的数据的拷贝。如果使用volatile关键字修饰变量,线程在使用变量的时候不是从线程内存中获取,而是从主内存中获得数据。

    49.synchronized关键字

       当synchronized修饰静态方法时,修饰的是当前类的class对象锁

       当synchronized修饰实例方法时,修饰的时对象中的实例方法

    50.并发和并行

       并发:一个处理器同时处理多个任务

       并行:多个处理器处理不同的任务

    51.原子性问题解决方案

      (1)使用同步代码块或同步方法  

      (2)使用原子性操作的类 java.util.concurrent.atomic  底层使用CAS实现 (CompareAndSwap)

    52.Lock锁

       实现类为ReentrantLock   Lock lock = new ReentrantLock();

                                                   lock.lock();

    53.Lock锁和synchronized的区别

       Lock产生异常时不会自动释放锁  所以要在finally中释放锁(lock.unlock();)

       synchronized修饰的锁产生异常时会自动释放

    54.条件锁 Condition  需要结合Lock锁

    54.线程池中的线程是由线程创建的,程序员只需要创建线程池就可以

    55.线程池创建的四种方式

    ExecutorService executor1 = executors.newSingleThreadExecutor();//创建只有一个线程的线程池
    
    ExecutorService executor2 = executors.newFixedThreadPool(10);//创建一个固定数量线程的线程池
    
    ExecutorService executor3 = executors.newCachedThreadPool();//创建一个可拓展的线程池,没有上限
    
    ExecutorService executor4 = executors.newScheduledThreadPool();//创建一个可以轮序执行的

    56.线程池的任务:Callable或者Runnable任务

    57.四种线程池的底层:ThreaPoolExecutor

    58.同步容器:synchronize修饰,产生性能影响

    59.并发容器:jdk1.5提出,改善同步容器性能,专门为并发环境设计

       (1)HashMap(线程不安全)、HashTable(线程安全)  可以用  ConcurrentHashMap代替

       (2)ArrayList、vector 可以使用 CopyOnWriteArrayList

       (3)set 可以使用CopyOnWriteArraySet

       (4)Queue 可以使用 ConcurrentLinkedQueue(高性能队列) 或linedBlokingQueue(阻塞队列)

                  https://www.jianshu.com/p/ff872995db56

    60.HashMap、HashTable、ConcurrentHashMap的区别

           1.HashMap线程不安全,HashTable和ConcurrentHashMap线程安全,所以HashMap运行效率高

           2.HashMap的Key和Value可以是null值,HashTable和ConcurrentHashMap不行

           3.HashTable和ConcurrentHashMap之间的主要差别在于性能方法。ConcurrentHashMap采用"分段锁",性能比HashTable要好

    61.Java中的Callable和Runnable有什么区别

        两者都用来代表线程中的任务,Runnable从1.0版本就有,Callable出现在1.5版本当中,主要区别是,Callable的call()方法可以有返回值和异常,Runnable的run()方法不行,Callable可以返回带有计算结果的Future对象

    62.Volatile

      volatile是一个特殊修饰符,可以保证下一个读取操作是在上一个写操作之后。

    63.如何在两个线程间共享数据?

     1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,卖票系统就可以这么做。

     2.如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,

     例如,设计4个线程。其中两个线程每次对j增加1,另外两个线程对j每次减1,银行存取款

    64.为什么wait, notify 和 notifyAll这些方法不在thread类里面

      因为Java中的锁是对象级别的,wait,notify,notifyAll等操作都是锁级别的操作

    65.什么是FutureTask

       在Java并发程序中FutureTask表示一个可以取消的异步运算。只有当运算完成的时候结果才能取回,如果运算尚未完成get方法将会阻塞。

    66.为什么要使用线程池

         因为线程的创建需要花费昂贵的资源和时间,线程池可以在程序开始运行时就创建若干线程来响应处理。

    67.死锁现象

        指的是两个或两个以上的线程执行过程中,为争夺资源出现相互等待的现象

    68.死锁解决办法

        最简单的办法是阻止循环等待条件,规定线程争夺资源是以一定的顺序进行的。

    69.检测一个线程是否有锁

        java.lang.Thread中的一个方法holdsLock(),返回true

    70. 有三个线程T1,T2,T3,怎么确保它们按顺序执行

       使用join()方法

    71.泛型的作用

        约束集合中数据的类型,所谓的泛型就是允许在定义类、接口、方法时使用类型形参。

    72.如不指定泛型:集合中存放的数据默认为Obiect类型的

     

    补充

    1.构造方法不能被重写,但可以重载,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次声明。

    2.抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized

            都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如 C 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。 synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

    3.静态变量、实例变量

       静态变量属于类,实例变量依存于某一实例

    4. == 和 equale()区别

      一个是修饰符,一个是方法,

     ==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等,

    equals():用来比较方法两个对象的内容是否相等,equals方法不能比较基本数据类型。

    5.switch 后类型

           byte、short、int、char、字符串、枚举

    6.数组中没有length方法,但是有length属性,字符串有length方法,javaScript中字符串长度使用length属性

    7.数据类型转换

      (1)字符串如何转化为基本数据类型?

         调用基本数据类型对应的ParseXXX(String)方法或Valueof(String)。

      (2)基本数据类型转化为字符串

          用“”与基本数据类型+,或是调用toString()方法。

    8.流的分类

        1.流的方向:输入输出流

           2.实现功能:节点流和处理流

           3.处理数据的单位:字节流和字符流

    9.volatile 和 synchronized 的区别

     (1)volatile 表示变量的值在工作内存中是不确定的,需要在主内存中去获取,synchronized 则是锁定当前变量,只有当前线程可以访问            该变量,其他线程只能被阻塞。

     (2)volatile只可以使用在变量级别,synchronized可以使用在变量、方法、类级别。

     (3)volatile只可以实现变量修改的可能性,不能保证原子性,而synchronized则可以保证变量修改的可见性和原子性。

     (4)volatile不会造成线程阻塞,synchronizedhui造成线程的阻塞。

     (5)volatile标记的变量不会被编译器优化,synchronized标记的变量可以被编译器优化

    10.叙述对于线程池的理解

       线程池是指事先将线程对象放到一个容器当中,这样,可以减少new线程的时间,提高代码执行的效率,通常,使用java.util.concurrent.Executor来创建线程池,可以创建四类线池,通过newSingleTHreadExecutor可以创建有一个线程的线程池,通过newFixedThreadPool创建一个指定数量的线程池,通过newCachedThreadPool可以创建一个可拓展的线程池,通过newScheduleThreadPool可以创建一个周期性执行的线程池,通过使用线程池,可以降低能源消耗,提高响应速度,调高线程的可管理性。

    11.对Java反射的理解

            反射就是把java类中的各种成分映射成一个个的Java对象

           Java中的反射首先要能获取到Java重要反射的类的字节码,通过,Class.forName(类的全名称),类名.class和ths.getClass(),然后把字节码中的方法,变量,构造函数等映射成相应的类,然后就可以调用丰富的方法。

          JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

    12.谈谈JVM的内存结构和内存分配

           JVM内存结构:分为四个部分:1.方法区   2.Java栈   3.Java堆  4.程序计数器)

           方法区:静态分配,源代码中的命名常量,类信息、String常量和static变量都保存在方法区

           栈:栈空间有可能是连续的,也有可能是不连续的,最典型的应用是方法调用(分为虚拟机栈和本地方法栈)

           堆:堆内存是随意分配的

           程序计数器(线程执行字节码行号)

    13.Java中的引用类型

     (1)强引用:垃圾回收机制不会回收

     (2)软引用:内存够用不会回收,内存不够,一定回收

     (3)弱引用:只要发现就会被回收

     (4)虚引用:一定回收,要结合引用队列使用

    14.栈和堆的区别

        1.申请方式

           栈:由系统自动分配

           堆:程序员自己分配,并指明大小,

      2.申请效率

           栈:系统自动分配,速度快

           堆:由new分配的内存,速度比较慢

    15.类的初始化

     (1)创建类的实例,new一个关键字

     (2)访问某个类或接口的静态变量,或者对该静态变量赋值

     (3)调用类的静态方法

     (4)反射(Class.forName(“类的全名称”))

     (5)初始化一个子类

    16.垃圾回收算法

    1. 应用计数算法
    2. 根搜索算法

    17.垃圾收集算法

    1. 标记-清除算法
    2. 复制算法
    3. 标记-整理算法

    18.JDBC连接数据库的步骤

    (1)加载jdbc驱动程序

    (2)提供jdbc连接的URL地址

    (3)创建数据连接

    (4)创建一个Statement对象

    (5)执行sql语句

    (6)处理结果

    (7)关闭jdbc对象

    补充

    1.什么时候使用二叉树

      在处理大批量的动态的数据是比较有用。

    2.先序遍历规则

       (1)访问根节点

       (2)先序遍历左子树

       (3)先序遍历右子树

      中序遍历规则

       (1)中序遍历左子树

       (2)访问根节点

       (3)中序遍历右子树

      后序遍历规则

       (1)后序遍历左子树

       (2)后序遍历右子树

       (3)访问根节点

    4.三次握手和四次挥手  http://blog.51cto.com/jinlong/2065461

      (1)三次握手(TCP连接的建立):为了建立可靠通信信道

      a.由客户端建立TCP连接的请求报文,其中报文中含有seq序列号,是由发送端

    随机生成的,并且将报文中的SYN字段设置问1,表示需要建立TCP连接。

    ( SYN=1,seq=x,x为随机生成数值)

    b.由服务器回复客户端发送的TCP连接请求报文,其中seq是序列号,是由服务器随机生成,并将SYN设置为1,而且会产生ACK字段,ACK的数值是客户端发送过来的序列号seq的基础上+1,进行回复,以便客户端收到信息时,知晓自己的TCP建立请求已得到验证(SYN=1,ACK=x+1,seq=y,y为随机生成数值)这里的ack加1可以理解为是确认和谁建立连接。

         c.客户端收到服务端发送的TCP连接建立验证请求后,会使自己的序列号加1表示,并且在此回复ACK验证请求。(SYN=1,ACK=y+1,seq=x+1)

                                      http://i2.51cto.com/images/blog/201801/26/cf32189db2b594d6f239ea75d4f7b652.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

    (2)四次挥手(TCP连接的断开):

    a.客户端发送断开的TCP请求报文,其中报文中包含seq序列号,是由发送端随机生成,并且将报文中的FiN字段设置为1,表示需要断开TCP连接,(FIN=1,seq=x,x由客户端随机生成)

    b.服务端会回复客户端发送的TCP断开请求报文,其包含seq序列号,是由回复端随机生成的而且会产生ZCK字段,ACK字段实在客户端发送过来的seq序列号基础上+1进行回复的,以便客户端收到收到信息时,知晓自己的TCP断开请求已经得到了验证。

    c.服务端在回复完客户端的TCP断开请求后,不会马上进行TCP的连接断开,服务端会确保断开前,所有的输送数据传输完毕,一旦确认传输数据完毕,将会将回复报文的FIN字段设置为1,并且产生seq序列号。(FIN=1,ACK=x+1,seq=z,z由服务端随机生成)

    d.客户端收到服务端的TCP断开请求后,会回复服务端的断开请求,包含随机生成的seq字段和ACK字段,ACK会在服务器的TCP断开请求的seq基础上+1.从而完成服务端请求的验证回复。(FIN=1,ACK=z+1,seq=h,h为客户端随机生成)。

                                      http://i2.51cto.com/images/blog/201801/26/7b0328d95ac0eb055d1e38e0e27e0ba8.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

    5.HTTP请求/响应步骤

      (1)客户端连接到Web服务器

      (2)发送http请求

      (3)服务器接受请求并返回Http响应

      (4)释放连接

      (5)客户端浏览器解析HTML内容

    6.折半查找:最多次数  log(2n)+1

    展开全文
  • 什么是JavaSE,写给第一次接触Java的人

    万次阅读 多人点赞 2017-01-17 23:56:54
    Java语法基础 Java开发环境搭建 Java概述 Java是一门编程语言,是用来编写软件的。QQ、迅雷、淘宝、京东等等这些常用软件都可以...JavaSE是java分类中的标准版,是刚接触java要学习的基础知识。 JavaEE是java分类中的企

    Java语法基础

    Java开发环境搭建

    Java概述

    Java是一门编程语言,是用来编写软件的。QQ、迅雷、淘宝、京东等等这些常用软件都可以用Java来编写。
    其实,Java最擅长的是编写如下类型的软件:
    1、互联网:电商、P2P
    2、企业级应用:ERP、CRM、BOS、OA

    JavaSE是java分类中的标准版,是刚接触java要学习的基础知识。

    JavaEE是java分类中的企业版,是java中的高级,涉及到的知识广泛。

    JavaME中M是Micro的缩写,用在嵌入式等电子设备中。


    DOS命令

    刚开始运行java程序的时候是在DOS窗口中运行,并不像我们常见的一些应用程序直接双击图标就可以运行。

    调用DOS窗口的步骤:win图标+R > 输入 cmd > 回车:



    一些常用的DOS命令:

    清屏:cls

    切换盘符: :

    进入指定目录: cd

    返回上一级目录:cd..

    返回盘符根目录: cd\

    显示当前目录下的文件和子目录信息:dir


    Java 开发环境介绍

    Java的开发环境需要安装,包括JDK(Java Development Kit)和JRE(Java Runtime Envionment)。

    其中:JDK=JRE+开发工具;JRE=JVM+类库。

    软件开发人员需要JDK,如果只需要运行java文件,只需要安装JRE。


    Java语言的优点

    跨平台性是java最大的亮点。
    java程序可以在任意操作系统上运行,一次编写 到处运行,真正的一劳永逸。
    而支持java语言这么做正式JVM(Java Virtual Machine)。






    展开全文
  • JavaSe_基础篇(一)

    千次阅读 2018-12-17 19:12:13
    (一)HelloWord案例 代码: 运行结果: (二)常见的命名规则(见名知意) ...组成规则:英文大小写字母、数字字符、$和_ ...注意事项:不能以数字开头、不能是Java中的关键字、严格区分大小写 ...
  • javaSE试题(一)

    万次阅读 2019-01-07 20:15:04
    一、填空题(共20个题目,总计20分) 1.安装JDK后,为了告诉计算机javac.exe和java.exe等执行文件的位置,需要配置的环境变量是___path__________。 2.Java提供了三种注释类型,分别是单行注释,多行注释和______...
  • JavaSE

    2019-04-03 22:58:16
    Q1、 String 、StringBuffer、StringBuilder 区别及底层实现 1、String是字符串常量, StringBuffer、StringBuilder是字符串变量 2、StringBuffer线程安全(方法用了synchronized修饰)、StringBuilder线程不安全 ...
  • JavaSe--(一)

    2020-06-05 15:52:23
    一、Java中的注释: 注释的目的:方便我们阅读代码,不会影响到程序的运行,在从.java中编译成为.class时候,注释会消除掉。 注释的分类: 单行注释: // 多行注释:/* 注释的内容 / 文档注释: ...
  • JavaSe--(二)

    2020-06-07 17:15:47
    重点: 变量 运算符 一、什么是变量 变量是内存中装载数据的小盒子,你只能用它来存数据和取数据。 二、数据类型 (1)我们知道基本的数据类型有四种:整数类型、浮点数类型、字符类型、布尔类型,但是由于这...
  • Java SE是什么?Java各个版本区别

    千次阅读 2019-04-24 15:45:33
    一、Java的各个常用版本: Java SE、java EE、...(Java SE下载:https://www.oracle.com/technetwork/java/javase/downloads/index.html) 1. Java SE(Java Platform,Standard Edition) Java se 以前称...
  • 三年JavaEE开发积累的那些代码之一:JavaSE篇 有什么? 1)自己写的例子:或是为了项目中应用写的demo,或是为了学习某项技术写的demo。 2)网上下载的例子:或改过或没改过,或完善过或原封没动。 没什么? 1)公司...
  • javaSE

    2013-05-30 00:18:14
    javaSE
  • JavaSE

    千次阅读 2018-06-24 17:11:47
    JavaSE
  • JAVASE

    千次阅读 2018-10-06 16:04:48
    JAVASE day01 1.什么是软件(software)? (1)对软件的定义及认识 软件:是指一系列按照特定顺序组织的计算机数据与指令的集合。 数据:能够被计算机所识别的都是数据 avi mp3 txt png。 指令:计算机的操作步骤。 ...
  • javaSE学习笔记_目录

    千次阅读 多人点赞 2018-12-09 18:43:14
    javaSE (二十九)IO.read()输出是int的原因、fileoutputstream的追加功能、用byte[]优化拷贝文件、Buffered缓冲区内存示意图 javaSE (三十)IO流异常处理、图片加密处理、输入文件路径并拷贝文件内容、在文件中键入...
  • javase

    2019-02-23 11:30:24
    JAVA基础
  • JavaSE笔记总结

    2019-06-04 20:19:53
    这里面由我自己总结的一些JavaSE知识点总结。
  • javaSE项目

    2013-09-01 22:02:27
    当今物联网技术即将流行,这个javaSE项目中有基本的java知识点。包括数据库和数据库连接池的灵活运用,swing窗体,以及多线程的例子,运用了java的基本基础知识点
  • javaSE (四十二)javaSE阶段性总结

    千次阅读 2018-12-15 18:25:24
    javaSE学习笔记 终于把javaSE补完了,累啊 写博客是为了自己专注于学习和总结,现在看来效果比手书好多了 下一阶段: 继续学javaEE 算法温习强化 学校的课题 ...
  • javaSE JDK1.8

    2017-07-12 06:56:42
    根据jdk1.8制作的chm

空空如也

1 2 3 4 5 ... 20
收藏数 131,652
精华内容 52,660
关键字:

java se

java 订阅