1.基础篇回顾

1.1运算符与键盘录入

注意两数相除

/*        
算数运算符:
            +
            -
---------------------------------------------------------------------
            *:
            /:整数相除,结果只能得到整数,想得到带有小数的结果,需要有小数参与运算
            %   取模     作用:取余数
                
            问题:这玩意儿有什么用?
            回答:% 目前能够想到的场景,可以进行奇偶的判断
            - 任何一个数%2的结果,不是0,就是1        
*/

给一个数(123)想获得个位,十位,百位,上的数字

/*              个位的计算:
                数值%10
                123除以10(商12,余数是3);
                十位的计算:
                数值/10%10
                123除以10(商12,余数为3);
                商12再模以10(商1,余数为2)
                百位的计算:
                数值/10/10%10
                123/10/10%10(123/10得到12,12/10得到1,1%10得到1) 以此类推
 */

1.1.2计算机中进制的分类


    计算机中进制的分类:
        十进制:默认
        二进制:0b开头
        八进制:0开头
                -今后编写数值,尽量不要以0开头
        十六进制:0x开头
                -今后看到一组数据是0~9,字母a~f组合排列的,要知道这是16进制数据.
    二进制到十进制转换
        公式:  系数*基数的权次幂 累加起来


        系数:就是每一位上的数
        基数:当前进制数
        权:从右往左,依次为  0 1 2 3 4 5 6....

        @8421快速转换法
        二进制中,每一位的1都是代表一个固定的数值
        把每一位的1代表的十进制加起来得到的结果就是它所代表的十进制数.

        1       1       1       1       1       1       1       1
        128     64      32      16      8       4       2       1
 

 原码,反码,补码 以及强转过程的精度损失

        @原码:
            数据的二进制体现形式,一个字体由8个二进制组成
            高位:二进制数据中,最左侧的数据,通过高位代表符号位
                    0代表正数
                    1代表负数
                    其余位,表示数值大小
            弊端:遇到负数运算,就会出现错误(计算机在运算的时候,都是以二进制补码的形式在运算)
        @反码:
        正数的反码与原码相同
        负数的反码是对原码逐位取反,但符号位除外.
        @补码:
        正数的补码与其原码相同
        负数的补码是在其反码的末尾加1
         */
        //          原码:1 0 0 0 1 0 1 0
        //          反码:1 1 1 1 0 1 0 1
        //          +                 1
        //----------------------------------
        //          补码:1 1 1 1 0 1 1 0
        /*
        强转中的精度损失:
        int a=130;
        byte b=(byte)a; //-126

        !整数130:默认为int,int 占用4个字节,也就是4组8个二进制位
        00000000 00000000 00000000 10000010
        !强转到byte:4个字节,强制转换位1个字节,就是砍掉前3组8位
        10000010        (此时为补码(正数的原反补都是一样的)(符号位为1 代表负数))
        !根据运算后的补码,反推原码
         */
        //!!!!!!!   (原码到补码的转换:取反再加1)
        //!!!!!!!   (补码到原码的转换:还是取反再加1)
        //          补码: 1 0 0 0 0 0 1 0
        //       +1:反码: 1 1 1 1 1 1 0 1
        //---------------------------------------
        //     二进制原码: 1 1 1 1 1 1 1 0
        //       8421码:
        //- 64 32 16 8 4 2 1
        //  拼上符号为即是-126
        // 这就是为什么int 130强转为byte后为-126

1.1.3 Scan 键盘录入步骤

Scanner 键盘录入的三个步骤
1.找符咒
    代码:import java.util.Scanner;
    位置:class上面
    含义:能让自己的类ScannerDemo,从代码仓库中,找到Scanner符咒

2.召唤精灵
    代码:Scanner sc=new Scanner(System.in)
    位置:main方法里面
    含义:从符咒里召唤精灵,给精灵取名叫sc

3.指挥精灵干活
    代码:
            int age=sc.nextInt();
            double height=sc.nextDouble();
            boolean flag=sc.nextBoolean();
            String name=sc.next();

1.1.6类型转换 面试

类型转换面试题:下列代码是否存在错误,如果有,请指出说明,并改正.
        byte b1=3;
        byte b2=4;
        byte b3=b1+b2;
错误原因:
        b1和b2是两个byte类型,在运算的时候,会提升为int类型
        提升之后,就是两个int在运算了,运算的结果还是int.
        将int类型的结果,赋值给byte类型的变量,属于大给小,不能直接给.


        byte b1=3;
        byte b2=4;
        byte b3=(byte)(b1+b2);
        System.out.println(b3);
        
   还没结束 请问 byte b=3+4 是否可以通过编译,如果是,请问为什么?
   byte b=3+4; 
   错误答案:
   某同学:这里的3和4是两个字面量,之前说过,所有整数默认都是int类型,所以这里应该是两个int做运算
   运算后的结果还是int,int类型结果给byte类型变量赋值,大的给小的,不能直接给,编译错误.
   正确思路:
   Java存在常量优化机制:在编译的时候(javac)就会得到3和4两个字面量或者说常量进行运算,可以通过编译.
            产生的字节码文件:byte: b=7;(编译时就进行3+4的运算了,到了字节码文件中就会=7)
                                                                               
   前面的 byte b3=b1+b2; b1 b2 是变量 不是 字面量(常量) 所有不可以通过编译

1.1.7 类型转换

(小的会提升成大的)


    类型转换-隐式转换
        介绍:将取值范围小的数据或变量,给取值范围大的变量赋值,可以直接赋值
            -简单记:小的给大的,可以直接给(指的是取值范围)
    取值范围从小到大
        byte-->short->int->long->float->double
            问题:float 占用4个字节,为什么放在了long(8个字节)的后面
            解释:虽然float占用了4个字节,但是[取值范围]要比8个字节的long更大
                -小数的二进制存储形式,要更加节省内存

    运算过程中的隐式转换
        *取值范围小的数据,和取值范围大的数据进行运算,小的会想提升大的之后,再进行运算
        *byte short char 三种数据在运算的时候,都会提升为int,然后再进行运算

      int a=10;
      double b=12.3;
      double c=a+b;

      byte a=10;
      byte b=5;
      int c=a+b;

      int a=1;
      char b='a';
      int c=a+b;
      System.out.println(c); 98
   强制转换介绍
    *把一个取值范围大的数值或变量,赋值给另一个取值范围小的变量,不允许直接赋值,需要加入强转
    注意:强制转换[有可能]会出现精度损失

 1.1.8 基本数据类型

1. 基本数据类型

    整数
        byte    1个字节  -128~127
        short   2个字节
        int     4个字节
        long    8个字节
    小数
        float(单精度)   4个字节
        double(双精度)  8个字节
    字符
        char    2个字节
    布尔
        boolean 1个字节
