java总结

java

一. 关键字,标识符,常量

1. 学习了计算机基础知识(软件/硬件)

2. java语言的特点:

       面向对象语言的一种

​       跨平台

​       开源

3. 了解了java平台版本以及历史.

4. 开发一个Java应用程序

       jre:Java程序运行环境,也包括jvm以及java所需的核心类库.

​       jvm:java虚拟机

​       jdk:java开发工具包,包含jre以及开发工具的包.
                  三者之间的关系: jvm<jre<jdk

5. 了解了什么是关键字:

       关键字是指被Java语言赋予特定含义的词.

​       class :表示创建一个类(Java语言最基本的单元)

​       public:权限修饰符的一种

​       static:静态修饰符号

​       void:和java的方法有关

6. 什么是标识符:

 针对包,类,接口,方法,变量,常量等起名字的字符序列

标识符的组成:
​      26个英文字母(大小写)

​      数字字符

​      $符号

​      _下划线符号

​      .严格区分大小写的

标识符的注意事项:
        1.数字字符不能作为标识符的开头位置
        2.不能是Java中的关键字
        3.Java严格区分大小写,我们在起名字的时候:见名知意
        4.满足条件:满足组成的一种即可!不能是非法字符

7. 包,类,接口,方法,变量,常量,书写规则

     包: (目录/文件夹) 都是字母小写  或者可以有"_"

​     类:  如果是一个单词   首字母大写 其余小写                      例:     class Student{}

           如果是多个单词组成    每个单词首字母都大写 其余小写          例:     class DataTypeDemo{}

​     接口:      与 类 相同

​     方法: 如果是一个单词  字母全部小写                             例: main ()

                                                                 int price = 10;

            如果是多个单词   第一个单词全部小写 从第二个单词开始每个单词的首字母大写其余小写

                                  例: checkUserName

                                    int appleprice = 10;

​     变量:        与 方法 相同

​     常量:   如果是单个单词  字母全部大写                                例:HELLO

             如果是多个单词  每个单词字母都大写  单词与单词之间用"_"隔开

8. 什么是常量:

在程序执行过,其值不发生改变的量     分为: 字面值常量  自定义常量

1.字面值常量:

​       字符串常量:使用双引号包裹起来的内容:称为"字符串常量"      "HelloWorld"

​       字符常量:    使用单引号包裹起来的内容      'a'        'A'

​       整数常量:    100    56 

​       小数常量:    2.15    0.64

​       布尔常量:    true    false 

​       空常量:      null

2.自定义常量(面向对象  关键字 final) 

​       进制也属于常量

二. 变量,运算符

1. 了解了更简单的方法: 8421码 可以快速的进行二进制到十进制,十进制到二进制的转换.

2. 有符号位的数据表示法

计算机底层对数据的计算: 是通过补码进行运算的

​    正数的 原码 反码 补码 相同

​    负数的最高符号位为1  

​    负数的反码是在原码的基础上,最高符号位不变,数值位按位取反.

​    负数的补码是在反码的基础上,最高符号位不变,数值位末尾+1.

3. 变量 在程序执行过程中,其值发生改变的量

变量的三要素

数据类型   

变量名: 满足标识符规则  

初始化值: 满足的范围即可

      格式:   数据类型  变量名 = 初始化值

4. 数据类型 :在Java中,数据类型分为两大类型:

A)基本数据类型:四类八种   (研究的都是基本类型)
    整数类型:默认int
           字节类型             byte          占1个字节(8个比特位) 取值范围:-128~127
           短整型              short          占2个字节
           整数默认类型         int            整数默认类型 占4个字节
           长整型              long           占8个字节
                                注意事项:必须在long的初始化值的末尾加L或者l
                                    
    浮点类型:默认类型double
           单精度         float      单精度      占4个字节
                                注意事项:
                                        float f = 12.56F ; //后面加上F或者f
           双进度         double     双进度       占8个字节
                                
    字符类型      char                           占2个字节 
                 初始化值:单引号括起来的单个内容
                                
    布尔类型      boolean     不会参与类型转换:仅仅表示真,假          占1个字节
                             要么是true/要么false
                                int a = 10 ;
                                int b  =20 ;
                                比较a与b是否相等:获取到boolean类型的结果
B)引用数据类型:后面说
             数组,类,接口
 

5. 定义变量的注意事项:

在java语言(强类型语言:语法结构很严谨)中,同一个变量不能重复定义
                                 (javascript语言:弱类型语言:可以去重复定义变量)

​      一行就写一个变量即可!  一行结束之后分号;(代码规范风格)

​      一行也可以定义多个变量;

​      变量要么直接初始化,要么先定义,但是必须在使用之前对其进行初始化

变量要进行运算,必须要确定数据类型的一致

​           在Java中有一个隐式类型转换: byte,short,char三者之间不进行相互转换,

​           参与运算, 优先转换为int类型,long,float-double类型

6. 显示转换与隐式转换

显示转换(强制转换) :      大的数据类型----->小的数据类型
             格式:      目标数据类型 变量名  = (目标数据类型)初始化值;   会有损精度!

隐式转换:(隐式类型提升)    byte,char,short三者之间不转换,一旦参与运算,优先提升为int...

​       超出了 byte类型 的范围为-128~127   

​       先算出int 类型的二进制(4字节)  然后化为byte(1字节) 类型的二进制

​       最高符号为0,原码 ,反码,补码都相同

​       最高符号为1 数值位-1 求反码  数值位按位取反求原码

7. Java中的运算符号:

(1) 算术运算符            +     -     *      /        %
    扩展算术运算符        ++     --

第一种:        
    ++或者--单独使用

​    无论++或者--在数据前面还是数据后:都是对当前数据本身自增1或者自减1
​    
第二种:
​    ++或者--参与运算使用
​    
​    如果++或者--在数据的前面:需要先进行自增1或者自减1,然后再参与运算!

​    如果++或者--在数据的后面:先进行运算,然后再进行自增1或者自减1

(2) 赋值运算符             =

    扩展的赋值运算符:将符号右边的数据和左边的数据相加,然后再赋值给左边的这个变量
                    +=,-=,*=,/=,%=

   +=举例:
       int a = 10 ;
       a += 20 ;
       类似于 a = a + 20 ;

   举例:

short s = 1;

1)s = s + 1 ;
2)s+=1 ;

以上代码1),2)哪一句会编译失败?为什么?哪一句编译成功?
1)编译失败
byte,short,char三者不转换,一旦参与运算,先提升为int类型,然后再参与运算!

2)编译成功:
        s+= 1  ; 类似于s = s + 1 ;   
        扩展的赋值运算符中:
            特点:隐藏了强转类型转换
            等价于 s = (short)(s+1) ;

8. 关系(比较)运算符

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

无论我们的表达式是简单还是复杂的,最终比较运算符的结果不是true,就是false

注意:        ==不能写成= 

​        数学表达式:
         3 <=x <=5    x>=3 && x<=5 Java语言(逻辑符号)    

9. 逻辑运算符

基本的逻辑运算符号:
​    逻辑单与:       &              并列关系(满足全部条件)         有false,则false
                
​    逻辑单或:       |              或的关系:满足一个条件即可       有true,则true
                 
​    逻辑异或:       ^              相同则为false,不同则为true

​    逻辑非:         !             非true,则false;非false则true         偶数个非是他本身
扩展的逻辑运算符:

​    逻辑双与:       &&             左边有false,右边则不执行

​    逻辑双或:       ||             左边有true,右边则不执行

10. 位运算符

基本的位运算符号: 

​     位与:              &             有0则0

​     位或:              |             有1则1
​            
​     位异或:            ^             相同则为0 不同则为1   

​                                       特点:  一个数据被另一个数据位异或两次,其值是他本身!

位运算之位移符号:

​    <<:    左移
​        将数据的补码进行左移动,右边不够的补0;将最高符位丢弃掉
​    >>:    右移
​        将数据的补码进行右移动;如果最高符号位为1,则左边补1;
​        最高符号位为0,则左边补0;
​    >>>:    无符号右移
​        无论最高符号位是1还是0,左边始终补0

​    左移的特点:           <<:将左边的数据乘以2的移动次幂
​                
​    右移的特点:           >>:将左边的数据除以2的移动次幂

11. 三元(三目)运算符

 int temp = (x > y )? x: y ;
     int result = (temp > z)? temp : z ;

 或者

    int max2 = (x>y)?((x>z)?x:z):((y>z)?y:z) ;

三. 语句

1. 键盘录入

使用步骤

(1). 导包: 在java语言中:只要不是java.lang包下的类都需要导入!
位置:class上面  
 import java.util.Scanner;
    

(2). 固定格式: 创建键盘录入对象(文本扫描器对象)
Scanner 对象名 = new Scanner(System.in) ;
    
(3). 开始录入数据  :使用int类型举例
int 变量名 =  对象名.nextInt(); 
import java.util.Scanner;
class LiXin6{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个值");
int a = sc.nextInt();
System.out.println("请输入第二个值");
int b = sc.nextInt();
System.out.println("请输入第三个值");
int c = sc.nextInt();
int max2 = (a>b)?((a>c)?a:c):((b>c)?b:c);
System.out.println("最大值为:"+max2);		
}
}
      public String nextLine():正式用法:
import java.util.Scanner;
class ScannerDemo2{
public static void main(String[] args){
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入一个字符串数据:") ;
String line = sc.nextLine() ;
System.out.println("您输入的字符串是:"+line) ; //"helloworld"
    }
}

如果同时录入两个int类型,
同时录入两个String类型
或者 先录入String,在录入int
先录入int,在录入String:哪一个会有问题?   

(4). 键盘录入的细节:
           如果先录入int,再录入String会出现,会漏掉第二个数据String
           原因就是 输入回车符号-->才能录入数据 ;回车符号---> (换行)

方案1:在录入字符串之前,新创建一个键盘录入对象

    //先录入int,在录入String字符串
    Scanner sc = new Scanner(System.in) ;
	System.out.println("请输入第一个数据:") ;
	int a = sc.nextInt() ;
	
	//创建一个新的键盘录入
	Scanner sc2 = new Scanner(System.in) ;
	System.out.println("请输入第二个数据:") ;
	String b = sc2.nextLine() ;
方案2:Scanner类提供了这个功能:
		public String next():录入一个字符串 (非正式用法) 
        System.out.println("请输入第二个数据:") ;
        String b = sc.next() ;     

2. if 语句

格式一:
        if(表达式){
            语句;
        }

格式二:

if(表达式){
    语句1;
}else{
    语句2;
}

   if 语句的嵌套: 

if(表达式1){
    if(表达式2){
        语句1;
    }else{
        语句2;
    }
}else{
    if(表达式3){
        语句3;
    }else{
        语句4;
    }
}

if 语句格式三 :