2个引用数据类型
-----------------------------------------------------
使用思路:
    1.整数类型:
    首选int,如果发现int装不下,将类型换成long,定义long类型变量需要加入L标识

    2.小数类型:
    首选double,非要用float类型,需要加入F标识
    
     /*
        变量的注意事项:
            1.变量名不允许重复定义
            2.一条语句可以定义出多个变量,中间要使用逗号分隔
            3.变量在使用之前,必须完成赋值
            4.TODO:变量的作用域(未完待续)

1.1.8 方法介绍

方法(函数)介绍:一段具有独立功能的代码块,不调用就不执行.

        好处:
            1.可以将原本挤在一起的臃肿代码,按照功能做分类管理.
            2.提高了代码的复用性
        定义格式:
            public static void 方法名(){
                方法体(逻辑代码)
            }
        方法的调用格式:
            方法名();
        注意事项:
            1.方法与方法之间是平级关系,不允许嵌套定义
            2.方法不调用就不会执行
            3.方法的定义顺序,和执行顺序无关,想要梳理执行顺序,就看调用顺序

1.1.9 赋值运算符

   /*
       赋值运算符:
           1.基本运算符
               =:将符号右侧的数据,赋值给左边的变量
               int num=10;
           2.扩展赋值运算符
               +=:将符号左右两边的数据,做加法运算,再将结果赋值给左边.
               -=:将符号左右两边的数据,做减法运算,再将结果赋值给左边.
               *=:将符号左右两边的数据,做乘法运算,再将结果赋值给左边.
               /=:将符号左右两边的数据,做除法运算,再将结果赋值给左边.
               %=:将符号左右两边的数据,做取模运算,再将结果赋值给左边.
               int num =10;
               num +=20;
               System.out.println(num);
----------------------------------------------------------------------------
       细节补充:
               扩展赋值运算符,内部自带强转效果
               short s=1;
               s=s+1;//(会报错)
               s=(short)(s+1);(得改成)
               System.out.println(s);

  public static void main(String[] args) {
        double a=12.3;
        int b=10;

        b+=a;     //22.3
        System.out.print(b);    //22
  }

1.1.10 关系运算符(比较运算符)

        关系运算符(比较运算符)
        >
        >=
        <
        <=
        ==
        !=

1.1.11 逻辑运算符

   逻辑运算符 :

       1. 用于连接boolean类型的表达式, 或者是值
       2. 整合多个条件, 为一段整体的逻辑

   分类:

       &(与) : 并且, 遇false, 则false

               场景: 范围性的判断查找
               举例: 键盘录入一个学生成绩, 判断该成绩是否是90~100之间
               伪代码: 不能运行, 仅供理解
               int score = 95;
               如果(score >= 90 & score <= 100){
               }

       |(或) : 或者, 遇true, 则true
               场景: 多个条件任选其一
               举例: 键盘录入一个学生学号, 学号 3 5 12

               int id = 3;

               如果(id == 3 | id == 5 | id == 12){
               }

       !(非) : 取反
               场景: 对一段逻辑整体做取反操作
               举例: 键盘录入一个学生学号, 学号除了 3 5 12 都要
               如果(  ! (id == 3 | id == 5 | id == 12)  ){
               }
       ^(异或) : 相同为false, 不同为true

1.1.12 短路逻辑运算符

或,与,非

public class OperatorDemo5 {
    /*
    短路逻辑运算符 :

        & : 没有短路效果, 无论左边是true, false, 右边都要继续执行
        && : 具有短路效果, 左边为false, 右边不执行了
                左边为true, 右边要继续执行

        | : 没有短路效果, 无论左边是true, false, 右边都要继续执行
        || : 具有短路效果, 左边为true, 右边不执行了
                左边为false, 右边要继续执行

    ---------------------------------------------------        常用的逻辑运算符:   &&  ||   !
 */
}

    public static void main(String[] args) {

        int x = 3;
        int y = 4;
        // false
        boolean result = ++x > 5 && y-- < 4;

        System.out.println(x);          // 4
        System.out.println(y);          // 3
        System.out.println(result);     // false

    }

 1.1.13 方法重载关系的要求

    方法重载关系的要求
        在同一个类中,定义了多个同名的方法
        但每个方法有不同的参数类型或参数个数,这些同名的方法,就构成了重载关系(方法与方法之间的关系)
    简单记:同一个类中,方法名相同,参数不同的方法
        参数不同:个数不同,类型不同,顺序不同

        注意:识别方法之间是否重载关系,只看方法名和参数,跟返回值(void,int...)无关.
 */

/*
    方法重载(Overload):方法与方法之间的一种关系
        目标1:    能够独立识别除方法与方法之间,是否是正确重载
                    - 在同一个类中,方法名相同,参数不同,与返回值无关
                        -参数不同:1.类型不同    2.个数不同 3.顺序不同
        目标2:    能够理解方法重构带来的好处

                    -不需要记忆过多繁琐的方法名字了

1.1.13方法的补充

定义方法时,要做到两个明确
    明确参数:主要是明确参数的类型和数量
    明确返回值类型

1.2 if 与循环结构

1.1.15 break和continue

1.1.16 control 死循环

            无限循环(死循环)
                1.for(;;){}
                2.while(true){}
                3.do{}while(true);

1.1.17 do while 循环

//特点:无论判断条件是否满足都至少执行一次循环体

        do...while循环格式:
        初始化语句;
        do{
            循环体语句;
            条件控制语句;
         }while(判断条件);
     执行流程:
        1.执行初始化语句
        2.执行循环体语句
        3.执行条件控制语句
        4.执行判断条件,看起返回结果是true,false
                    false:循环结束
                    true:回到第二步继续

    public static void doWhileTest() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("程序员");
        }
        System.out.println("***************************");

        int i = 1;
        do {
            System.out.println("程序员");
            i++;
        }
        while(i <= 5) ;

    }

1.1.18 for 循环

        for 循环语句格式:
        for(初始化语句;判断条件;条件控制语句){
        循环体语句;
        }
      执行流程:
        1.执行初始化语句,在整个循环过程中,只执行一次
        2.执行判断条件,看其返回结果是true,false
                false:循环结束
                true:执行第三步
        3.执行循环体语句
        4.执行条件控制语句
        5.回到2继续...

         for 循环注意事项:
            1.for循环{}中定义的变量,在每一轮循环结束后,都会从内存中释放
            2.for循环()中定义的变量,在整个循环结束后,会从内存中释放
            3.for循环()和{}之间不要写分号

    public static void print() {
        for (int i = 1; i <=10; i++) {
            System.out.println("跑圈");
        }
    }

    public static void forTest2(){
        //快捷键 5.fori+回车
        for (int i = 0; i < 5; i++) {
            //i=0,1,2,3,4(默认i从零开始)

        }
    }

    for循环 : 用于控制循环的那个变量, 在循环结束后, 就会从内存中消失, 循环结束后, 不能继续使用

    while循环 : 用于控制循环的那个变量, 在循环结束后, 不会从内存中消失, 循环结束后, 可以继续使用

1.1.19 while 循环

        while循环格式:

            初始化语句;
            while(判断条件){
                循环体语句;
                条件控制语句;
            }

        执行流程:
            1. 执行初始化语句
            2. 执行判断条件, 看其返回结果是true, false
                    false : 循环结束
                    true : 进入第三步
            3. 执行循环体语句
            4. 执行条件控制语句
            5. 回到2继续

1.1.20 if 语句

1.1.21 switch 语句

        switch语句格式 :

            switch (将要匹配的值) {
                case 值1:
                    语句体1;
                    break;
                case 值2:
                    语句体2;
                    break;
                case 值3:
                    语句体3;
                    break;
                ...
                default:
                    语句体n+1;
                    break;
            }

        执行流程:

            1. 拿着 () 中将要匹配的值, 跟case给出的选项, 逐个进行匹配
                    匹配成功, 执行对应的语句体, 再由break结束掉整个的switch语句

            2. 如果给出的所有case, 都匹配失败了, 将会执行最后的 default, 由break结束掉整个的switch语句

 注意事项:

        switch语句注意事项 :

            1. case 后面的值不允许重复
            2. case 后面的值, 只能是字面量, 不能是变量
            3. switch () 中可以接收的类型

                        1). 基本数据类型: byte short char int
                        2). 引用数据类型: jdk5版本开始可以是枚举, jdk7版本开始可以是String字符串

            4. case穿透现象

 穿透现象:

    public static void switchTest3(){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        int week = sc.nextInt();

        switch(week){
            case 1, 2, 3, 4, 5 -> System.out.println("工作日");
            case 6, 7 -> System.out.println("休息日");
            default -> System.out.println("您的输入有误");
        }
    }
}

sb的编码形式:

public static void switchTest2(){
        int week = 1;

        String num = "1";

        switch (num) {
            case "1" :
                System.out.println("星期一");
                break;
            case "2" :
                System.out.println("星期二");
                break;
            case "3" :
                System.out.println("星期三");
                break;
            default:
                System.out.println("您的输入有误");
                break;
        }
    }

1.1.22 random 随机数

//需求:产生20~80之间的随机数

public class RandomDemo {
    public static void main(String[] args) {
        randomTest();
    }
    /*
        Random 产生随机数
     */
    public static void randomTest(){
        //2.召唤精灵
        Random r=new Random();
        //3.指挥精灵产生随机数

        /*for (int i = 1; i <= 20; i++) {
            int num =r.nextInt(100)+1;
            System.out.println(num);
        }*/
        //需求:产生20~80之间的随机数
        Random rc=new Random();
        for (int i = 1; i <= 60; i++) {
            //0~60+20
            int num=rc.nextInt(61)+20;
            System.out.println(num);

        }
    }
}