if(表达式1){
    语句1;
}else if(表达式2){
    语句2;
...
...
...
}else{
    语句n;
}

3. switch语句

switch语句格式:
    
switch(表达式){
case 值1: 
语句1;
break ;
case 值2:
语句2;
break ;
 ...
 ...
    default:
            语句n;
            break ;
    }

switch语句使用的注意事项:

(1). case语句后面的值只能是常量,不能是变量(Java是一个强类型语言的:语法结构非常严谨) 

(2). 书写switch语句的时候,case语句必须存在break语句,结束switch语句的! 如果没有书写break语句,会造成"case穿透!"现象

(3). switch语句的结束条件

​       a)遇见break结束

​       b)程序默认执行末尾结束

4. for 语句 (明确循环次数使用)

for的格式:
   for(初始化语句;条件表达式;控制体语句;){
    循环体语句;
   }
   
for 语句的嵌套:
       for(初始化语句;条件表达式;控制提语句){
           for(初始化语句;条件表达式;控制体语句){             
           }
       }

5. while 语句 (不明确循环次数使用)

while语句的格式:
     初始化语句;
     while(条件表达式);
     循环体语句;
     控制体语句;
使用的场景不同

6. 死循环 break可跳出死循环

Kxxxxxxxxxx 死循环的格式有两种:          1. for(;;){             循环体语句;                    }          2. while(true){             循环体语句;                    }

7. do while 循环语句

do while循环语句的格式:
     do{
         循环体语句;
         控制体语句;
       }
       while(条件表达式);

8. for while 和 do while的区别

1.格式的不同
2.for循环节省内存空间:
       for循环结束,变量随着被释放掉,节省内存空间;(不能访问这个变量了.)
       while循环结束,依然可以访问这个变量,比较消耗内存空间...
3.dowhile:优先循环体语句,即使条件不成立,循环体至少执行一次
    开发中:
         优先for,其次while,再次do-while

9. 跳转控制语句有三个关键字 :

break: 结束中断,结束循环(不能单独使用)switch和循环中使用
continue: 继续, 在循环中使用 ,结束当前循环,立即进入下一次循环
return:很少单独使用,结合有具体返回值类型的方法使用!     结束方法的;

看程序:写结果

   for(int i = 1; i <= 10; i++) { //i=1,i=2,i=3,i=4,i=5,i=6....i=9
          if (i % 3 == 0) {
              //在此处填写代码      
          }
          System.out.println("java基础班");

		  //1)2),3),4)
      }
      在控制台输出2次“java基础班”         break;结束中断
      在控制台输出7次“java基础班”         continue:结束当前循环,立即进入下一次循环
      在控制台输出13次“java基础班”        System.out.println("java基础班"); 

四. 方法

1. 方法:就是使用{}代码块包起来,并且起一个名字(见名知意)

Java中定义方法的格式:
(1).有具体返回值类型的方法的定义
	固定格式
		 public static 返回值类型 方法名(小驼峰命名法)(参数类型1 变量名1,参数类型2 变量名2....){
				                                     int a,int b,intc 
			    ...
				return 结果;
			 
		 }

		 定义两个数据之和的功能时候,
		两个明确
			1)明确返回值类型:int
			2)明确参数类型以及参数个数
				int类型 2个参数
public static int sum(int a,int b){//形式参数
		int result = a + b;//30+20
		return result ;
            }
}: class Text {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入第一个值");
        int a = sc.nextInt();
        System.out.println("请输入第二个值");
        int b = sc.nextInt();
        System.out.println("请输入第三个值");
        int c = sc.nextInt();
        int max = sum(a, b, c);
        System.out.println(max);
    }

    public static int sum(int a, int b, int c) {
        int max = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
        return max;
    }
}

2. 方法使用中的注意事项

(1). 方法和方法是平级关系,不能进行嵌套:    在一个方法中定义另一个方法不允许
			
(2). 在Java中,定义方法的时候形式参数必须携带数据类型! (Java是一个强类型语言)					
	 
(3). 调用方法的时候,传递的实际参数不需要在携带数据类型了 
        
(4). 定义方法的时候: 有{括号的地方不能有分号;     

没有具体返回值的类型的方法的定义:
    没有具体返回值类型的方法调用
    1)单独调用: 只能单独调用
    2)输出调用:
    3)赋值调用:
                 
    //void v = printStar() ; //FunctionDemo.java:28: 错误: 非法的表达式开始
    //输出调用
    //System.out.println(printStar()) ; 不行

    //单独调用
    //printStar(m,n) ;

3. 方法重载 :

方法重载(overload) :方法名相同,参数列表不同,与返回值无关!
	参数列表不同:
	 1)参数个数不同
	 2)参数类型不同

五. 数组

1. 数组 : 就是存储多个数据的容器,必须保证容器内数据类型的一致.

2.数组的定义格式:

  动态初始化 :
            给定了数组的长度,系统默认对元素进行初始化!
            数据类型 数组名称[] = new 数据类型[数组长度];
            数组类型 []数组名称 = new 数据类型[数组长度];
                 例:         int[] arr ;定义一个int类型的数组arr
		                     int[] arr = new int[3] ;
		                     int arr[];定义了一个int类型的arr数组
		                     int arr[] = new int[3] ;
             length : 获取数组长度.
  静态初始化 :
            我们给定的具体的元素,数组长度由系统确定
            数据类型 数组名称[] = new 数据类型{元素 1, 元素 2, ....};
            数据类型  []数组名称 = new 数据类型{元素 1, 元素 2,....};
            可简写为 : 数据类型 数组名称[] = {元素 1, 元素 2,.... };
                      数据类型 []数组名称 = {元素 1, 元素 2,....};

3. 遍历

printArray2(arr) ; //调用方法
public static void printArray2(int[] arr){
System.out.print("[") ;
//遍历数组
for(int x = 0 ; x < arr.length ; x ++){
	//判断:如果当前x :取到最大索引值 arr.length-1
	if(x==arr.length-1){
		System.out.println(arr[x]+"]") ;
	}else{
		//不是最后一个索引值,中间的元素 arr[x]+", " 不换行
		System.out.print(arr[x]+", ") ;
	}
}
}
//  栈:存储都是局部变量(在方法定义中或者方法声明上)
//  堆:new出来的东西,创建对象 (里面存储:"成员变量")
//  方法区:有哪些方法--分别存储在哪个类中---xxx.class()

4. 数组的基本应用 :

求最值问题:
    class Text {
    public static void main(String[]args) {
        int[] arr = {69,13,56,87,24} ;
        //调用方法
        int result = getMax(arr);
        System.out.println("数组中的最大值是:" + result);
    }
        public static int getMax(int[] arr){
            //假设思想:
            int max = arr[0] ;
            for(int x = 1 ; x < arr.length ; x ++){
                //判断
                if(arr[x] > max){
                    max = arr[x] ;
                }
            }
            return max ;
        }
    }

5. 冒泡排序:

 //冒泡:两两比较,较大的值往后放,第一次比较完毕,最大值出现在最大索引处;总共比较的次数:数组长度-1次
class Text {
public static void main(String[] args){
    int arr[] = {12,24,6,35,21};
    for (int x = 0;x < arr.length-1;x++){
        for (int y = 0;y < arr.length-1-x;y++){
            if (arr[y] > arr[y+1]){
                int a = arr[y];
                arr[y] = arr[y+1];
                arr[y+1] = a;
            }
        }
    }
    sum (arr);
}
public static void sum(int arr[]){
    System.out.print("[");
    for (int x = 0; x < arr.length;x++){
        if (x == arr.length-1){
            System.out.print(arr[x]+"]");
        }else{
            System.out.print(arr[x]+",");
        }
    }
}
}

6. 方法的形式参数问题 :

​ 形式参数的改变不能影响实际参数

7. 类与对象的关系 :

 类 : 能够描述现实世界真实事物的一组属性和行为的集合!
 事物 : 现实真是存在的事物;
                 
 创建对象 : 格式:类名 对象名 = new 类名();	
            
 面向对象 : 
         面向对象的思想特点:
	        1)更符号我们生活中是思想行为习惯
			2)让复杂的事情简单化
			3)我们从执行者变成了指挥者   
 三大特点 : 封装,继承,多态

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

1)在程序中的书写位置不同
	局部变量:
		   方法定义中或者方法声明上
	成员变量:
		   在类中,成员方法外定义的变量	
2)在内存中	
	局部变量:
			在栈内存中
	成员变量:
			在堆内存中		
3)生命周期不同
	局部变量:
			随着方法调用而存在,随着方法调用完毕而消失!
	成员变量:
			随着对象的创建而存在,随着对象创建完毕之后,不会立即消失,
							需要等待GC(垃圾回收器空闲时候回收掉!)
									GC算法----->标记算法
												标记---清除												
4)初始化不同
	局部变量:
			可以先定义,但是必须在使用之前必须赋值,否则:可能尚未初始化变量			
	成员变量:
			可以不初始化,它存在系统默认初始化!(根据类型判定)
                
                
    如果一个方法的形式参数是引用类型  是具体类,那么调用该方法时,实际参数如何传递  
     
     
 //学生类
class Student{
	//有一个成员方法:学习的方法
	public void study(){
		System.out.println("Good Good Study ,Day Day Up!!") ;
	}
}
//定义一个StudentDemo类
class StudentDemo{
	//有一个method成员方法
	public void method(Student s){ //方法的形式参数是Student类型
										//调用method 方法的时候:实际参数需要传递的是当前类的具体对象
										//Student s = new Student();
		s.study() ;					//对象名.方法() ;		//stu.study() ;
	}
}
//测试类
class StudentTest{
    public static void main(String[] args){
	//在测试类中访问StudentDemo类中的method方法?
	//创建StudentDemo类对象
	StudentDemo sd = new StudentDemo() ;
	//sd.method(s) ;//找不到符号
	
	//先去创建学生对象
	Student stu = new Student() ;
	sd.method(stu) ;
    }
}

9. 匿名对象

没有名字的对象
        格式:
		    new 类名() ;

匿名对象有一个特点:可以作为参数进行传递
			        在开发中,匿名对象使用一次即可! 
			        (因为没有栈内存变量指向堆内存地址,直接是在堆内存开辟空间,使用完毕,立即被回收!)
    class NoNameObjectDemo{
    public static void main(String[] args){
	//之前的写法
	//访问StudentDemo类中的method 方法
	//创建StudentDemo类对象
	StudentDemo sd = new StudentDemo() ;
	
	//创建一个具体的学生对象
	Student s = new Student() ;
	sd.method(s) ;
	
	System.out.println("------------------------------") ;
	//方式2
	StudentDemo sd2 = new StudentDemo() ;
	sd2.method(new Student()) ;
	System.out.println("------------------------------") ;
	
	//链式编程
	//一步走
	new StudentDemo().method(new Student()) ;
}
}

10. 封装

​ 目的 : 保证数据的安全性

11. private关键字的特点

​ 1)可以修饰成员变量,也可以修饰成员方法,但是都只能在本类访问,外界类不能够访问
​ 2)这些被私有修饰的成员变量,或者成员方法,可以间接通过公共方法来访问!

12. this

 this:解决局部变量隐藏了成员变量
 格式 : this.成员变量名  = 局部变量; 
 this:就是代表当前类的对象的地址值引用!
        this.变量名 :访问的本类的成员变量
        this.方法名():访问的是本类的成员方法
        this() ; 访问本类无参构造方法
        this(String xx):访问本类的有参构造方法

13. 构造方法

 1)构造方法名和类名一致
 2)没有具体的返回值类型
 3)连void都没有
 构造方法的目的:为了给类的成员的一些数据进行初始化	
                 
        无参构造方法 :
        
                 private String brand ;
	             private int price ;//价格
	             private String color ;
                 public Phone(){
	             System.out.println("这是phone类的无参构造方法...") ;
                 }
                 ....
                 ....
                 Phone p = new Phone();//
		         //setXXX()赋值
		         p.setBrand("锤子手机") ;
		         p.setPrice(1299) ;
		         p.setColor("黑色") ;
		         System.out.println("品牌:"+p.getBrand()+",价格:"+p.getPrice()+",颜色:"+p.getColor()) ;
		         System.out.println(p) ;
        有参构造方法 :
        
                 public Student(String name){
	             //this.name = name ;
	             System.out.println("这是Student类带String类型的有参构造方法...") ;
                 }
                 ....     (set xxx,get xxx)
                 ....
                 Phone p2 = new Phone("锤子手机",1299,"黑色") ; 
		         System.out.println("品牌:"+p2.getBrand()+",价格:"+p2.getPrice()+",颜色:"+p2.getColor()) ;
                }
一个类的成员:
			1)成员变量
			2)成员方法
			3)构造方法

14. 静态static关键字的特点:

  1)随着类的加载而加载
  2)优先于对象存在:  它不能this共存   (this:代表当期类对象的地址值引用)
               对象还没有new的时候,当前被static修饰的成员就已经内存了

  3)被静态修饰的 可以被多个对象共享:有共享共用的意思

  4)被静态修饰的变量,方法----->静态变量或者静态方法
           我们所说的成员变量和成员方法:都指的是非静态
           静态的成员的访问方式:类名.变量
                                类名.方法名()
关于static关键字的使用注意事项:

   1)非静态的方法既可以访问静态变量,也可以访问非静态的变量
                既可以调用静态方法,也可以调用非静态方法

   2)静态的方法:只能访问静态变量,
               只能调用静态方法
               简单记:静态只能访问静态

15. 代码块

 在java中用{}包起来的内容,称为代码块.
 分类 :
      局部代码块 : 在方法定义中使用,作用:限定局部变量的生命周期.
      构造代码块 : 在类的成员位置(类中,方法外),使用使用{}包裹起来 
                  作用:给类中的一些成员进行数据初始化                
                  特点:每次在执行构造方法之前,如果存在构造代码块,先执行构造代码块中的内容!
      静态代码块 : 在类的成员位置,直接使用 static{}.    静态代码块就加载一次!
                  作用:也可以通过static代码块,对一些操作(后期IO流创建文件/JDBC)
                  特点:随着类的加载而加载,优先于对象存在!
      //     优先级:
      //     静态代码块(只执行一次) > 构造代码块 > 构造方法

16. 继承

 将多个类的共性内容抽取到一个独立的类中,然后这多个类和独立的这个类产生一种关系 : 继承关系
      关键字 : extends
      书写格式 :class Fu{}
               class Zi extends Fu{}
      继承的好处:
              1)提高代码的维护性
              2)提高代码的复用性
              3)让类和类之间产生的关系,是"多态的前提条件"
      继承的特点 :
              1)类与类之间的关系,继承关系,只支持单继承
              2)不支持多继承,但是可以支持多层继承
      继承中使用的注意事项 :
              1)子类继承父类 :可以继承父类的非私有的成员,私有的成员外界不能访问的,只能在本类中访问,                             但是可以通过公共方法间接访问.
              2)构造方法是不能被继承的,但是子类可以间接通过 super 关键字访问父类的构造方法.
一个类的组成 :
           成员变量
           构造方法
           成员方法

 继承中,每一个成员变量的关系问题

 成员变量 :
         a)子类继承父类,如果子类中的成员变量名称和父类的成员变量名称不一致,分别访问即可!
         b)子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致:如何访问呢? (重点)
            1)首先在子类的局部位置找,是否存在局部变量名称,如果有,就使用
            2)如果没有,就在子类的成员位置找,是否存在这个变量,如果存在,就使用
            3)如果在子类的成员位置中没有找到,直接在父类的成员位置中找,如果有,就是使用!
            4)如果父类的成员位置都没有,就没有这个变量,报错!
                  // 遵循一个原则:就近原则!
继承中构造方法的访问 :

         a)子类继承父类,子类的所有的构造方法都会默认的访问父类的无参方法.
           子类的所有构造方法的第一句话:默认隐藏了super() ;  
            因为子类中肯能会使用到父类的数据,所以在继承关系中,
            得先让父类初始化---->构造方法  : 分层初始化!(先父类无参构造方法,在执行子类的构造方法)

         super:代表的父类对象的空间表示(父类对象的地址值引用!)
         b)如果父类中的无参构造方法没有,子类会怎么样?
           子类的所有的构造都会报错! (因为子类所有构造方法默认父类的无参构造方法!)
         如何解决呢?
              方式1:手动给出父类的无参构造方法(推荐)
              方式2:在子类的构造方法中的第一句话:通过super(xxx),间接的访问父类的有参构造方法
              方式3:只要子类的所有构造方法中一个能够让父类初始化即可!
               在子类的有参构造方法中:this():---->访问本类的无参构造方法,然后再子类的无参构造方法中
               间接访问父类的有参构造方法super(xxx) ;

   如何正确使用继承关系(extends)
   如果一个A类是B类的一种,或者B类是A类的一种,这个时候就可以使用继承关系
           继承关系:现实世界事物中本质体现的是一种 "is a"的关系

17. 总结:this和super 的区别

 this:代表的当前类对象的地址值引用
       super:代表的父类对象的地址值引用(代表父类的空间标识)

 访问成员变量
       this.变量名; 访问的本类中的成员变量
       super.变量名; 访问的是父类的成员变量

 访问构造方法:
       this() ; 访问本类的无参构造方法
       super() ;访问的父类的无参构造方法

       this(xxx);访问的本类的有参构造方法
       super(xxx);访问的父类的有参构造方法
 成员方法:
       this.方法名();访问的是本类的成员方法
       super.方法名() ;访问的是父类的成员方法

18.方法重载,方法重写

//如果子类出现了和父类一模一样的方法声明,叫做方法重写!(Override) —方法复写(覆盖)
//方法重写和方法重载的区别?

  方法重载:Overload   
  在一个类中,提供n多个功能,这些功能,方法名相同,参数列表不同,与返回值无关(目的:提高某个功能的扩展性)
           参数列表不同:
                      1)类型不同
                      2)个数不同
                      3)考虑参数类型的顺序
                        public static void open(int a,double d){}
                        public static void open(double a,int b){}
                   构造方法也可以重载!
   重载的目的:为了提高功能的扩展性:同一个方法可以接收很多类型的参数

  方法重写:Override
  在继承关系中,子类出现了父类一模一样的方法声明,重写的目的:子类有自己的功能,需要将父类的该功能覆盖掉!
  重写的目的:为了沿用父类的功能,并且还需要使用子类的功能(具体的子类才具备具体的动作...)
                           举例:
                                 动物:
                                        都具备吃和睡的功能
                                         猫和狗都继承自动物类,他们吃的不一样的
                                         猫和狗就需要讲吃和睡的功能覆盖掉...
                                               猫具体吃鱼
                                               狗具体吃肉

19.关键子 : final

final(状态修饰符):最终的,无法更改的
    关于final关键字的特点:
       1)可以修饰类,该类不能被继承!
       2)可以修饰符成员方法,成员方法不能重写!  (根据具体的题意要求!)
       3)可以修饰的变量,这个变量此时是一个常量! (自定义常量)

final修饰基本数据类型和引用类型的区别?
          final修饰基本数据类型: 基本数据类型的对应的数据值不能在被赋值了,只能赋值一次!
          final修饰引用类型:引用数据类型对应的地址值不能被改变
               final Student s = new Student() ;//修饰实例变量s,s的堆内存地址值永远是固定值!
                             s = new Student() ;//重新开辟空间(报错)

六.多态

1.多态 : 一个事物在不同时刻不同形态.

 多态的前提条件:
           1)必须存在继承关系 (extends)
           2)必须存在方法重写
                   子类需要覆盖父类的功能
                Animal
                    eat():"动物都需要吃饭..."
                Cat
                    eat() "猫吃鱼"
                Dog
                    eat() "狗吃骨头"

          3)必须有父类引用指向子类对象
               class Fu{}
               class Zi extends Fu{
                   //存在重写
               }

               格式: Fu fu = new Zi() ;

2. 多态成员的访问特点

 Fu f = new Zi() ;
     成员变量:编译看左(看Fu类是否存在变量,存在,编译不会报错!)
             运行看左(使用Fu类的东西)

     成员方法:(一般没有明确是静态方法的都是----->非静态)
            编译看左(看Fu类是否存在这个方法,存在,编译不会报错!)
            运行看右(存在方法重写,所以最终子类的功能将父类的该功能进行覆盖!)

     静态的方法:
             编译看左看Fu类是否存在这个静态方法,存在,编译不会报错!),
             运行看左(静态方法:子类出现了父类一模一样的静态方法,算不上重写,跟类相关的-->类成员)                       
             静态功能推荐的方式:类名.访问


     构造方法:
             即使多态的情况进行测试,多态的前提条件---->继承关系
             当前执行子类的构造方法之前,需要让父类的先进行初始化,然后子类进行初始化(分层初始化!)

3. 多态的好处

1)提高代码的复用性:由继承保证

2)提高了代码的扩展性:由多态保证 (重点)
            Fu fu = new Zi() ; 父类引用可以指向子类对象     

4. 多态的弊端:

不能访问子类的特有功能   (Fu f = new Zi())
                       f.方法名() ;报错了. 父类中没有子类特有功能!