1.1.23 循环练习实例

        需求:求1~100之间的偶数和,并把求和的结果打印在控制台

分析:
            1.定义求和变量sum,准备记录累加的结果
            2.使用for循环,分别获取数据1-100
            3.循环中加入if语句,筛选除偶数数据
            4.将每一个偶数数据,和sum变量进行累加
            5.循环结束后,打印求和后的结果

        //1.定义求和变量sum,准备记录累加的结果
        int sum = 0;
        //2.使用for循环,分别获取数据1-100
        for (int i = 1; i <= 100; i++) {
            //i:1~100之间的每一个数据
            //3.在循环加入if语句,筛选除偶数数据
                if (i % 2 == 0) {
                    //4.累加求和
                    sum = i + sum;
                    return sum;
                }
        }

    /*需求:在控制台打印出99乘法表

    1*1=1
    1*2=2 2*2=4
    1*3=3 2*3=6 3*3=9
    1*4=4 2*4=8 3*4=12 4*4=16
    1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
    ...

    建议初学步骤:
    1.9行9列的矩形
    2.9行的直角三角形
    3.99乘法表

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

1.1.24 if 语句练习实例

1.1.25 random 随机数练习实例

1.1.26 while 循环练习实例

1.3 数组

1.1.27 需求:排序数组

//需求:(从小到大)排序数组

public static void main(String[] args) {
    Scanner reader=new Scanner(System.in);
    //定义实参数组
    double arr[];
    System.out.println("请输入要排序数组的长度");
    int n=reader.nextInt();
    arr=new double[n];//初始化数组
    //创建排序对象sortNumber1
    SortNumber1 sortNumber1=new SortNumber1();//初始化对象sortNumber1
    //为实参数组赋值
    for (int i=0;i<arr.length;i++){
        System.out.println("请输入第"+(i+1)+"个数");
        arr[i]=reader.nextDouble();//这段代码是在Java中使用Scanner对象的nextDouble()方法来读取用户输入的一个double类型的值,并将其赋值给数组arr的第i个元素。换句话说,这行代码是用来从控制台输入读取一个double类型的值,并将其存储到数组arr的第i个位置上。

    }
    //将实参数组的应用传递给形参数组
    sortNumber1.sortArray(arr);

    //输出数组
    for(double num:arr){
        System.out.println(num);
    }
}

}
class SortNumber1{

    //数组排序
    void sortArray(double numArray[]){
        for (int i=0;i<numArray.length-1;i++){				//仔细思考length-1
            for (int j=i+1;j<numArray.length;j++){
                if(numArray[i]>numArray[j]){
                    double temp=numArray[i];
                    numArray[i]=numArray[j];
                    numArray[j]=temp;
                }}}}}

1.1.28 传值

public class ArgsTest1 {
    //课程在黑马的Day5_06 14:50
    public static void main(String[] args) {
        int number = 100;
        //变量在内存中就会占字节空间
        System.out.println("调用change方法前:" + number);        // 100
        change(number);
        System.out.println("调用change方法后:" + number);        // 100
    }

    public static void change(int number) {/*这个方法有形参,形参对于方法而言
        就是个变量而已,变量就会占空间*/
        number = 200;
    }
}

与上述代码区别 change中有个return

//数组记录的是一份地址!
/*
    方法的参数传递问题
        方法的参数  如果是基本数据类型  那么在传参的时候
        真正所传过来的就是具体的数值
*/

public class ArgsTest1_1 {

    public static void main(String[] args) {
        int number = 100;
        System.out.println("调用change方法前:" + number);
        //int result=change(number),这是找了一个新变量来接收
        number = change(number);//用已有的number接着做接收
        //方法有形参,形参对于内存来讲是变量
        System.out.println("调用change方法后:" + number);
    }

    public static int change(int number) {
        number = 200;
        return number;/*在哪调的方法,结果就会回到哪里去
        这里是change调的,就会回到change()中
        */
    }
}
//运行结果:	
调用change方法前:100
调用change方法后:100

注意比较与下面数组的区别

//方法  栈内存  堆内存
//方法的参数,传递的是引用数据类型的时候,它真正所传递的是地址值
public class ArgsTest2 {
        /*
        方法的参数传递问题 :

            1. 基本数据类型: 传递的是数据值
            2. 引用数据类型: 传递的是地址值

            问题: Java到底是值传递, 还是址传递?
            回答: 值传递, 地址值也是值
     */

    public static void main(String[] args) {
        int[] arr = {11, 22, 33, 44, 55};
        System.out.println("调用change方法之前:" + arr[0]);           // 11
        change(arr);
        System.out.println("调用change方法之后:" + arr[0]);           // 66
    }

    public static void change(int[] arr) {/*
    这个方法是有形参的,形参对于内存来讲是变量,变量就要占空间
    change也会开辟一个空间
    空间中也有一个int[] arr
    主方法会将arr的地址给change一份(两个人两根链子牵着同一只狗)*/

        arr[0] = 66;
    }
    //return后 主方法里面别忘了找一个变量做接收
}

展开讲解 java中的参数传递 按 值 还是 按引用

我的理解: 一个是传 字面量(数字),一个是传地址值 数字是值 ,地址值也是值呀!

1.1.29 数组介绍

        数组介绍:一种容器,可以存储同种数据类型的多个值
        数组的使用场景:发现手里的数据有多个,并且这多个数据还属于同一数组
                     就可以考虑使用数组容器进行维护
        初始化:再内存中,为数组开辟空间,并将数据存入容器的过程

        数组的定义格式:
                1.数据类型[] 数组名;
                2.数据类型 数组名[];
                注意:
                    这种定义格式,定义出来的,只是数组的类型的变量而已,
                    内存中还没有创建出数组容器.
     */
    public static void arrayTest1() {
        int[ ] array;
        int array2[ ];
        //System.out.println(array);
        //System.out.println(array2);
    }

/*
   数组的静态初始化格式:
         1.完整格式:
            数据类型[ ] 数组名=new 数据类型[]{元素1,元素2,元素3...}
         2.简化格式:
            数据类型[ ] 数组名={元素1,元素2,元素3...};
    打印数组名:
        [I@4eec7777
        @:分割符
        [:当前空间,是数组类型的
        I:当前数组类型,是int型
        4eec7777:数组的十六进制内存地址
                
*/
    public static void arrayTest2(){
        int[ ] arr1={11,22,33};
        double[ ] arr2={11.1,22.2,33.3};
        System.out.println(arr1);
        System.out.println(arr2);
    }
}
//运行结果
[I@4eec7777
[D@3b07d329

1.1.30 数组元素访问格式:

1.1.31 数组的动态初始化

数组的动态初始化:
  在初始化的时候,只需要指定数组的长度,系统就会分配默认值(初始值)

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

        不同数据类型 默认值不同
        默认值的分类 :
            整数 : 0
            小数 : 0.0
            布尔 : false
            -----------------------------------------------------
            字符 :'\u0000' ---> Unicode字符---> 常见的体现是空白字符
            引用数据类型 : null
            
                    引用数据类型有哪些呢?
                    有 数组, 类, 接口
                    String本质来讲就是一个类(按ctrl 鼠标左键点一下这个string

1.1.32 二维数组

        细节: 二维数组在存储一维数组的时候, 具体存储的是一维数组的地址值

        二维数组的元素访问格式 :

                数组名[m索引][n索引] :

                m索引 : 指定访问哪一个一维数组
                n索引 : 访问一维数组中的哪一个元素

1.1.33 二维数组的动态初始化

        二维数组动态初始化 :

            格式: 数据类型[][] 数组名 = new 数据类型[m][n];

            m : 这个二维数组中, 可以存放多少个一维数组
            n : 每一个一维数组中, 可以存放多少个元素

1.1.34 二维数组的访问格式

        细节: 二维数组在存储一维数组的时候, 具体存储的是一维数组的地址值

        二维数组的元素访问格式 :

                数组名[m索引][n索引] :

                m索引 : 指定访问哪一个一维数组
                n索引 : 访问一维数组中的哪一个元素

1.1.35 数组索引越界异常

         数组索引越界异常 : ArrayIndexOutOfBoundsException

         原因: 访问了不存在的索引

1.1.36 空指针异常

            空指针异常 : NullPointerException

            原因: 当引用数据类型的变量, 被赋值为null之后, 就代表跟堆内存的连接被切断了
                    这时候还想去访问堆内存的数据, 就会出现空指针异常
                    (相当于你牵着一条狗,null就是一把菜刀,把你牵狗的绳子切断了)

1.1.37 静态初始化与动态初始化的两种区别

      数组两种初始化的区别:
        动态初始化:手动指定长度,系统分配默认初始化值
        静态初始化:手动指定元素,系统会根据元素的个数,计算出数组的长度

      两种初始化的使用选择:
        1.静态初始化:
            如果要操作的数据,需求中已经明确给出了,直接静态初始化
                需求:已知班级学生成绩为:100,90,100,20,100,找出最高分
                int[] arr={100,90,100,20,100}
        2.动态初始化:
            只明确元素个数,不明确具体数值
                需求1:键盘录入5个学生成绩,找出最高分
                需求2:产生10个1~100之间的随机数,找出最小值

                int[] arr={???}//错误
                int[] arr=new int[5];//正确,得先动态初始化

1.1.43 数据交换

面试题: 实现两个变量的数据交换, 不允许定义第三方变量

定义第三方变量的大家都会

            int a = 10;
            int b = 20;

            int c = a;
            a = b;
            b = c;

            System.out.println("a=" + a);   // 20
            System.out.println("b=" + b);   // 10

不定义第三方变量呢?

 ^ 异或 :

            特点:
                    1. 相同为false, 不同为true
                    2. 一个数字, 被另外一个数字异或两次, 该数本身不变

    异或操作数值的运算过程 :

        1. 将需要运算的数据, 转换为二进制数据

                0000 1010       10
                0000 0101       5

        2. 将二进制数据的0当做为false, 1当做为true, 运算

                0000 1010
            ^   0000 0101
        --------------------
                0000 1111

        3. 将运算后的二进制数据, 转换为十进制

1.1.44 需求:打印逢7则过的数据

        需求:在控制台打印出1~100之间满足封七过的规则的数据

        分析:
                1.通过循环获取到1~100之间的每一个数字
                2.数值拆分,拆分出个位和十位
                3.根据规则加入if判断
                            if(ge==7 || shi==7 || i % 7==0)
                4.打印出满足规则的数据

1.1.45 需求:输出数组元素和

需求:
            有这样的一个数组,元素是{68,27,95,88,171,996,51,210}
            求出该数组中满足要求的元素和
            要求是:求和的元素个位和十位都不能是7,并且只能是偶数

  public static void main(String[] args) {
        int[] arr={68,27,95,88,171,996,51,210};
        int evenNumberSum = getEvenNumberSum(arr);
        System.out.println("元素和为:"+evenNumberSum);
    }

    public static int getEvenNumberSum(int[] arr){

        //1.定义一个求和变量
        int sum=0;
        //2.变量数组,获取到内部的每一个元素
        for (int i = 0; i < arr.length; i++) {
            int ge=arr[i]%10;
            int shi=arr[i]/10%10;
            if (ge!=7 && shi!=7 && arr[i]%2==0){
                //System.out.println(arr[i]);
                //求和操作
                sum+=arr[i];

            }

        }return sum;

    }

1.1.46 需求:比较数组内容

        需求:定义一个方法,比较两个数组的内容是否相同
        要求:长度,内容,顺序完全相同

        提示:

        ==:
            1.基本数据类型:比较数据值
            2.引用数据类型:比较地址值

  public static void main(String[] args) {
        int[] arr1={11,33,22};
        int[] arr2={33,22,33};
        boolean b = checkArrayContent(arr1, arr2);
        System.out.println(b);

    }
    public static boolean checkArrayContent(int[] arr1,int[] arr2){
        //1.比较数组的长度
        if (arr1.length!=arr2.length){
            return false;
        }
        /*代码要是能够走到这里,代表数组的长度肯定是相同的
        数组的长度相同,意味着索引是相同的*/
        //比较数组中的元素内容
        for(int i=0;i<arr1.length;i++){
         if(arr1[i]!=arr2[i] ){
             return false;
            }
            //如果代码走到这里,代表两个数组长度,内容,顺序完全相同
        }return true;
    }

1.1.47 需求:查找数组元素索引位置

        需求:
            设计一个方法,查找元素在数组中的索引位置
            (其实是查找元素,在数组中第一次出现的索引位置)
            已知一个数组arr={19,28,37,46,50};
            键盘录入一个数据,查找该数据在数组中的索引.
            并在控制台输出找到的索引值
            如果没有查找到,则输出-1

 public static void main(String[] args) {
        int[] arr={19,28,37,46,50};
        Scanner sc=new Scanner(System.in);
        int num= sc.nextInt();
        int index = genIndex(num, arr);
        System.out.println(index);


    }
    public static int genIndex(int num,int[] arr){
        //1.假设要查找的元素,在数组中就是不存在的
        int index=-1;
        //2.遍历数组,获取内部的每一个元素
        for (int i = 0; i < arr.length; i++) {
            //3.比较
            if (arr[i]==num){
                //4.找到了,让index变量记录正确的索引位置
                index=i;//不是index=num 因为需求是要索引位置不是数字
                break;
            }
        }
        return index;

1.1.48 需求:查找数组元素索引位置(考虑重复问题)

        需求:设计一个方法,查找元素在数组中的索引位置(考虑重复元素问题)
        注意:return只能返回一个结果(提示:没有类型的限制)

        提示:当一个方法运行结束后,有多个结果需要返回,要怎么处理?
        回答:可以将多个结果,存入一个数组容器,将数组返回

    public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        int num= sc.nextInt();
        int[] arr={19,28,37,46,50,19,19};
                //  0   1  2  3  4  5  6
        System.out.println("请输入您要查找的值");
        int[] result = getIndex(num, arr);//这里必须得是实参,除非用Scannner

        if(result.length==0){
            System.out.println("您要查找的元素,在数组中不存在");
        }else {
            for (int i = 0; i < result.length; i++) {
                System.out.println(result[i]);
            }
        }
    }
   public static int[] getIndex(int num,int[] arr) {
       //统计出来num的个数
       int count = 0;
       for (int i = 0; i < arr.length; i++) {
           if (arr[i] == num) {
               count++;
           }
       }
       //根据统计出来的个数来创建一个数组,用于接受相同的元素
       int[] result = new int[count];
       int index = 0;
       //查找元素在数组中的索引,并将其导入数组中
       for (int i = 0; i < arr.length; i++) {
           if (arr[i] == num) {
               result[index] = i;
                index++;//!
           }
       }//将带有结果的数组返回
       return result;
   }

1.1.49 需求:数组反转

        需求:
            已知一个数组arr={11,22,33,44,55};用程序实现把数组中的元素值交换
            交往后的宿主arr={55,44,33,22,11};并在控制台输出交换后的数组元素

思路:

        

        1.确定好谁跟谁换

            第一个和倒数第一个:arr[0] arr[arr.length-1-0]
            第二个和倒数第二个:arr[1] arr[arr.length-1-1]
            第三个和倒数第三个:arr[2] arr[arr.length-1-2]

            arr[i]  arr[arr.length-1-i]

    public static void main(String[] args) {
        int[] arr={11,22,33,44,55};

        reverseArray2(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

    }

    private static void reverseArray1(int[] arr) {
        for (int i = 0; i < arr.length/2; i++) {
            int temp=0;
            temp= arr[i];
            arr[i]= arr[arr.length-1-i];
            arr[arr.length-1-i]=temp;
        }
    }
}

请想出第二种解办法:

            在程序中设计两个指针,指针所指向的位置,交换
                1.定义两个变量,模拟开始和结束指针
                    int start=0;
                    int end=arr.length-1;
                2.交换
                    int temp=arr[0];
                    arr[0]=arr[5];
                    arr[5]=temp;
                3.每一次交换完成,让两个指针向中间移动
                    start++;
                    end--;
            数组反转的思路:
                第一个元素和最后一个元素交换
                第二个元素和倒数第二个元素交换
                ...
                交换的条件:
                start<end

    private static void reverseArray2(int[] arr) {
        for (int start = 0, end = arr.length-1; start < end; start++,end--) {
            int temp=arr[start];
            arr[start]=arr[end];
            arr[end]=temp;
 }

1.1.50 需求:输出评委平均分

        需求:
            在编程竞赛中,有6个评委为参数选手打分,分数为0~100的整数分
            选手的最后得分为:去掉一个最高分和一个最低分后的4个评委的平均值

            1.基本实现(不考虑分数校验)
            2.校验键盘录入的分数是否是0~100之间
            3.抽取方法

思路:

            //1.键盘录入6个评委的打分
            //2.求出6个数据的总和,然后从这6个数据中找到最大值和最小值,
            //3.之后就用总分减去最大值和最小值

        

1.1.51 需求:校验验证码

       需求:请从26个英文字母(大小写都包含),以及数字0~9中,随机产生一个5位的
       字符验证码并打印在控制台
       效果: uYqI,3r4Zj

       分析:
       得到随机验证码后要去做一个校验的行为

    public static void main(String[] args) {
        char[] chs = getContents();//获取内容Contents 内容

        String checkCode = getCheckCode(chs);
        //校验:即与用户输入的字符进行对比!
        System.out.println("请输入验证码!");
        Scanner sc=new Scanner(System.in);
        System.out.println("产生的验证码为:"+checkCode);
        /*if();无法比较因为你只能打印出来随机的字符串,此时还无法使用
        必须的将打印出来的字符拼接成一个整体  去看StringDemo
        字符串的比较还没学习到,暂时先做到这里*/
    }

    private static String getCheckCode(char[] chs) {
        Random r=new Random();
        String checkCode="";
        char[] inputRandom=new char[5];
        for (int i = 0; i < 5; i++) {
            int index2=r.nextInt(chs.length);
            checkCode+= chs[index2];
         }
        return checkCode;
    }

    private static char[] getContents() {
        //定义一个数组满足题目要求
        char[] chs=new char[26+26+10];//不是字符串
        int index=0;
        for (char i = 'a';  i<='z'; i++) {
            chs[index]=i;
            index++;
        }
        for (char i = 'A'; i <='Z'; i++) {
            chs[index]=i;
            index++;
        }
        for (char i = '0'; i <='9' ; i++) {
            chs[index]=i;
            index++;
        }
        System.out.println(chs);
        return chs;
    }
}

1.4 构造方法

1.1.51 构造方法(第7天)

        构造方法 (构造器) :

                创建对象的时候, 要执行的方法

        格式:
                1. 方法名与类名相同, 大小写也需要一致
                2. 没有返回值类型, 连void都没有
                3. 没有具体的返回值 (不能由return语句带回结果数据)

        构造方法的执行时机 :

                在创建对象的时候, 被调用执行
                每创建一次对象, 就会执行一次构造方法.

        构造方法的作用 :

                1. 本质的作用 : 创建对象
                2. 结合执行时机 : 可以创建对象的时候, 给对象中的数据初始化

        构造方法的注意事项 :

                1. 一个类中, 没有编写构造方法, 系统将会提供一个 [默认的] [无参数] 的构造方法
                2. 一个类中, 如果手动编写了构造方法, 系统将不会再提供那个默认的无参构造了
                        * 建议 : 编写类的时候, 无参构造, 带参构造, 全部手动给出

                3. 构造方法不允许手动调用

好处
            1.更好的维护数据
            2.使用者无需关心内部实现,只要知道如何使用即可
        封装的设计规范

同一个类当中,方法名相同,参数不同------->重载关系
    //构造方法也是方法------>允许重载关系的出现


        1.私有成员变量(目的:为了保证数据的安全性)

        2.针对是有的成员变量,提供对应的setXXX和getXXX方法

                set:设置
                get:获取

        封装的设计规范:合理隐藏,合理暴露

1.1.52需求:构造函数的练习

比较简单 跳过

1.1.53 就近原则

        情况:成员变量和局部变量重名的情况,
        Java使用的是就近原则

        问题:非要使用成员变量,怎么办?
        解决:使用this关键字进行区分

 -------------------------------------------
        this关键字的作用:
            this可以调用本类成员(变量,方法)
                this.本类成员变量
                this.本类成员方法();

             this.的省略规则:
                本类成员方法:没有前提条件,this.可以直接省略
                本类成员变量:方法中没有出现重复的变量,this.才可以省略

     ---------------------------------------
              this介绍:代表当前类对类的引用(地址)
                                -谁来调用我,我就代表谁
                              !!(哪一个对象调用方法,方法中的this,就代表的就是哪一个对象(的地址).)

                                stu1.print()---->this--->stu1的地址
                                stu2.喷淋头()---->this--->stu2的地址

1.1.54 java中的类

    前提需知 : Java当中要想创建对象, 必须现有类的存在

    类 : 一组相关属性和行为的集合, 将其看做为是对象的设计图.
    对象 : 是根据设计图(类), 创建出来的实体

    类和对象的关系:

            1) 依赖关系: 需要根据类, 创建对象
            2) 数量关系: 根据一个类, 可以创建出多个对象

    类的组成:

            类的本质 : 就是对事物进行的描述

                    举例1: 我之前有一个{学生}, 叫做<张三>, 今年<23岁>了, <180的身高>, 平时就喜欢(吃饭)和(学习)...
                    举例2: 前一阵买了一台<白色>的<海尔>{洗衣机}, 花了我<1999块钱>, 老心疼了, 但是(洗衣服)和(甩干)倒是挺方便...


            属性(名词): 在代码中使用成员变量表示, 成员变量跟之前定义变量的格式一样, 只不过位置发生了改变, 类中方法外.

            行为(动词): 在代码中使用成员方法表示, 成员方法跟之前定义方法的格式一样, 只不过需要去掉 static 关键字

 创建类对象进行使用

        创建Student类的对象进行使用

        1. 创建对象的格式
                类名 对象名 = new 类名();

        2. 使用对象成员变量的格式
                对象名.成员变量;

        3. 使用对象成员方法的格式
                对象名.成员方法();

        ----------------------------------------

        细节:
                1) 打印对象名, 可以看到对象的内存地址

                        com.itheima.oop.Student@4eec7777
                        全类名 : 包名 + 类名

                2) 成员变量就算没有赋值, 也可以直接用, 使用的是对象的默认值