如何解决多态的弊端?

      方案1: (不推荐)
             具体的子类创建具体的子类对象  Zi z = new Zi() ;
             z.成员方法名() ;

             本身Fu f = new Zi() ;已经在堆内存中开辟空间了
              Zi z = new Zi() ;在堆内存中又开辟空间,从内存角度考虑,这种比较消耗内存空间,不太好!

      方案2:(推荐使用:"向下转型")
            多态的第三个前提条件:父类 引用指向子类对象      :"向上转型 "Fu f = new Zi() ;
            能不能将父类的引用转换成子类的引用?   好处:不需要在堆内存开辟空间
            可以------>"向下转型"
                Zi z =   (Zi)f ;  还原成子类型

           强转类型转换: 目标类型 变量名 =(目标类型)初始化值;

                  基本类型 :   int num =  65 ;
                     //num--->char类型
                  char ch  = (char)num ; ====>'A'

5. 多态的向上转型和向下转型

多态的向上转型:多态的第三个前提条件--->父类引用指向子类对象	
		格式:Fu fu = new Zi() ;
		
    多态的弊端:不能访问子类的特有功能
    可以使用向下转型:
         将父类的强转强转转换为子类引用
          Zi zi = (Zi)fu;


多态的方式:使用向下转型时,可能出现异常?
           要使用向下转型,前提必须有父类引用指向子类对象 Fu f = new Zi() ;

           遵循向下转型的格式:
                       Zi z = (Zi)f;     必须心里清楚堆内存存储的类型....

  向下转型使用不当,就出现java.lang.ClassCastException:类转换异常: (属于运行时期异常)
               当前堆内存中的实例不是该类型时,就会出现问题!             

6. 抽象类

什么是抽象类----->现实世界事物中,某个事物是比较概括性(人/水果/动物),描述为抽象事物,
  只有具体的工人/苹果/猫或者狗,才具备具体的功能;
  将某个事物中的一些功能仅仅给出声明即可,没有方法体----->抽象方法---->此时这个类必须为抽象类!

           举例:
                   动物都需要吃和睡
                   只要看到具体的动物类:猫类/狗类,才具备吃和睡的功能
                   将动物类中的吃和睡给出一个声明:加入一个关键字 abstract:抽象方法
                   动物类----->抽象类


     抽象的关键字:Java语言 :abstract关键字 (抽象的含义)

     抽象方法的格式;
       权限修饰符(一般情况都是public) abstract 返回值类型  方法名(形式参数列表) ;

     抽象类的格式:
     abstract  class 类名{}

7. 抽象类的特点

1)有抽象方法的类一定是抽象类
2)抽象类中不一定只有抽象方法 ,还可以非抽象方法(有方法体)
3)抽象类不能实例化---->意思:不能创建对象
               如何实例化呢:通过具体的子类进行实例化(进行对象的创建), 抽象类多态  Fu fu = new Zi() ;Fu类型 抽象类型
4)抽象类的子类有两种情况:
      a)目前来说:如果抽象类的子类都是抽象类---毫无意义  因为子类也不能new ,除非再有具体的子类
      b)抽象类的子类具体类---才能new     :抽象多态的形式  Fu fu = new Zi() ;

抽象类的核心宗旨:就是强制子类必须完成的事情(要将父类中的所有的抽象方法必须重写,否则报错!)
     
抽象类成员特点:
       成员变量
           既可以定义变量,也可以常量:被final修饰
       成员方法
           既可以定义为抽象方法,也可以定义为非抽象方法
           如果定义为抽象方法:关键字abstract(显示给出)
       构造方法
           存在无参构造/有参构造方法---->目的:分层初始化
               
一个类中没有抽象方法,那么将这个类定义为抽象类的意义何在?
       意义:为了不让它直接实例化!
       如何实例化:
               情况1)直接就有具体的子类
               情况2)间接的有具体的子类                 

8.接口

接口---->它的本质就是体现一个现实世界事物所具有的的额外的扩展功能!
         定义格式:    interface  接口名{}  ------>接口名遵循"标识符规则"---->大驼峰命名法

接口中的方法:不能有方法体,隐藏public abstract关键字,只能是抽象方法,不能有方法体

9. 接口的特点

   1)不能实例化(不能创建对象)
   2)如何实例化
           接口实例化: 通过接口的子实现类(一定是具体类)进行实例化----接口多态(使用时最多的!)

           子实现类和接口的关系: implements 实现关系


           接口的子实现类如果是抽象类----->肯定要存在抽象类的具体的子类,否则都不能实例化!

接口的子实现类的命名规则:
       开发中--->在接口名的后面+Impl:子实现类
                       interface Inter{}

                       class InterImpl  implements Inter{

                       }
接口的成员特点:
       1)接口中的成员方法:只能是抽象方法,默认的修饰符:public abstract(可以省略不写)
       2)接口没有构造方法
       3)接口的成员变量只能是常量:
                       存在默认修饰符:public static final (可以省略不写)
                           
类与类之间的关系:  extends 继承关系
                        只支持单继承,不支持多继承,但是可以多层继承

类和接口的关系:   implements关系:实现关系
                         一个类继承另一个类的同时,可以实现多个接口,中间逗号给隔开

接口与接口之间:   extends:继承关系
                       不仅支持单继承,也可以多继承,中间使用逗号隔开
    

10.形式参数问题的研究:引用类型

如果方法的形式参数是类 ,调用方法的时候,如何传递实际参数?
          具体类,调用该方法,实际参数需要传递当前具体类的对象
          抽象类,调用该方法实际参数需要传递的抽象类的子类对象 (抽象类多态)
          接口  调用该方式,实际参数需要传递的是当前接口的子实现类对象(接口多态)

 如果一个方法的返回值是引用类型,最终方法结束,如何返回?
          具体类  :方法返回的就是当前具体类对象!
          抽象类 :需要返回的是抽象类的子类对象
          接口 :需要返回的是该接口的子实现类对象     

11.关键词 : package

 包的真实含义:
            以后要代码分层...
            将包进行划分

 开发中,写包名的时候(字母都是小写,多级包) :公司域名反写

           开发中:
                   先按照模块划分,在按照功能划分
                           用户模块
                                  注册功能
                                    登录功能
                                    用户激活功能(使用邮件激活技术,手机短信验证,微信二维码)
                                    用户退出
                          商品模块
                          订单模块
                          购物车模块
                          支付模块                   

12.权限修饰符

 默认修饰符
 私有修饰符:private
 受保护的 :protected
 公共的,公开的:public

   修饰的权限从小到:private,默认,protected,public

七. 内部类

1. 内部类

在一个类中可以定义另一个类:

     在类A 中定义了类B,将类B就称为类A的内部类,类A就是外部类!

成员内部类:
       在一个类的成员位置中定义了另一个类

       内部类可以访问外部类的成员,包括私有!
         
外部类如何直接访问内部类的成员方法?
      格式:
          外部类名.内部类名  对象名 = 外部类对象.内部类对象;

成员内部类的修饰符:
        在成员内部类上面---加入private修饰:为了数据的安全性,它的访问---就要外部类的公共访问间接访问...
         
如果当前成员内部类是静态的,  里面的方法无论是静态的还是非静态的,都只能访问外部类的静态成员,包括私有!

  如何直接访问静态成员内部类的成员呢?
       将静态的成员内部类看成是外部类的静态成员访问

       直接访问方式
               外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
               

2. 局部类部类

关于局部内部类,它的书写位置,在外部类的成员方法中的定义的类
 
      局部内部类可以访问外部类的成员变量包括私有!
      在外部类的局部位置,访问内部类的成员方法,创建当前局部内部类对象来访问!

3. 局部内部类访问局部变量的时候,此时局部变量应该注意什么?

(JDK7/JDK8),为什么要加入final关键字呢?

如何此时Java环境是Jdk7,局部内部类访问局部变量时,此时该变量必须显示加入final修饰

目前环境是JDK8环境,做了什么优化?

通过反编译查看

class Outer2$1Inner2{
 
final int val$num;  num已经加入了final修饰

final Outer2 this$0;

public void show(){

System.out.println(val$num);

}

Outer2$1Inner2(){

this.this$0 = this$0;

val$num = I.this;

super();

}

}


原因:

  局部变量的生命周期是随着方法调用而存在,随着方法调用结束而消失

  而当前外部类对象调用method 方法的时候,此时num进入栈内存,在局部位置创建了局部内部类对象

  而局部内部类对象调用它的成员方法访问该变量,方法method方法结束之后,内部类对象不会立即消失,

  它里面的成员方法在访问局部变量,局部变量必须变成常量,常驻内存,否则如果当前变量消失了,局部内部类的成员依然在访问

  就会出现冲突! 所以 jdk7 收到必须加入final修饰,jdk8通过jvm已经做了优化了,无需手动加入final修饰
 

4. 匿名内部类

没有名字的内部类   一般在我们局部位置使用!

格式:
    匿名内部类它是内部类的一种简化格式
    new 类名(可以是抽象类,也可以具体类)或者是接口名(){
        重写功能
     } ;
 
匿名内部类的本质:
             继承了该类或者是实现了该接口的子类对象

关于匿名内部类在开发中的使用:
//       方法的形式参数如果是一个抽象类,那么实际参数可以需要接口的子类对象
              1)将子类定义出来 继承自抽象类
              2)直接使用抽象类的匿名内部类
//       方法的形式参数如果是一个接口,实际需要传递的接口子实现类对象
              方式1:将接口的子实现类定义出来
              方式2;使用接口的匿名内部类
//看程序,写结果
   要求:需要在控制台分别打印30,20,10
 
 考点:
   外部类直接访问非静态的成员内部类的格式
   外部类的成员变量的方法方式,(在成员内部类的成员方法中)
   成员变量,局部变量名称都一样(就近原则)
   外部类和内部类没有继承关系
   class Outer{
    int num = 10 ;

    //成员内部类
    class Inner{
        int num = 20 ;
        public void show(){
            int num = 30;
            //补全代码
            System.out.println(num);
            System.out.println(this.num);//this限定 :this.变量名:当前类的成员变量
           // System.out.println(new Outer().num) ; //方式1:new Outer().num

            System.out.println(Outer.this.num) ; //方式2:外部类的this限定
        }
    }
}
public class OuterTest {
    public static void main(String[] args) {
            Outer.Inner oi = new Outer().new Inner() ;
            oi.show();
    }
}
//        方法的返回值是一个抽象类?
//              需要返回的是当前抽象类的子类对象
//        方法的返回值是接口类型,需要返回的当前接口的子实现类对象 

5. java.lang.Object:是类结构层次的根类(超类—>父类),所有的类都默认继承自Object子类(派生类)

使用JDK提供的API文档学习常用类中的常用功能

API:Application Programming Interface:应用程序接口开发文档

Object功能类的getClass()方法

public final Class getClass():表示正在运行的类  (就是字节码文件对象)

Class----->反射的时候去使用
 
Class类:

       功能:
            public String getName():       获取当前类的全限定名称(包名.类名)

Object类中的getClass()/finalize()/hashCode()以及以后常用类

功能中如果native关键字:本地方法,非java语言底层实现另外一个功能