1.1.55 权限修饰符

        权限修饰符 :

                private : 同一个类中
                (default) : 同一个类中, 同一个包中
                protected : 同一个类中, 同一个包中, 不同包的子类
                                TODO: 继承
                public : 任意位置访问

1.1.56 需求:展示电影内容

主类:

public class Test {
    public static void main(String[] args){
        Movie movie1=new Movie(1,"东八区的先生们","2022",2.1,"中国大陆","剧情 喜剧","夏睿","张翰 王晓晨");
        Movie movie2 = new Movie(2, "上海堡垒", "2019", 2.9, "中国大陆", "爱情 战争 科幻",  "滕华涛", "鹿晗 舒淇");
        Movie movie3 = new Movie(3, "纯洁心灵·逐梦演艺圈", "2015", 2.2, "中国大陆", "剧情 喜剧",  "毕志飞", "朱一文 李彦漫");

        Movie[] movies={movie1,movie2,movie3};

        //该如何将一个类中的数据,传递给另外一个类
        MovieService movieService=new MovieService(movies);
        movieService.start();
    }

}

 方法:

/**
 * 启动电影信息管理系统
 */
public class MovieService {
    private Movie[] movies;
    private Scanner sc=new Scanner(System.in);

    public MovieService(Movie[] movies) {//得到主类中的movies数据
    this.movies=movies;
    }