public int hashCode():(了解)获取对象的一个哈希码值 (本质不是地址值,可以把它理解为地址值)----跟哈希表有关系(HashMap)
一般情况:不同的对象获取的哈希码值是不同的 ,(但是中文字符,可能内容不一样,但是哈希码值不同!)
底层是通过哈希表算出来的.

6. 获取一个类的字节码文件对象有几种方式? 三种

第一种:通过Object类的getClass()--->Class    :正在运行的java类: class  包名.类名
 
第二种:任意Java类型的class属性----获取当前类的字节码文件对象Class

第三种方式:Class里面forName("类的全限定名称(包名.类名)") ; (使用最多)

7. Object的public String toString()

返回对象的字符串表示形式。结果应该是一个简明扼要的表达,容易让人阅读。
建议所有子类覆盖此方法。

描述一个对象:是由很多属性(成员变量组成),应该看到的具体的属性描述
要么手动方式(不推荐)
也可以直接快捷键----重写toString即可

大部分的常用类或者后面的集合都会重写Object类的toString()

8. Object类的equals方法

public boolean equals(Object obj)
判断当前obj对象是否和当前对象想等
  
面试题:
equals和==的区别?
 
==:    连接的基本数据类型: 比较的是数据值否相同

==:    连接的是引用类型: 比较的是地址值是否相同
 
equals方法:如果使用Object默认的:底层用==,默认比较的还是两个对象的地址值是否相同,

          Student s1  = new Student("文章",35) ;
          Student s2  = new Student("文章",35) ;

          s1和s2虽然地址值不同,他们的成员的内容相同,认为他是同一个人,但是如何让s1.equals(s2)true:针对equals来说比较的是           成员信息内容是否相同;

                重写Object的equals方法同时还需要重写hashCode内容相同,还需要比较哈希码值相同
 
      alt+ins--->hashcode+equals方法
      重写之后,就比较的是成员信息的内容是否相同!
     
克隆方法:
   protected Object clone() throws CloneNotSupportedException:创建对象并返回该对象的副本
   这个方法会抛出一个异常,throws:表示的是可能出现异常,针对调用者必须进行处理

   要使用clone方法,当前某个对象所在的类必须实现"标记接口"Cloneable(没有字段(成员变量),也没有成员方法)
   实现这个接口,那么就可以使用Objectclone()方法

9. Scanner

Scanner类:文本扫描器    java.util.Scaner ;

构造方法:
       public Scanner(InputStream source) :创建一个文本扫描器 
       形式参数是一个抽象类--->
       它通过System类里面的public static final InputStream in
          System类中
              public final static InputStream in = null;
              本地方法(非Java语言实现)---> private static native void setIn0(InputStream in);
              底层方法一定会创建系统资源---->读取用户输入的 字符(整数,字符串...)
 
Scanner类提供判断功能:  防止出现输入的类型和结果类型不匹配!

public boolean hasNextXXX():判断下一个录入的是否为指定的XXX类型
XXX nextXXX() 获取功能
 
举例:
      public boolean hasNextInt()
      int nextInt()
      如果先录入int,在录入String---->nextLine()---- 录入的字符串数据被漏掉

解决方案;
   1)直接使用next()---->String
   2)在使用nextLine()之前,在创建Scanner对象即可
统一先用String----->全部接收     ----->后期可以通过Integer的特有功能将整数---->String
前提条件:String---->数字字符串 "1","2","3"

举例:
本身:int
录入5个学生的语文,数学,英语成绩,按照总分从高到底排序(可以TreeSet集合进行排序)
语文成绩,数学成绩,英语成绩---->nextLine()---->String
"98"  "78"     "60"
String---    基本类型的包装类类型Integer--->int

八. String大家族

1. String构造方法

java.lang.String:代表的字符串:
字符串是一个常量,一旦被赋值了,其值(地址值)不能被更改
推荐的使用方式:
            String  变量名 = "xxxx" ;//xxxx代表 的当前String的实例
 
String类常用的功能:
获取功能:
int length():获取字符串长

面试题:
在数组中有没有length方法,String类中有没有length方法,在集合中有没有length方法
数组中没有length方法,length属性

               int[] arr = new int[3] ;
               arr.length;
               String类中有length()
               集合中没有length(),----->size()获取元素数
 
构造方法:

(1). public String(): //空参构造:空字符序列
    例: String s = new String() ;
        System.out.println("s:"+s); //String类重写了Object的toString(),
        System.out.println(s.length());
(2). public String(byte[] bytes)://将一个字节数组构造成一个字符串,使用平台默认的字符集(utf-8:一个中文对应三个字节) 解码
    例: byte[] bytes = {97,98,99,100,101} ;
        String s2 = new String(bytes) ;
        System.out.println(s2);
    编码和解码---保证字符集统一
    编码:将一个能看懂的字符串---->字节                "今天老地方见"  utf-8
    解码:将看不懂的字节---->字符串                           "今天老地方见" gbk
 

(3). public String(byte[] bytes,字符集):使用指定的字符集,将字节数组构造成一个字符串
(4). public String(byte[] bytes,int offset,int length):将指定的部分字节数组转换成字符串
                     参数1:字节数组对象,参数2:指定的角标值  参数3:指定长度
     例: String s3 = new String(bytes,2,2) ;
          System.out.println(s3);
          System.out.println(s3.length());
 
(5). public String(char[] value):将字符数组构造成一字符串
     例: char[] chs = {'我','爱','高','圆','圆'} ;
         String s4 = new String(chs) ;
         System.out.println(s4);
         System.out.println(s4.length());
(6). public String(char[] value,int offset,int count):将部分字符数组转换成字符串
    例:  String s5 = new String(chs,1,4) ;
         System.out.println(s5);
         System.out.println(s5.length());
(7). public String(String original):构造一个字符串,参数为字符串常量
    例:  String s6 = new String("hello") ; //创建字符串对象,常量值:hello
         System.out.println(s6);
         String s7 = "hello" ; //推荐的方式
         System.out.println(s7)

//面试题:
   String s1 = "hello" ;
   String s2 = new String("hello") ;
   在内存中分别创建了几个对象?

   第一个创建了一个对象,直接在常量池创建,开辟常量池空间
   第二个:创建了两个对象,一个堆内存中开辟空间,一个指向常量池(不推荐)
   /**
 * String类型重写了Object的equals方法
 * Object 的equals
 *
 *  public boolean equals(Object obj) {
 *         return (this == obj);   //默认比较的地址值
 *     }
 * class String{
 *  private final char value[];  属性 value 字符数组
 * public boolean equals(Object anObject) {  Object anObject = new String() ;
 *         if (this == anObject) {  //判断当前字符串对象和传递进来S2对比
 *             return true;         //判断地址值相同
 *         }
 *         if (anObject instanceof String) {    //判断传进来的s2是否为String类型的实例
 *             String anotherString = (String)anObject; // 向下转型  String类型
 *             int n = value.length;            //获取了字符数组长度   this.value.length---->  int n = 5
 *             if (n == anotherString.value.length) {  //  if(s1的长度 5 == s2.value.length   5)
 *                 char v1[] = value;                  //char v1[] = this.value;  将s1---->v1字符数组
 *                                                      char v1[] = {'h','e','l','l','o'}
 *                 char v2[] = anotherString.value;     //char v2[] =s2.value; 将s2----->v2字符数组
 *                                                      char v2[]  = {'h','e','l','l','o'}
 *                 int i = 0;               //统计变量
 *                 while (n-- != 0) {        // i=0
 *                     if (v1[i] != v2[i])      // v1[0] != v2[0]  ---->'h'     v1[1] != v2[1]
 *                         return false;
 *                     i++;                 /i=1
 *                 }
 *                 return true;         //true
 *             }
 *         }
 *         return false;
 *     }
 *
 *   }
 */ 

2. String类的常用的转换功能: (重点)

(1). byte[] getBytes() : 将字符串转换成字节数组 (编码)
                         如果方法为空参,使用平台默认的编码集进行编码(utf-8:一个中文对应三个字节):   String str = "中国" ;
             byte[] bytes = str.getBytes();//默认utf-8
             System.out.println(Arrays.toString(bytes));//[-28, -72, -83, -27, -101, -67]
(2). byte[] getBytes(String charset): 使用指定的字符集进行编码           
解码的过程:将看不懂的字节数----->String
(3). String(byte[] bytes):使用默认字符集进行解码
       例:    String strResult = new String(bytes) ;// //使用平台默认解码集进行解码:   utf-8
              System.out.println(strResult);
(4). String(byte[] bytes,指定字符集)编码和解码必须要保证字符集统一 
    字符集:
         gbk :一个中文两个字节(中国中文编码表)     
         gb2312:gbk升级版(含义有一个中文字符:中国的中文编码表)     
         iso-8859-1:拉丁文码表     
         utf-8:任何的浏览器--->都支持 utf-8格式 (后期统一个)     
         unicode:国际编码表     
         JS:日本国际 电脑系统 一个字符集
Arrays     
    静态功能:         
    (5). public static String toString(int/byte/float/double...[] a):将任意类型的数组---->String 
    (6). public char[] toCharArray():   将字符串转换成字符数组
               例:               //定义一个字符串
                           String s2 = "helloworldJavaEE" ;
                           // public char[] toCharArray()
                           char[] chs = s2.toCharArray();
                           //遍历字符数组
                            for(int x = 0 ; x < chs.length;  x ++){
                               System.out.println(chs[x]);
                            }
    (7). public String toString():      返回自己本身---"当前字符串的内容":         //System.out.println(s2.toString());
    (8). public String toUpperCase():   将字符串转换成大写
    (9). public String toLowerCase():   将字符串转换成小写java
               例:        System.out.println(s2.toUpperCase());
                          System.out.println(s2.toLowerCase());

3. String类型的判断功能

public boolean equals(Object anObject)://比较两个字符的内容是否相同 (区分大小写)
public boolean equalsIgnoreCase(String anotherString)://比较两个字符串是否相同(不区分大小写)
public boolean startsWith(String prefix)://判断字符串是否以指定的内容开头
public boolean endsWith(String suffix)://判断字符串是否以指定的内容结尾
需求:在某个时间点(今天下午18:00 将某个目录下的所有的以.java文件结尾删除)
          Java中定时器类:Timer---->定时任务TimerTask(抽象类)
          表示文件或者文件夹的抽象路径形式:File类
          递归删除 (定义方法删除)
 