    public void start() {//用于将系统启动起来

        lo:
        while (true) {//快捷键 选中需要的内容 ctrl + alt + T
            System.out.println("-----------电影信息系统-------------");
            System.out.println("请输入您的选择:");
            System.out.println("1.查询全部电影信息");
            System.out.println("2.根据id查询电影信息");
            System.out.println("3.退出");
            int choice=sc.nextInt();

            switch(choice){
                case 1:
                    queryMovieInfos();

                    break;
                case 2:
                    System.out.println("请输入1或2或3进行选择");
                    queryMovieInfoById();
                    break;
                case 3:
                    System.out.println("3.退出");
                    //System.exit(0); //终止正在运行的JVM虚拟机
                    break lo;
                default:
                    System.out.println("您的输入有误!请检查!");
                    break;

            }
        }
    }

    /**
     * 此方法根据电影编号,查询电影详细信息
     */
    private void queryMovieInfoById() {
        //1.键盘录入用户输入的编号
//Scanner sc=new Scanner(System.in);将其放在成员变量中,并私有化,没有必要暴露出去
        System.out.println("请输入您要查询的电影编号");
int id= sc.nextInt();
        //2.遍历数组,从数组中查询电影信息
        for (int i = 0; i < movies.length; i++) {
            Movie movie=movies[i];//按住ctrl 鼠标左键点一下这个Movie 进入这个类里面来
            if(id== movie.getId()){
                id=i;
                //将找到的电影信息,打印在控制台
                System.out.println(movie.getId() + "---" + movie.getTitle() + "---" + movie.getTime()
                        + "---" + movie.getScore() + "---" + movie.getArea() + "---"
                        + movie.getType() + "---" + movie.getDirector() + "---" + movie.getStarring());
                return;
            }
        }
        //代码要是到了这里,说明没找到
        System.out.println("您输入的编号不存在,请重新输入!");


    }


    /**
     * 展示出系统中全部的电影(名称,评分)
     *
     */
    private void queryMovieInfos() {
        //1.遍历数组,取出每一个电影对象
        for (int i = 0; i < movies.length; i++) {
            Movie movie=movies[i];
            //System.out.println(movie); 打印对象名,会看到内存地址
            //2.通过电影对象,调用内部getXXX方法,获取信息并打印
            System.out.println(movie.getTitle());
            //这个得到的是地址System.out.println(movie);
            //这个得到的是地址System.out.println(movies[i]);
        }

    }
}

总结:

                1.得需要一个总方法(电影管理系统)也肯定需要Scanner方法
                得需要一个启动电影管理系统,当系统一启动的话,我们就应该给他展示一个菜单
                2.先搭建一个菜单吧!(其实就是一连串的打印语句)
                然后switch语句来将用户输入的choice与菜单做匹配
                3.发现只能运行一次,则我们应该加入循环!快捷键 ctrl alt T
                并且 加入取别名功能  来更好的结束死循环
                4.完善switch输出语句!
                5.发现在switch case1 中需要添加一个方法 来进行
                当用户输入1时 给人家打印电影目录
                6.发现在switch case2 中需要添加一个方法 来进行
                当用户输入2时 给人家打印这个电影的信息

1.5 String 类