boolean isEmpty()  判断字符串是否为空 ://若为空,则返回true;否则返回false 
String s = "" ;// 空字符串 ,存在String对象 ""
String s = null ; 空值 (空对象) null:引用类型的默认值
    例:
        String s1 = "helloJavaEE" ;
        String s2 = "hellojavaee" ;
        //比较两个字符的内容是否相同 (区分大小写)
        System.out.println("equals:"+s1.equals(s2));
        //比较两个字符的内容是否相同 (不区分大小写)
        System.out.println("equalsIgnoreCase():"+s1.equalsIgnoreCase(s2));
        /*
         *     public boolean startsWith(String prefix):判断字符串是否以指定的内容开头
         *      public boolean endsWith(String suffix):判断字符串是否以指定的内容结尾
         *      boolean isEmpty()  判断字符串是否为空 :若为空,则返回true;否则返回false
         */
        System.out.println("startsWith():"+s1.startsWith("hel"));
        System.out.println("startsWith():"+s1.startsWith("ak47"));
        System.out.println("endsWith():"+s1.endsWith("EE"));
        s1 = "" ; //length()---->长度0 (空字符序列)
        System.out.println(s1.isEmpty());

4. String类的获取功能:(重点)

(1). int length():   //获取字符串长度
(2). public char charAt(int index);  //获取指定索引处的字符:  String str = "helloworldJavaEE" ;
		         System.out.println("charAt():"+str.charAt(4));
(3). public String concat(String str):  //将指定的字符串和当前字符串进行拼接,获取一个新的字符串:  System.out.println("concat:"+str.concat("R").concat("Go"));
(4). public int indexOf(int ch):   //返回指定字符第一次出现的索引值
(5). public int lastIndexOf(int ch):  //返回值指定字符最后一次出现的索引值:   System.out.println("indexOf():"+str.indexOf("o"));
                  System.out.println("lastIndexOf():"+str.lastIndexOf("o"));
(6). public String[] split(String regex): //拆分功能:通过指定的格式将字符串---拆分字符串数组:   String str2 = "JavaEE-Python-Go-R-C-C#-PHP" ;
		          String[] strArray = str2.split("-");
                  for(int x = 0 ; x < strArray.length ; x ++){
                       System.out.print(strArray[x]+"\t");
                  }
(7). public String substring(int beginIndex) ://从指定位置开始默认截取到末尾角标从0开始

(8). public String substring(int beginIndex,int endIndex)://从指定位置开始,截取到位置结束(包前不包右)
                                                          //只能取到endIndex-1处:    String str = "helloworldJavaEE" ;
                   System.out.println("subString():"+str.substring(5));
                   System.out.println("subString():"+str.substring(5,9))
                   
(9). public static String valueOf(boolean/int/long/float/double/char...Object b)//万能方法,将任意类型转换String                                                                                 //类型
                       

5. 字符串其他功能:

(1). public String replace(char target,char replacement)://替换功将指定的内容使用target字符进行替换 
             例:     String s = "helloworld" ;
                     System.out.println("replace():"+s.replace('l','k'));

(2). public String replaceAll(String regex, String replacement) ://将指定的和参数1正则表达式匹配的字符串 使用                                                                        //replacement进行替换

参数1:
     [0-9]   --->如果字符是数字字符

     参数2: "*"替换掉
     
(3). public String trim()://去除字符串两端的空格
         例:        String s3 = "      hello  " ;
                   System.out.println("s3:"+s3.trim()+"----");

重点:
(4). public int compareTo(String anotherString):按照字典顺序比较,返回值是int.
String s1 = "hello" ;
String s2 = "hel" ;
String s3 = "abc" ;
s1.compareTo(s2); //2
s1.compareTo(s3) ;//7
/*
	String类型---内置一个属性: char[] value
   //1)字符串底层---->字符数组  s1和s2--->转换字符串数组 获取长度 5 和 3
     2)通过Math的min方法(5,3) --->获取最小值 int lim = 3 ;
     3) 创建两个数组对象   char[] c1 = {'h','e','l','l','o'}
                         char[] c2 = {'h','e','l'} ;
     4)判断 定义统计变量 k = 0 
     while(k < lim){
     		if(c1[k] != c2[k]){
     				return 对应的字符值进行相减
     				return 'h' - 'a' = 104 - 97 = 7
     		}
     		
     		k ++ ; //统计变量++
     }
     return  字符串的长度相减(字符数组长度相减)
*/

6. int 和 String 类型之间如何转换

//int---->String
   //integer类型的静态功能toString
   public static String toString(int i)
       
 //String--->int
  //Integer的静态功能
       public static int parseInt(String s)
       
  //String ---->Integer ---->int
       String s = "100" ;
	  Integer i = new Integer(s) ;
      int num = i.intValue() ;

7. StringBuffer 的构造方法以及功能

StringBuffer :字符串缓冲区 ---->类似于String,但是不一样 (可变的字符序列)
线程安全------>线程----(多线程中说)
线程依赖于进程存在!进程,能够被系统资源调用的独立单位
一个进程可以有多个线程,每一个线程----->"执行单元"(任务)
线程安全---->同步的----->执行效率低

举例:
银行类的网站/医疗网站
ATM机取钱---->插卡--->输入密码---->查询余额---->取钱
StringBuilder:StringBuffer具有相互兼容的API,它是线程不安全的类---->不同步----->执行效率高

举例:
论坛网站
博客...
单线程程序中:jvm在进行编译的时候  使用StringBuilder去替换StringBuffer
 
//StringBuffer的构造方法:
public StringBuffer() :  空参构造,创建一个空字符序列的字符串缓冲去  (推荐)
public StringBuffer(int capacity): 构造一个字符串缓冲区对象,指定容量大小
public StringBuffer(String str):  指定字符序列,长度加上初始容量16(总容量)
 
//获取功能:
public int length():获取字符数(长度)
public int capacity():获取字符串缓冲区容量
//StringBuffer常用功能
StringBuffer的反转功能:reverse()
StringBuffer的追加功能: append(xxx)
StringBuffer的删除工能:deleteCharAt(int index)delete(int start,int end)
StringBuffer的截取功能: subString(int bengin,int end)
StringBuffer的截取功能: subString(int bengin)
StringBuffer的插入功能: insert(int offset,String str)

8. StringBuffer,StringBuilder的区别

共同点:
	两个都都是字符串缓冲区,支持可变的字符序列!
不同点:
   StringBuffer:线程安全的类---->同步的(多线程:同步锁:源码几乎所有的方法都是同步方法 synchronized)
   				执行效率低
   StringBuilder:线程不安全的类---->不同步----->执行效率高 
   单线程程序中,只考虑执行效率不考虑安全,所以StringBuilder类用作StringBuffer的简易替换
   多线程环境中,要考虑安全问题只能使用StringBuffer,
   
   线程安全的类:StringBuffer,Vector(List接口的子类)

9. StringBuffer和数组的区别

共同点:都是容器,都可以存储任意类型的元素 ,	可以存储基本类型,也可以存储引用类型
数组---->同一种类型的元素   长度是固定的
如果需求中长度是不断变化的,那么数组用不了,考虑:StringBuffer/集合
	
StringBuffer---->存储不同类型的元素 append(int/char/double/Object/foat...)   长度是可变的

借助StringBuffer的功能:reverse()/append()追加----->转换成String形式体现

10. StringBuffer,StringBuilder和String的区别

String:字符串是一个常量,一旦被赋值,其值不能更改/作为形式参数属于特殊的引用类型,形式参数的改变不会实际参数
StringBuffer:可变的字符序列,线程安全的类----同步的----->执行效率低(线程角度)
StringBuilder:可变的字符序列.和StringBuffer具有相互兼容的api,单线程程序中(只考虑执行效率,不考虑安全问题)会使用StringBuilder替代StringBuffer
		作为方法的形式参数,形参的改变会直接影响实际参数

11. String类的遍历

//将字符串的每一个字符分别输出!    charAt(int index)

	String str = "helloJavaEE" ;
	//循环改进: 利用String类的length():获取字符串长度 + charAt(int index)
        for(int x = 0 ;x < str.length() ; x ++){
            System.out.println(str.charAt(x));//charAt(0)
        }
	    //使用String类的转换功能
        //String---->字符数组toCharArray()--->char[]
        char[] chs = str.toCharArray();
        for(int x = 0 ; x < chs.length ; x ++){
            char ch = chs[x] ;
            System.out.println(ch);
        }

13. String类的字符串反转,判断字符串是否为对称字符串(reverse)

public class StringTest4 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您输入一个字符串:");
        String line = sc.nextLine() ;
        
        //方式2:使用StringBuffer的功能改进
        boolean flag2 = compare2(line) ;
        System.out.println(flag2);   
        
   	private static boolean compare2(String line) {
       /*
        StringBuffer sb = new StringBuffer(line) ;
        String str = sb.reverse().toString();
        return str.equals(line) ;
        */        
        return new StringBuffer(line).reverse().toString().equals(line) ;
    }

14. String类的equals方法表示什么意思

String类底层已经针对Object的equals和hashCode方法进行了重写
hashCode():String对象的哈希码值是否相同,哈希码值相同的不一定内容就相同,所以它需要覆盖equals方法
比较的字符串内容是否相同.
	String s1 = "hello" ;
	String s2 = new String("hello") ;
	s1 ==s2--->  false 
	s1.equals(s2) ---->true

15. StringBuffer和String如何转换

//String--->StringBuffer
String s = "hello" ;
//使用StringBuffer的有参构造方法
StringBuffer sb = new StringBuffer(s)
//或者是StringBuffer的追加功能
StringBuffer sb = new StringBuffer() ;
sb.append(s) ;

//StringBuffer--->String
//String类的构造方法 String(StringBuffer)
StringBuffer buffe = new StringBuffer("world") ;
String str = new String(buffer) ;
//第二种方式:StringBuffer的toString方法

九. Integer

1. 基本类型对应的包装类类型

整数类型                    引用类型(默认值都是null)
  byte                        Byte
  short                       Short
  int                         Integer
  long                        Long
 *
浮点类型
   float                       Float
   double                      Double

字符类型
   char                         Character
布尔类型
  boolean                       Boolean

2. 通过Integer得到int类型的取值范围

public static String toBinaryString(int i)://将整数---->二进制 的字符串
public static String toOctalString(int i)://将整数---->八进制的字符串
public static String toHexString(int i)://将整数---->十六进制数据
public static final int MAX_VALUE:int的最大值
public static final int MIN_VALUE:int的最小值

        System.out.println(Integer.toBinaryString(100)); // 1100100
        System.out.println(Integer.toOctalString(100));  //  144
        System.out.println(Integer.toHexString(100));    //64

        System.out.println(Integer.MIN_VALUE);//-2的31次方
        System.out.println(Integer.MAX_VALUE);//2的31次方-1

3. Integer的构造方法

Integer(int value):可以将int类型保证为Integer类型
Integer(String s) throws NumberForamtException:  抛出一个数字格式化异常

注:当前字符串如果不是能够解析的整数的,就会出现数字格式化异常,s必须为 数字字符串

        String s  = "50" ;
        Integer integer2 = new Integer(s) ;
        System.out.println(integer2);

4.自动拆装箱

基本类型---> 对应的包装类类型   (装箱)
对应的包装类型---->基本类型     (拆箱)
    
方式:int---->Integer---->String               //Integer作为桥梁
	int i = 50 ;
    Integer ii = new Integer(i) ;
    String str2 = ii.toString(); 
    System.out.println(str2);//50
方式:String ---->Integer---->int
	 String s = "100" ;
	 Integer integer = new Integer(s) ;
     int result2 = integer.intValue();
     System.out.println(result2);//100

> Integer的内部缓存区:IntegerCache   
> 								low =-128   high=127
 直接赋值的形式----》执行的底层Integer.valueOf(int i){}
> Integer i = 128 ;   					//new Integer(128)
> Integer i2 =128 ;						//new Integer(128)
> System.out.println(i == i2) ;false

十. Charcater : char类型的包装类类型

1. 构造方法

public Character(char value)

        //创建字符类对象
     //Character character = new Character('a') ;
       Character character = new Character((char)(97)) ;
       System.out.println(character); ----------a

2.主要功能

public static boolean isUpperCase(char ch)://判断当前字符是否大写字母字符
public static boolean isLowerCAse(char ch)://是否为小写字母字符
public static boolean isDigit(char ch)://是否为数字字符

3.例题

  //定义三个统计变量
        int bigCount = 0  ;
        int smallCount = 0 ;
        int numberCount =  0;
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in) ;

        //提示并录入数据
        System.out.println("请您输入一个数据:");
        String line = sc.nextLine() ;

        //转换成字符数组
        char[] chs = line.toCharArray();
        for (int i = 0; i <chs.length ; i++) {
            char ch = chs[i] ;
            
         //直接判断
            if(Character.isDigit(ch)){
                numberCount ++ ;
            }else if(Character.isUpperCase(ch)){
                bigCount ++ ;
            }else if(Character.isLowerCase(ch)){
                smallCount ++;
            }
        }

十一. 日历类

1. Data

public Date()://当前系统时间格式
public Date(long date):参数为 时间毫秒值---->Date对象  (197011...)
    
        //创建日期类对象
        Date date  = new Date() ;
        System.out.println(date);

        long time = 60*60 ;
        Date date2 = new Date(time) ;
        System.out.println(date2);

2. Date和String类型如何转换

//java.util.Date---->String: 格式化操作
//1)创建Date对象
Date date = new Date() ;
//2)创建SimpleDateFormat对象
SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd") ;
//3)格式化的操作
String textDate = sdf.foramt(date) ; //使用textDate:日期文本字符串


//String:日期文本字符串----->java.util.Date :解析操作
//1)日期文本字符串
String source = "2021-7-29" ; //格式
//2)创建SimpleDateFormat对象
SimplDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd") ; //模式必须和String的格式一致,否则解析出错
//3)解析操作
Date date2 = sdf2.parse(source) ; //使用Date

3. 静态功能,返回值是它自己本身 public static Calendar getInstance()

public int get(int field)://根据给定日历字段----获取日历字段的值(系统的日历)
     Calendar calendar = Calendar.getInstance();
 	 int year = calendar.get(Calendar.YEAR) ;
	 int month = calendar.get(Calendar.MONTH) ;
	 int date = calendar.get(Calendar.DATE) ;
public abstract void add(int field,int amount)://给指定的日历字段,添加或者减去时间偏移量
                      参数1:日历字段
                      参数2:偏移量
	 int year = calendar.add(Calendar.YEAR,-3);

十二. Random(伪随机数生成器)

1.构造方法

 public Random():    产生一个随机生成器对象,通过成员方法随机数每次没不一样的(推荐)
 public Random(long seed) :参数为long类型的值(随机数流:种子),每次通过成员方法获取随机数产生的随机数相同的

2. 获取随机数的成员方法

 public int nextInt():获取的值的范围是int类型的取值范围(-231次方到231次方-1)
 public int nextInt(int n):获取的0-n之间的数据 (不包含n)
     产生随机数:
               Math类的random方法
                          public static double random();
 
               Random:也能够去使用
                          无参构造方法  + 成员方法
                          public Random():+ public int nextInt(int n)

3. java.lang.Math :针对数学运算的工具类,提供了很多方法

public static int abs(int  a)://绝对值方法
public static double ceil(double a)://向上取整
public static double floor(double a)://向下取整
public static int max(int a,int b)://获取最大值
public static int min(int a,int b)://获取最小值
public static double pow(double a,double b)://a的b次幂
public static double random():[0.0,1.0)://随机数
public static long round(double a)://四舍五入
public static double sqrt(double a)://开平方根
              Math类中的功能都是静态的,里面构造方法私有了!
      一般情况:工具类中构造方法都是会私有化(自定义的工具类),提供对外静态的公共访问方法
      (Java设计模式:单例模式)
JDK5的静态导入特性,必须方法静态的(导入到方法的级别)
     Math类的功能都是静态的,就可以使用静态导入
     import static 包名.类名.方法名;
     前提不能和其他方法名重名;

4. BigDecimal

小数要进行精确计算-还可以计算的同时保留小数点后的有效位数
Java提供的类: BigDecimal
    构造方法:
           public BigDecimal(String value):数字字符串

    成员方法:
           public BigDecimal add(BigDecimal augend)//加
           public BigDecimal subtract(BigDecimal subtrahend)//减
           public BigDecimal multiply(BigDecimal multiplicand)//乘
           public BigDecimal divide(BigDecimal divisor)//除

           public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)
           参数1:商
           参数2:小数点后保留的有效位数
           参数3:舍入模式 :四舍五入

5. ObjectArrayDemo 对象数组:能够存储对象的数组.

十三. Collection

Collection:集合层次的根接口
   一些集合允许元素重复(List),一些集合不允许元素重复(Set)
   一些集合有序(存储和取出一致)(List),一些集合无序(存储和取出不一致)(Set),
   JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如SetList
Collection
     List:
     最具体的子实现类ArrayList,LinkedList,Vector
 基本功能:
      添加
         boolean add(Object e)://添加元素 E(Element)
      删除:
         void clear() //  暴力删除(将集合的素有元素全部干掉)
         boolean remove(Object o)://从集合中删除指定的元素
         获取集合的元素数 :int size()
         判断功能:boolean isEmpty()://判断集合是否为空,为空元素,则返回true
         boolean contains(Object o)://判断集合中是否包含指定元素,包含则返回true

1. Collection的高级功能

boolean addAll(Collection c)://添加一个集合中的所有元素
boolean containsAll(Collection c)://包含一个集合中的所有元素
boolean removeAll(Collection c)://删除集合中的所有元素, (删除一个算删除,还是删除所有)
boolean retainAll(Collection c)://A集合对B集合求交集, boolean的返回值是什么意思,交集的元素是保存在A中还是B//Collection最基本的遍历功能,不属于集合的专有遍历
     Object[] toArray():将集合转换成了对象数组

2. Collection的迭代器:集合的专有遍历方式

Iterator iterator():返回值类型接口类型,需要返回的子实现类对象
    Iterator接口:
 
           boolean hasNext():判断迭代器中是否存在下一个元素
           Object next():  获取下一个可以遍历的元素
           给Collection中存储String类型,遍历出来
               
public class CollectionTest {
    public static void main(String[] args) {
        //创建集合对象
        Collection c = new ArrayList() ; //List接口的子实现类 (重复元素)
        //添加元素
        c.add("hello") ;
        c.add("world") ;
        c.add("javaee") ;
       // System.out.println(c);
        //获取Collection的迭代器Iterator iterator()
        Iterator it = c.iterator();
        //如果现在明确存储了3个元素,以后这些数据可能数据库获取的一个列表集合数据,一般while循环
        while(it.hasNext()){//判断迭代器中有下一个元素
            //才获取
            Object obj = it.next();// Object obj = new String("hello") ...
            //  System.out.println(obj+"----"+obj.length());
            //获取的元素同时,还要获取当前存储元素的长度  ---->String类型   length()
            String str = (String) obj;//向下转型
            System.out.println(str+"----"+str.length());
        }

    }
}    

3.泛型<E/T>

集合类型<引用数据类型> 集合对象名 = new 子实现类<引用数据类型>() ;

泛型的好处:
           1)将运行时期异常提前了编译时期
           2)避免了强制类型转换
           3)提高了程序安全性
    public class GenericDemo {
    public static void main(String[] args) {

        //创建Collection集合对象
        Collection<String> c = new ArrayList<String>() ; //new XXX<数据类型>: jdk7以后泛型推断


        c.add("hello") ;
        c.add("高圆圆") ;
        c.add("你好吗") ;
       // c.add(100) ;

        //获取迭代器Iteratr<E>是集合中存储的泛型是一致的
        Iterator<String> it = c.iterator();
        while(it.hasNext()){
            //获取String字符串的同时,还要获取长度
            String str = it.next();
            System.out.println(str+"---"+str.length());
        }
    }
}

4. Collection的面试题

集合和数组的区别
1)长度区别
       数组:长度固定
       集合:长度可变
 
  2)存储数据类型的区别
       数组:
               可以存储基本数据类型,也可以存储引用数据类型
                  int[] arr = {100,200,50,"hello"} ;不行的
 
        集合:前提条件:集合中加入泛型<>          也是在模拟数组的特点:
               只能存储引用类型  Collection<E> :泛型<引用类型>
  3)存储元素的区别:
              数组:
                       存储的元素必须为同一种数据类型
                               举例:
                                       水杯中加入水
 
              集合:如果没有加入泛型     :就出任意类型的元素(必须引用类型)
 
                               举例:
                                       水杯加入水,可乐,加入威士忌

十四. List

1. List 集合的特点

1.有序(存储元素和取出元素一致)
2.允许元素重复
具备Collection相关的功能
         Object [] toArray()
         Iterator iterator()

2.特有功能

void add(int index,Object element):在指定的索引处插 入元素
     Object get(int index):获取指定位置处的元素    + int size():一种新的集合遍历方式
     Object remove(int index):删除指定位置处的元素
     Object set(int index,E element):修改指定位置处的元素(替换)
 
     ListIterator<E> listIterator():列表迭代器
                   ListIterator接口:
                           void add(E e)有添加
                           remove():有删除

3. List集合的遍历方式

Object[] toArray()
  Iterator iterator()
  Object get(int index):获取指定位置处的元素    + int size():一种新的集合遍历方式
 
  ListIterator<E> listIterator():列表迭代器  :List集合专有遍历方式
    