1.1.57 String 类的特点

        String类的特点:
            1.java 程序中所有双引号字符串,都是String这个类的对象

            2.字符串一旦被创建,就不可更改,字符串内容不可更改
                                如果想要更改,只能使用新的对象,做替换

            3.String字符串虽然不可改变,都是可以被共享

                  字符串常量池:当我们使用双引号创建字符串对象时,
                  会检查常量池中是否存在该数据
                    不存在:创建
                    存在:复用
                    (jdk7版本之前:StringTable是在方法区中
                    (jdk7版本开始:StringTable是在堆内存中

    public static void main(String[] args) {
        String s="abc";//只有对象才用.调用var/toUpperCase...等许多方法
        System.out.println(s.toUpperCase());
        System.out.println("hellowold".toUpperCase());//只要是写了双引号字符串
        // 他就已经是String字符串的对象了
        s="def";
        System.out.println(s);

        Student stu=new Student("张三",23);
        stu =new Student("李四",24);
        System.out.println(stu.getName()+"---"+stu.getAge());

        String s1="abc";
        String s2="abc";
        System.out.println(s1==s2);//比较的是地址  运行的结果是true
    }
}

1.1.57 String类中常见的构造方法

        public String() :创建有个空白的字符串,里面不含任何内容
        public String(char[] chs):根据传入的字符数组,创建字符串对象
        public String(String original):根据传入的字符串,来创建字符串对象

注意:

            双引号创建出的字符串和new出来的字符串区别:内存地址不一样
            双引号的:在string table中
            new的:堆内存中有自己独立的空间

 public static void main(String[] args) {
        //public String():创建一个空白字符串,里面不含任何内容
        String s1=new String();
        System.out.println(s1);

        //public String(char[] chs):
        char[] chs={'a','b','c'};
        String s2=new String(chs);
        System.out.println(s2);//abc
    }

 1.1.58 String 类中常见面试题

请问是false还是true:

答案:false

原因:

那下一题请问是false还是true:

答案为true

原因:由于java中存在常量优化机制:"a"+"b"+"c"会自动转化为"abc"

1.1.59 String类的比较

        String类中用于比较的方法 :
                将此字符串与指定的对象比较
                public boolean equals(Object anObject)


                将此 String 与另一个 String 比较,不考虑大小写
                public boolean equalsIgnoreCase(String anotherString)

1.1.60 String类的遍历方法

第一种方法:

    /**
     * 字符串的第一种遍历方式
     */
    private static void print1() {//什么时候加static?
        //如果你的方法与主方法是平级的,那么就带有static
        //反之,都不加!
        String s ="itheima";
        char[] chars = s.toCharArray();//将字符串转换为字符
        for (int i = 0; i < chars.length; i++) {//数组的length是一个属性是没有括号的
            System.out.println(chars[i]);
        }
    }

推荐第二种方法:

    /**
     *字符串的第二种遍历方式
     */
    public static void main(String[] args) {
        print1();

        String s ="itheima";
        for (int i = 0; i <s.length(); i++) {//这里是带括号的  方法
            //i=0 1 2 3 4 5 6
            char c=s.charAt(i);
            System.out.println(c);//itheima
        }

1.1.61 String类的截取方法

        String类的截取方法 :
        根据传入的索引开始做截取, 截取到字符串的末尾
                public String substring(int beginIndex) :


         根据传入的开始和结束索引, 对字符串做截取
                            - 包含头, 不包含尾 [ )
                public String substring(int beginIndex, int endIndex) :

         注意: 截取出来的内容, 是作为新的字符串返回, 别忘记找变量接收!!!

1.1.62 String类的替换方法

   String类的替换方法 :

     public String replace(CharSequence target,CharSequence replacement)  :

                    参数1 : 旧值
                    参数2 : 新值

1.1.63 String类的切割

  String类的切割方法 :
    根据传入的字符串作为规则, 切割当前字符串
        public String[] split(String regex)

        .是一个通配符 指的是任意的字符(会切碎糊了)
        可以前面加 \\

        建议: 先正常指定切割规则, 后来发现没有得到自己要的效果,
         就可以尝试在规则前面, 加入 \\
         "abababafba"
         .toCharArray()方法 可以拆分字符串 
         char[ ] charArray=info.toCharArray();

    public static void main(String[] args) {

        String s = "192+168+1+1";

        String[] sArr = s.split("\\+");

        for (int i = 0; i < sArr.length; i++) {
            System.out.println(sArr[i]);
        }

    }
}//     192
//      168
//       1
//       1

1.1.64 StringBuilderDemo

    有字符串拼接操作就得想到StringBuilder
        StringBuilder的作用 : 提高字符串的操作效率

学习目的:

                1. StringBuilder的特点
                2. StringBuilder的构造方法
                3. StringBuilder常用成员方法
                4. 练习
                5. StringBuilder提高效率

主方法中使用StringBuilder拼接一万个字符串用时10秒

method()方法中String普通字符串拼接一万个用时2004秒 StringBuilder提高效率 完胜

    public static void main(String[] args) {

       long start = System.currentTimeMillis();//start开始节点

        StringBuilder sb = new StringBuilder();

        for(int i = 1; i <= 100000; i++){
            sb.append(i);
        }

        System.out.println(sb);

        long end = System.currentTimeMillis();//结束节点 end

        System.out.println(end - start);// 10

        //method();

    }

    private static void method() {
        // 获取1970年1月1日0时0分0秒到现在所经历过的毫秒值 (1秒 = 1000毫秒)
        long start = System.currentTimeMillis();

        String s = "";

        for(int i = 1; i <= 100000; i++){
            s += i;
        }

        System.out.println(s);

        long end = System.currentTimeMillis();

        System.out.println(end - start);            // 2804
    }
}

1.1.65 String类中常见的构造方法

String类常见构造方法 :

            public String() : 创建一个空白字符串, 里面不含任何内容
            public String(char[] chs) : 根据传入的字符数组, 创建字符串对象
            public String(String original) : 根据传入的字符串, 来创建字符串对象

        -----------------------------------------------------------------

        1. 打印对象名, 会看到对象的内存地址, 这里打印字符串对象, 为什么没有看到地址值
                回答: 暂不解释
                TODO: 面向对象(继承), 方法重写, Object类, toString方法

        2. 这三个构造方法, 创建字符串对象, 都没有双引号直接创建来的方便.

                String s = "abc";

        -----------------------------------------------------------------

        字符串对象, 两种创建方式的区别

                1. 双引号直接创建
                2. 通过构造方法创建

 打印对象名, 会看到对象的内存地址, 这里打印字符串对象, 为什么没有看到地址值?

在Java中,打印对象的默认行为是调用对象的 toString() 方法。对于大多数对象,包括字符串对象,toString() 方法的默认实现会打印对象的内存地址(即对象的哈希码),但字符串对象在 toString() 方法中被特别处理。

详细说明:

  1. 默认的 toString() 实现

    • 对于大多数Java对象,toString() 方法的默认实现是输出对象的类名和对象的哈希码,例如: 

    • public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
    • 这个方法的输出通常看起来像 ClassName@HashCode,其中 ClassName 是对象的类名,HashCode 是对象的哈希码。
  2. 字符串对象的 toString() 实现

    • 对于 String 对象,toString() 方法被重写以返回字符串的内容。也就是说,toString() 返回的是字符串对象内部保存的字符序列,而不是内存地址或哈希码。因此,打印字符串对象时,你看到的是字符串的实际内容。
  3. 示例

    String str = new String("Hello");

    System.out.println(str); // 输出: Hello                   System.out.println(str.toString());   // 输出: Hello

  1. 在这里,str 是一个字符串对象,System.out.println(str) 直接输出了字符串的内容“Hello”。由于 String 类重写了 toString() 方法,返回的是字符串的实际值而不是内存地址。

总结

字符串对象的 toString() 方法返回字符串本身,而不是对象的内存地址或哈希码。这是因为 String 类重写了 toString() 方法,提供了更有用的输出,直接显示字符串内容。这种行为与其他大多数对象不同,后者通常会显示内存地址或哈希码。

在Java中,new String("someString") 会在堆内存中创建一个新的 String 对象。至于这个对象会存储在哪里,涉及到两种情况:

  1. 堆内存中的普通对象

    • 使用 new String("someString") 创建的字符串对象会存储在堆内存中,但它与字符串常量池(String Pool)不同。
  2. 字符串常量池

    • 当你使用字符串字面量(例如 "someString")时,这个字符串会存储在字符串常量池中。这是一个特殊的内存区域,用于缓存不可变的字符串字面量,以节省内存和提高性能。

关键点:

  • 字符串常量池

    • String 字面量会被自动放入字符串常量池。例如,"someString" 会放在池中,以便重复使用。
  • 新字符串对象

    • new String("someString") 创建的对象是在堆内存中分配的,独立于字符串常量池。它实际上是一个 String 实例,它会持有对字符串常量池中对应常量的引用,但不会直接放入常量池中。

总结

new String("someString") 创建的对象会在堆内存中分配,属于普通的对象实例,而不是字符串常量池中的内容。字符串常量池主要用于优化字符串字面量的存储和重用。

1.1.66 Scanner中的next和nextLine

 

 Scanner键盘录入字符串
            String next():遇到了空格,或者tab键就不再录入了
            String nextLine():以回车作为录入的结束标志

            弊端:
                1.next():数据可能录入不完整
                2.nextLine():之前调用过nextInt(),nextDouble(),nextFloat()...
                                    如果再nextLine()方法,就不干活了
            解决方法:不用解决
                    Scanner:采集用户信息(只在学习过程用得到) Interger.parse(sc.nextLine())将数字字符串转换为数字  这个代替nextInt() 从而解决 nextLine()与nextInt()冲突的问题
            目前的使用方案:
                    需求如果要键盘录入字符串
                    如果所有的数据,全部都是字符串,直接nextLine();
                        举例:
                            键盘录入用户名,键盘录入用户密码
                        如果数据除了字符串,还有其他类型,需要调用next()方法
                        举例:
                            键盘录入用户名,键盘录入用户年龄,用户身高

public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        

        System.out.println("请输入一个整数");23+回车
        int age=sc.nextInt();
        System.out.println(age);

        System.out.println("请输入字符串");
        String name=sc.nextLine();//这里 识别到回车 作为结束录入的标志
        System.out.println(name);
    }
}
/*请输入一个整数
	23
	23
	请输入字符串


	进程已结束,退出代码0

演示:

                1.next():数据可能录入不完整
                2.nextLine():之前调用过nextInt(),nextDouble(),nextFloat()...
                                    如果再nextLine()方法,就不干活了

      public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);


        System.out.println("请输入一个整数");// 23 +回车
        int age=sc.nextInt();
        String s = sc.nextLine();//这一步是执行不到的,因为 前面有nextInt()
        System.out.println(s);//这步执行不到
        System.out.println(age);

        System.out.println("请输入字符串");
        String name=sc.next();//如果输入的字符有空格,tab 那么空格后的数据是无法打印的 数据遗失 录入不完整
        System.out.println(name);
    }
}
请输入一个整数
23

23
请输入字符串
23 23
23

1.1.67 StringBuilder的特点

 StringBuilder的介绍 :

            1. 一个可变的字符序列

            2. StringBuilder是字符串缓冲区, 将其理解是容器, 这个容器可以
            存储任意数据类型, 但是只要进入到这个容器, 全部变成字符串.
            全部变成字符串.全部变成字符串.全部变成字符串.全部变成字符串.

        StringBuilder的构造方法 :

            public StringBuilder() : 创建一个空白的字符串缓冲区(容器),
            其初始容量为16个字符(超过了16个会自动扩容的)

            public StringBuilder(String str) : 创建一个字符串缓冲区(容器),
            容器在创建好之后, 就会带有参数的内容

         (带参构造与不带参构造 类似于 数组的动态初始化, 静态初始化)

1.1.68 StringBuffer

StringBuilder常用成员方法 :

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

            2. public StringBuilder reverse() : 将缓冲区中的内容, 进行反转

            3. public int length() : 返回长度

            4. public String toString() : 将缓冲区的内容, 以String字符串类型返回

 

1.1.69 需求:判断是否为对称字符串

        需求:键盘接受一个字符串,程序判断出该字符串是否是对称字符串
        (回文字符串),并在控制台打印是或不是
        对称字符串:123321   ,111
        非对称字符串:123123

        思路:对拿到的字符串进行反转(reserve),若跟原数据相同,则判定为回文字符串

public static void main(String[] args) {
        //1.首先会有键盘录入
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入一个对称字符串");
        String content=sc.nextLine();

        //将String转换为StringBuilder,为了调用内部反转的方法
        StringBuilder sb=new StringBuilder(content);
        String reverse = sb.reverse().toString();
        System.out.println("原来的数据:"+content);
        System.out.println("现在的数据:"+reverse);

        //判断反转后的内容,和原数据是否相同
        //content: String类型
        //sb:StringBuilder类型  将sb转换为String类型才能比较
        if(reverse.equals(content)){
            System.out.println("该字符串为对称字符串");
        }else {
            System.out.println("该字符串不是对称字符串");
        }
    }

1.1.69 需求:字符串拼接输出

        需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串
        返回,调用该方法并在控制台输出结果

        例如:
            数组为int[] arr={1,2,3};
            执行方法后的输出结果为:[1, 2, 3]

//public String toString() : 将缓冲区的内容, 以String字符串类型返回
public class StringBuilderTest2 {
    /*
        需求:定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串
        返回,调用该方法并在控制台输出结果

        例如:
            数组为int[] arr={1,2,3};
            执行方法后的输出结果为:[1, 2, 3]

     */
    public static void main(String[] args) {
        int[] arr={1,2,3};
        arrToString(arr);

    }
    //题目要求有返回,则应该想到得来个方法
    //2:two:to(速写不推荐)
    //4:four:for
    public static String  arrToString(int[] arr){//形参arr传递进来
        //有(大量(5次)拼接操作,联想到StringBuilder方法(大幅度提高效率)
        //先搭一个架子 注意架子是在new StringBuilder()括号中搭建

        StringBuilder sb=new StringBuilder("[");

        //架子ok之后,就要遍历数组
        for (int i = 0; i < arr.length-1; i++) {
            sb.append(arr[i]+", ");
        }
        //System.out.println(sb);//发现最后一个元素得特殊处理
        //对最后一个元素进行特殊处理
        System.out.println(sb.append(arr[arr.length-1]+"]"));
        return sb.toString();
    }
}

1.1.70 需求:模拟用户登录

        需求:模拟用户登录,一共三次机会,登录之后要给出相应的提示

        分析:
            1.定义两个变量,模拟已经存在的用户名和密码

            2.键盘录入用户输入的用户名和密码

            3.对比

 1.1.71 需求:统计字符出现次数

        需求:
            键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数
            (不考虑其他字符)

            例如 :aAb3&c2B*4CD1
            小写字母:3个
            大写字母:4个
            数字字母:4个

提示:关键是toCharArray()方法

1.1.71 需求:接收验证码

        需求:
            以字符串的形式从键盘接收一个手机号,将中间四位号码屏蔽
                        最终效果为:156****1234

    public static void main(String[] args) {
        //接受!
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入您的手机号");
        String phoneNumber= sc.nextLine();
        String result1 = phoneNumber.substring(0, 3);
        String result2 = phoneNumber.substring(7);
        System.out.println("屏蔽后为:"+result1+"****"+result2);
    }
}

1.1.72 需求:TMD取代

        需求:
            键盘录入一个字符串,如果字符串中包含(TMD),则使用***替换

public class StringTest4 {

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入骂人的话,请包含TMD:");
        String zhiFu = sc.next();//也可以用已有的zhiFu做接收
        String chars= zhiFu.replace("TMD","***");
        System.out.println(chars);
    }
}

1.1.73 积累的String类方法

1.toCharArray方法

在字符串的遍历方法当中,将字符串转化为字符序列

2.contains方法

String str=file.getname();

str.contains(" XXX"); 判断字符串中是否含有XXX信息

3.String

String s=new String (chs,0,len);将传入的chs字符数组从索引0到索引len截取下来赋值给s

基础篇完结

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值