public class ListTest {
    public static void main(String[] args) {

        //创建List集合对象
        List<String> list = new ArrayList<>() ;

        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("android");

        //size()+get(int index)集合
        for(int x = 0 ; x < list.size() ; x ++){
            String s = list.get(x);
            System.out.println(s+"---"+s.length());
        }

        System.out.println("-----------------------------------------------");
        //List集合存储Student对象并进行遍历(学生:姓名,年龄)
        List<Student> stuList = new ArrayList<>() ;//JDK7以后 泛型推断:自动的和前面的泛型类型一致!

        //创建3个学生
        Student s1 = new Student("张佳宁",31) ;
        Student s2 = new Student("迪丽热巴",29) ;
        Student s3 = new Student("张俊杰",20) ;

        //添加到列表中
        stuList.add(s1) ;
        stuList.add(s2) ;
        stuList.add(s3) ;

        //遍历
        //方式1:Object[] toArray()
        Object[] objs = stuList.toArray();
        for(int x = 0 ; x < objs.length ; x ++){
            Student s = (Student) objs[x];
            System.out.println(s.getName()+"----"+s.getAge());
        }


        System.out.println("--------------------------------------");

        //Collection的迭代器
        Iterator<Student> it = stuList.iterator();
        while(it.hasNext()){
            Student s = it.next() ;
            System.out.println(s.getName()+"---"+s.getAge());
           // System.out.println((it.next().getName()+"---"+(it.next().getAge())));
            // next()只能使用一次,不能多次使用 //错误的用法
        }
        System.out.println("-------------------------------------");

        //方式3:size()+get(int index)
        for(int x = 0 ; x < stuList.size() ; x ++){

            Student s = stuList.get(x);
            System.out.println(s.getName()+"----"+s.getAge());
        }


        System.out.println("-----------------------------------------");

        //正向遍历:ListIterator<E> listIterator():列表迭代器  :List集合专有遍历方式
        ListIterator<Student> lit = stuList.listIterator();
        /**
         * ListIterator extends Iterator{}
         *
         * class ArrayList{
             *  List具体ArrayList子实现类重写了Iterator listiterator(){
             *
             *      return new ListItr(0) ;
             *  }
         *
         *          private class ListItr extends Itr implements Iterator{
         *
         *                      //具备hasNext()
         *                      //next()
         *          }
         *
         *  }
         */
        while(lit.hasNext()){
            Student student = lit.next();
            System.out.println(student.getName()+"---"+student.getAge());
        }

        System.out.println("-----------------------------------------");

        //逆向遍历:前提:必须有正向遍历
        //ListIterator<E> listIterator()
        //ListIterator:特有功能:
        //boolean hasPrevious():是否有上一个元素可以迭代
        //Object previous():获取上一个元素
        while(lit.hasPrevious()){
            Student student = lit.previous();
            System.out.println(student.getName()+"---"+student.getAge());
        }

    }
}

4. LIst如何去重

(1).存储字符串类型
    
方式一:新建空集合思想
//新建一个空的集合List
        List<String> newList = new ArrayList<>() ;
        //遍历以前的集合
        for(String s :list){
            //使用新集合判断,不包含这个元素,说明该元素没有重复,就可以添加
            if(!newList.contains(s)){
                newList.add(s) ;
            }
        }
        //遍历新的集合
        for(String s:newList){
            System.out.println(s);
        }

方式二:利用选择排序的思想去完成
    //利用选择排序的思想完成
        for(int x = 0 ; x < list.size()-1 ; x ++){
            for(int y = x +1 ; y < list.size() ; y++){
                //如果后面的元素和前面的元素相同
                if(list.get(y).equals(list.get(x))){
                    //通过集合remove掉
                    list.remove(y) ; // public Object remove(int index)
                    //角标--
                    y -- ;
                }
            }
        }

        for(String s:list){
            System.out.println(s);
        }

(2). 存储自定义对象
    方式1:新建集合思想
          contains(Object)方法依赖于Object的equals方法,所以集合存储的类型所在的类必须重写equals方法,否则默认使用
    方式2:使用选择排序思想 将List存储的重复的学生对象进行重写!
      
//方式1:创建新的一个新集合
        List<Student> newList = new ArrayList<>() ;
        //遍历以前的集合获取每一个学生对象
        for(Student s:list){
            //如果当前newList不包含这个学生添加到新集合中
            if(!newList.contains(s)){
                newList.add(s) ;
            }
        }

        //遍历新集合
        for(Student student:newList){
            System.out.println(student.getName()+"----"+student.getAge());
        }

5. List的并发修改异常java.util.ConcurrentModificationException

集合在使用迭代器会经常出现的问题:并发修改异常,

当集合的元素正在被迭代器进行遍历,那么集合对象是不能够对元素进行增加或者删除 (一个线程正在遍历,一个线程在修改元素)
解决方案:
     1)要么就是迭代器去遍历集合的元素,迭代器去添加元素 :列表迭代器才具备添加的动作
     2)要么集合遍历,集合添加
public class ListTest2 {
    public static void main(String[] args) {

        //创建List集合对象
        List<String> list = new ArrayList<>() ;

        //给添加元素
        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;

        //使用迭代器遍历
        //Iterator iterator()
      /*  Iterator<String> it = list.iterator();  //"hello","world","javaee"
        while(it.hasNext()){
            String s = it.next() ;//"hello","world","javaee"

            //判断
            if("world".equals(s)){
                list.add("javaEE") ;//集合对象添加的元素,迭代器不知道
            }
        }

        System.out.println(list);*/

      //解决方案1:  1)要么就是迭代器去遍历集合的元素,迭代器去添加元素  :列表迭代器才具备添加的动作
        //ListIterator
        //void add(E e)
        /*ListIterator<String> lit = list.listIterator();
        while(lit.hasNext()){
            //获取
            String s = lit.next();
            //判断是否存在"world"元素
            if("world".equals(s)){
                //列表迭代器添加
                lit.add("javaEE");
            }
        }*/

        //方案2:要么集合遍历,集合添加
        //size()+get(int index)
        for(int x = 0 ; x < list.size(); x ++){
            String s = list.get(x);
            if("world".equals(s)){//将常量放前面,防止出现NullPointerException
                list.add("javaEE");
            }
        }
        System.out.println(list);

    }
}

十五. Vector

1. Vector集合特有功能:

添加
     public void addElement(Object obj):在vector对象的末尾添加元素  ------> 一直使用的add(Object e)
删除
     public boolean removeElement(Object obj):删除元素
获取功能
     public Object elementAt(int index):获取指定位置的元素---->类似于  public Object get(int index)
 
     public Enumeration<E> elements() :Vector集合的专有遍历方式---->类似于   Iterator literator()
                       接口
                           boolean hasMoreElements():判断是否有更多的元素可以迭代
                           Object nextElement() 获取元素

2. Vector集合遍历方式

public Enumeration elements()	Vector集合的专有遍历方式
    
public class VectorDemo {
    public static void main(String[] args) {
        //创建Vector集合对象
        Vector<String> v = new Vector<>() ;
        v.addElement("hello");
        v.addElement("world");
        v.addElement("SpringBoot");
        v.addElement("SpringCloud") ;
        //遍历:特有功能
        Enumeration<String> en = v.elements(); //相当于Iterator
        while(en.hasMoreElements()){
            String s = en.nextElement();
            System.out.println(s+"---"+s.length());
        }
        System.out.println("----------------------------------");
        for(String s: v){
            System.out.println(s+"----"+s.length());
        }

    }
}

十六. 增强for循环

1. 增强for循环

替代集合中迭代器去遍历集合使用的(优先在集合中使用)

格式:
    for(存储的引用数据类型 变量名: 集合/数组对象){
    //集合使用居多,数组一般都是使用普通for
    使用变量名即可
    }
注意事项:
       当前集合对象不能为空 null :foreach语句:增强for它本身就是获取迭代器了,就会出现空指针异常
       
public class ForeachDemo {
    public static void main(String[] args) {

        //数组
        int[] arr = {11,22,33,44,55} ;
        for(int x  = 0 ; x < arr.length ; x ++){
            System.out.println(arr[x]);
        }
        System.out.println("--------------------------------");

        /*
        for(存储的引用数据类型 变量名: 集合/数组对象){
        *            使用变量名即可
                    *      }

         */
        //对于数组来说:使用普通for
       /* for(int a:arr){
            System.out.println(a);
        }*/

       //创建List集合
        List<String> list = new ArrayList<>() ;
        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;

       /* for(String s:list){//替换迭代器使用
            //如果存在world元素,添加一个android元素
            //System.out.println(s);

            if("world".equals(s)){
                list.add("android") ;//出现并发修改异常
            }
           }
           System.out.println(list);
        */

       list = null ;
       if(list!=null){
           for(String s:list){//获取迭代器
               System.out.println(s+"---"+s.length());
           }
       }else{
           System.out.println("当前集合对象为null了");
       }


    }
}

2. 面试题

需求:
    使用增强for遍历List,存储三个学生,遍历后获取学生信息(姓名和年龄)
public class ForeachTest {

    public static void main(String[] args) {

        //创建List
        List<Student> list = new ArrayList<>() ;
        //创建三个学生
        Student s1  = new Student("张佳宁",29) ;
        Student s2  = new Student("邓超",40) ;
        Student s3  = new Student("黄海波",30) ;

        list.add(s1) ;
        list.add(s2) ;
        list.add(s3) ;
        //方式5:增强for循环
        for (Student s: list) {
//           System.out.println(s.getName()+"---"+s.getAge());
            System.out.println(s); //对象名称:直接使用重写后的toString()
        }
    }
}

3. 插入排序

核心思想:使用1角标对应的元素进行和0角标比较
        如果前面元素大,向右移动,确定角标1对应的元素的位置,再次使用2角标对应的元素依次和10都元素比较
        依次这样比较
public class InsertSortTest {

    public static void main(String[] args) {

        //定义一个Integer数组: Integer实现的自然排序:元素能够按照升序默认排序
        Integer[] arr = {34,8,64,51,32,21} ;

        System.out.println("排序前:");
        printArr(arr);

        //定义一个功能
        insertSort(arr) ;
        System.out.println("排序后:");
        printArr(arr);

    }
    //插入排序
    private static void insertSort(Integer[] arr) {

        //定义一个变量j
            int j ; //j记录当前角标的变化
            //定义变量 : p:表示一个比较次数 p=1,2,3,4,5 (每一移动的元素的位置)
            for(int p = 1 ; p < arr.length ; p ++ ){ //比较次数     p=2
                //定义临时变量temp
                Integer temp = arr[p] ;    //temp = 8;          temp = 64
                //开始比较
                for(j = p ; j>0 && temp.compareTo(arr[j-1])<0; j-- ){  // j= 1 ; 1>0&& 8 < 34   j-- : j= 0
                    //j=2 ; 2>0 && 64 < 32
                    //数据移动
                    arr[j] = arr[j-1] ;
                }

                //确定temp的位置:8的位置   64的位置:p=2
                arr[j] = temp ;         // 没有移动

        }

    }

    public static void printArr(Integer[] arr){
        System.out.print("[");
        for(int x = 0 ; x < arr.length ; x ++){
            if(x == arr.length -1){
                System.out.println(arr[x] +"]");
            }else{
                System.out.print(arr[x]+", ");
            }
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值