【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static

目录

  • 1 ArrayList 集合
    • 装箱,拆箱及包装类
  • 2 API 概述和使用
    • Scanner类
    • 匿名对象
    • Random生成随机数
  • 3 字符串
    • 字符串的3+1种构造方法
    • 字符串的常量池
      • equals和==
    • 字符串的获取相关方法
    • 字符串的截取方法
    • 字符串的转换相关方法
    • 字符串的分割方法
  • 4 静态static关键字
    • 静态static的内存图
    • 静态代码块
    • 静态方法和非静态方法的互相调用
  • ● 练习
    • 1 Scanner
    • 2 匿名对象
      • 1. 匿名对象做参数,方法用来输入和并打印输入的数
      • 2. 匿名对象做返回值,接收后调用输入内容
    • 3 Random
      • 1. 练习生成3~9之间的随机数
      • 2. 猜数字小游戏,产生一个随机数,获取输入并判断。
    • 4 对象数组
    • 5 ArrayList
      • 1. 生成6个1~33之间的随机整数,添加到集合,并遍历
      • 2. 自定义4个学生对象,添加到集合,并遍历
      • 3. 按指定格式遍历集合字符串即ArrayList
      • 4. 筛选集合中的随机数
      • 5. 创建一个ArrayList集合,不限制泛型,可以存储任何引用类型,并进行添加,删除,获取操作。打印格式:{元素1¥元素2¥元素3}
    • 6 字符串
      • 1. 定义一个数组,把数组{1,2,3}按照指定格式拼接成一个字符串 ,格式:[word1#word2#word3]
      • 2. 统计输入的字符串中各种字符的个数
      • 3. 把字符串“i. said. remember. this. moment\n in. the. back .of .my . mind\n”按照分隔符“.”分隔为字符串数组,再将字符串数组转化为char数组和byte数组。不限分隔符字符串中的字符类型。(优化:字符串和分割字符串都自己输入)
      • 4. (1)比较以下几个字符串是否是同一个String对象。(2)忽略大小写比较字符串"esEreW#212&REE","EserEw#212&rEe"是否相等
      • 5. (1)将 字符串“Qweken#4”与字符串“Tyuken87*90+)_”和字符串“!@3ken4s”拼接成一个字符串。
    • 7 static
      • 1. 创建一个学生类对象,要求属性:班级,学号,姓名,年龄,性别。其中班级号固定为同一个班级,学号不可随意更改,根据入学即创建学生对象的先后次序自动生成。
      • 2. 画出创建两个学生类对象过程的内存图,重点:静态成员
      • 3. 用静态代码块给学生类中的静态变量赋值
      • 4. 判断下列代码错误点分析修改,根据描述模拟情况

1 ArrayList 集合

  • 数组的长度不可以发生改变,ArrayList 集合的长度可以随意变化
  • ArrayList指泛型
    泛型:装在集合当中的所有元素, 全都是统一的类型
    注意:泛型只能是引用类型,不能是基本类型
  • jdk 1.7开始,右侧的尖括号内部可以不写内容,但<>本身还是要写
    ArrayList list = new ArrayList<>();右侧可以不写泛型内容,但左侧一定要写,这个算是标准写法
  • 对于ArrayList直接打印的不是地址值,而是[内容],为空则[],一般为[元素1,元素2,元素3,元素4]
  • ArrayList打印
public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("哈哈");
        list1.add("呵呵");
        System.out.println(list1);//[哈哈, 呵呵]
        
}
  • ArrayList常用方法和遍历

public boolean add(E e)向集合中添加元素,参数类型和泛型一致;返回值boolean代表是否添加成功
public E remove(int index)根据索引删除,返回删除的元素。(索引从0开始)
public int size()获取长度,返回值是集合中包含的元素个数
public E get​(int index) 返回此列表中指定位置的元素。
list.fori 快速生成遍历循环

装箱,拆箱及包装类

  • 因为泛型只能是引用类型,不能是基本类型,因为集合存的是地址。所以基本类型对应使用“包装类”
  • 引用类型都位于java.lang包下,所以无需导包
基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

从JDK1.5开始,支持自动装箱,自动拆箱
自动装箱:基础类型 -> 包装类
自动拆箱:包装类 -> 基础类型

2 API 概述和使用

使用一个类:
1.导包:package语句后 import 包路径.类名称 class语句前,若要用的目标类和当前类位于同一个包下,省略导包。java.lang包下的内容不需要导包,其他的包都需要import语句。
2.创建:类名称 对象名 = new 类名称();
3.使用:对象名.成员方法名();
不同模块之间,不能导包或者互相使用

Scanner类

导包 import java.util.Scanner;

String next​() 查找并返回此扫描仪的下一个完整令牌。
int nextInt​() 将输入的下一个标记扫描为 int 。

public class Demo01Scanner {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("输入一个int给sc");
        int num = sc.nextInt();
        System.out.println("输入一个String给num");
        String str = sc.next();
        System.out.println("输出接收的sc,num");
        System.out.println(num + "," + str);

    }
}

练习一:输入两个int数字,并且求出和值

public class Exercise01InputSum {
    public static void main(String[] args) {
       inputSum();

    }
    public static int inputSum(){
        Scanner sc = new Scanner(System.in);
        System.out.println("输入两个整数");
        int num1 = sc.nextInt();
        int num2 = sc.nextInt();

        System.out.println("总和" + num1 + num2);
        return num1 + num2;
    }
}

练习二,输入三个数,求max先判断前2个哪个大,再把最大的跟第3个比较

public class Exercise02InputMax {
    public static void main(String[] args) {
        inputMax();
    }
    public static double inputMax(){
        System.out.println("输入3个整数");
        Scanner sc = new Scanner(System.in);
        double num1 = sc.nextDouble();
        double num2 = sc.nextDouble();
        double num3 = sc.nextDouble();
        double max = num1 < num2 ? num2 : num1;
        max = max < num3 ? num3 : max;
        System.out.println("max:" + max);
        return max;

    }

}

匿名对象

匿名对象只能使用唯一的一次,下次再用不得不再创建一个新对象

public class Demo1Anonymous {
    public static void main(String[] args) {
        Person one = new Person();
        one.name = "芭比";
        new Person().name = "肯";
        
        one.showName();//我叫null
        new Person().showName();//我叫芭比
    }
}
  • 匿名对象做参数和返回值
public class Demo2ParamReturn {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        methodParam(sc);

        //用匿名对象简化写法
        methodParam(new Scanner(System.in));
    }
    public static void methodParam(Scanner sc){
        String str = sc.next();
        System.out.println(str);
    }
}
public class Demo2ParamReturn {
    public static void main(String[] args) {
        Scanner sc = methodReturn();
        sc.next();
    }
public static Scanner methodReturn(){
//        Scanner sc = new Scanner(System.in);
//        return sc;

        //简化写法
        return new Scanner(System.in);
    }
}

Random生成随机数

【JavaSE API 】生成随机数的2种方法:Random类和Math类的Random方法

  1. 导包 import java.util.Random;
  2. 创建Random r = new Random();
  3. 使用
    获取一个随机的int数字(范围是int所有范围,有正负两种);
    参数代表范围,左闭右开。[0,3)
int num = r.nextInt(3);

protected int next​(int bits) 生成下一个伪随机数。
int nextInt​(int bound) 返回伪随机的,均匀分布 int值介于0(含)和指定值(不包括),从该随机数生成器的序列绘制。

3 字符串

在java.lang包下,所以不用导包。
程序中所有的双引号字符串,都是String类的对象(就算没有new也是)
字符串的特点:
1.内容永不可变
2.因为字符串内容不可变,所以可以共享
3.字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组

字符串的3+1种构造方法

  • 1public String();创建一个空白字符串, 不含有任何内容
  • 2public String(char[] array);根据字符数组的内容,来创建对应的字符串
  • 3public String(byte[] array);根据字节数组的内筒,来创建对应的字符串
  • 1种直接创建
    String str = "Hello";注意:直接写上双引号,就是字符串对象。只要是字符串一定是对象

字符串的常量池

public boolean equalsIgnoreCase(String str);//忽略大小写进行内容比较

equals和==

  • ==
    对于基本数据类型比较 内容
    对于引用类,只有是同一个对象才true(比较的是对象的内存地址
  • equals
    只能比较引用对象,对于普通类对象,只有同为同一个对象才是true
    但对于File,String,Data和包装类,是比较内容
public class Demo2ConstantPools {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";
        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);

        System.out.println(str1 == str2);//true
        System.out.println(str2 == str3);//false

    }
}

在这里插入图片描述
程序当中直接写上的双引号字符串,就在字符串常量池中。
即直接创建的字符串在常量池,若内容相同即为共享一个对象,3种构造方法的字符串不在常量池也不是共享,是由字符数组或字节数组在堆中转化为字节数组的地址,内容相同也不是同一个对象。

public class Demo2ConstantPools {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";
        
        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);

        byte[] byteArray = { 'a', 'b', 'c'};
        String str4 = new String(byteArray);

        byte[] b2 ={'a', 'b', 'c'};
        String str5 = new String(b2);

        System.out.println(str1 == str2);//true
        System.out.println(str2 == str3);//false
        System.out.println(str3 == str4);//false
        System.out.println(str4 == str5);//false
        System.out.println(str1.equals(str2));//true
        System.out.println(str2.equals(str3));//true
        System.out.println(str3.equals(str4));//true
        System.out.println(str4.equals(str5));//true
        
        System.out.println(str1.equalsIgnoreCase("ABC"));//true
    
    }
}

字符串的获取相关方法

public int length();字符个数
public String concat(String);将当前字符串和参数拼接返回
public char charAt(int index);获取指定索引位置的单个字符(从0开始)
public int indexOf(String str);查出参数字符串在本字符串中首次出现的索引位置,没有就return -1;

注意:concat方法只会把拼接的结果返回,并不改变调用方法的字符串。除非原字符串接收他的返回值

字符串的截取方法

public String substring(int index);截取从参数位置一直到字符串末尾。返回新字符串
public String substring(int begin, int end);截取从begin开始一直到end结束中间的字符串。(按照索引从0开始对应 每一个字符,截取为 [begin,end)

字符串的转换相关方法

public char[] toCharArray();将当前字符串拆分为字符数组作为返回值
public byte[] getByte();获得当前字符串底层的字节数组
public String replace(CharSequence oldString, CharSequence newString); 将所有出现的老字符替换成为新的字符串,返回替换后的新字符串(CharSequence简单理解为可以接受String类型)

字符串的分割方法

public String[] split(String regex);按照参数的规则将字符串切分成为若干部分
注意: 无法根据.划分做参数,split方法的参数其实是一个正则表达式,如果按照英文句“.”必须写“\\.”

split() 方法根据匹配给定的正则表达式来拆分字符串。

注意: .$|* 等转义字符,必须得加 \\

public class Demo3StringMethod {
    public static void main(String[] args) {
        //字符串的获取相关方法-------------------------------------------------------
        String str1 = "Hi~Barbie";
        System.out.println(str1.length());
        System.out.println(str1.concat("Hi~Ken"));
        System.out.println("索引3的字符" + str1.charAt(3));
        str1 = str1.concat("bie~hello java $ rusty lake is fate 1 larua is blossom");
        System.out.println("str1 : " + str1);
        System.out.println("第一次出现bie的索引位置:" + str1.indexOf("bie"));
       
        //字符串的截取方法
        System.out.println("从4截取" + str1.substring(4));
        System.out.println("从[7,13)截取" + str1.substring(7,13));
        
        //字符串的转换相关方法
        char[] ch = str1.toCharArray();
        System.out.println("char数组:" + ch);
        System.out.println(Arrays.toString(ch));
        byte[] by = str1.getBytes();
        System.out.println("by数组:" + by + Arrays.toString(by));
        for (int i = 0; i < by.length; i++) {
            System.out.print(by[i] + ",");
        }
        System.out.println();
        String str2 = "Hoow doo yoou doo?";
        System.out.println("str2" + str2);
        System.out.println(str2.replace("oo", "*"));

        //字符串的分割方法
        String[] str3 = str1.split("a");
        System.out.println("根据a划分str1:"+ str1);
        for (int i = 0; i < str3.length; i++) {
            System.out.println(str3[i]);
        }
        
 		String str3 = "ewr.e..wfs...as.a.d";
        String[] atr = str3.split("\\.");
        printArray(atr);

        String str4 = "ewr\ne.\nwfs.n.as.d";
        String[] atr2 = str4.split("\\n");
        printArray(atr2);
        
    }
}

4 静态static关键字

用于多个对象共享同一份数据的情况,例如,一个学生类Student,除过姓名成绩等不同的属性外,共同的属性应该为同一间教室,多个对象的教室属性,内容完全相同。无需作为对象成员变量,每次赋不同的值。只需赋值一次,多个对象共享即可。
一旦用了static关键字,那么这样的内容不在属于对象自己,而是属于类的,所以凡是本类的对象,都共享一份static变量或方法。

例如:定义学生类中学号为static,作用:每new一个学生对象,学号都自增统计学生数量

public class DemoStatic {
    public static void main(String[] args) {
        Student stu1 = new Student("barbie",true,18);
        Student stu2 = new Student();
        Student stu3 = new Student("奥罗拉",true,16);
        Student stu4 = new Student("菲利普",false, 17);
        stu3.showInfo();
        stu2.showInfo();
        stu4.showInfo();
    }
}

学生学号:3 姓名:奥罗拉 是否女孩:true 年龄:16
学生学号:2 姓名:null 是否女孩:false 年龄:0
学生学号:4 姓名:菲利普 是否女孩:false 年龄:17

静态方法不属于对象,而是属于类。如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用他。

MyClass obj = new MyClass();
        obj.method();

        obj.methodStatic();//不推荐,会误以为是普通成员方法。
        MyClass.methodStatic();

对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用
不推荐用对象调用静态方法,因为会误以为是普通成员方法,且编译后也会被javac翻译成为类名称,.静态方法名
有static,都推荐使用类名称进行调用。
对于本类当中的静态方法,可以省略类名称直接调用。
注意:
1.静态不能直接访问非静态
2. 静态方法当中不能用this

因为在内存当中是先有得静态内容,后有的非静态内容。
this代表当前对象,通过谁调用的方法 ,谁就是当前对象。但静态方法不用对象

静态static的内存图

静态方法就算写为对象.方法对象.属性。编译期间也会翻译为类.方法类.属性,然后去方法区找。跟对象无关

public class Student {
    //为什么定义两个,因为id属于学生的属性,属于对象,每个对象不一样。但idCount属于属于类
    //每次new该类对象才自增,不保存加过的数
    private static int idCount = 0;
    private int id = 0;
    static String room = "一年级一班";
    String name;
    boolean girl;
    int age;

    public Student(String name, boolean girl, int age) {
        this.id = ++idCount;
        this.name = name;
        this.girl = girl;
        this.age = age;
    }
    public Student(){
        this.id = ++idCount;
    }
    public void showInfo(){
        System.out.println("学生学号:" + this.id + " 姓名:" + this.name + " 是否女孩:" + this.girl + " 年龄:" + this.age);
    }

    public static void setRoom(String room) {
        Student.room = room;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setGirl(boolean girl) {
        this.girl = girl;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static int getIdCount() {
        return idCount;
    }

    public int getId() {
        return id;
    }

    public static String getRoom() {
        return room;
    }

    public String getName() {
        return name;
    }

    public boolean isGirl() {
        return girl;
    }

    public int getAge() {
        return age;
    }

}
public class Demo02Static {
    public static void main(String[] args) {
        Student.room = "大一一班";

        Student one = new Student("小刘", false, 20);
        System.out.println("one的姓名:" + one.getName());
        System.out.println("one的教室:" + Student.getRoom());
        System.out.println("one的年龄:" + one.getAge());
        System.out.println("one的学号:" + one.getId());
        System.out.println("============================");
        Student two = new Student("小李", true, 12);
        System.out.println("two的姓名:" + two.getName());
        System.out.println("two的教室:" + Student.getRoom());
        System.out.println("two的年龄:" + two.getAge());
        System.out.println("two的学号:" + two.getId());

        System.out.println("学生人数:" + Student.getIdCount());

    }

}

在这里插入图片描述
注意:根据类名称访问静态成员变量的时候,全程和对象没关系,只和类有关

静态代码块

特点:当第一次用到本类时,静态代码块执行唯一的一次。
静态内容总是优先于非静态,所以静态代码块比构造方法先执行
格式:

public class 类名称{
	static{
  		//静态代码块的内容
	}
}

静态代码块的典型用途:用来一次性地对静态成员变量进行赋值

静态方法和非静态方法的互相调用

【JavaSE语法】类之间方法的调用(静态方法与非静态方法间的互相调用)

非静态方法调用内部类方法:一律直接调,方法名(参数)
非静态方法调用外部类方法:静态方法用类名.方法名。非静态方法用对象名.方法名(参数)
静态方法调用静态方法:内部类的方法直接调方法名(参数),同包外部类的方法用类名.方法名(参数)
静态方法调用非静态方法:一律用对象.方法名(参数)

● 练习

1 Scanner

  1. 输入四行话,并输出合并后的句子
    A:
		Scanner sc = new Scanner(System.in);
        String str1 = sc.next();
        str1 += sc.next();
        str1 += sc.next();
        str1 += sc.next();
        System.out.println(str1);
  1. 输入三个数,求max。先判断前两个哪个大,再把最大的跟第三个比较
    A:
 		//输入三个int数,输出最大的
        int num1 = sc.nextInt();
        int num2 = sc.nextInt();
        int num3 = sc.nextInt();
        num1 = num1 > num2 ? num1 : num2;
        num3 = num1 > num3 ? num1 : num3;
        System.out.println(num3);

2 匿名对象

1. 匿名对象做参数,方法用来输入和并打印输入的数

public static void method1(Scanner sc){
        System.out.println("输入几个整数,判断最小值");

        int num = sc.nextInt();
        int max = num;
        for(int i = 0; i < 5; i++){
            if(sc.hasNextInt()){
                num = sc.nextInt();
                max = num < max? num: max;
            }
            else{
                String str = sc.next();//把错误数据先读取掉,免得后续又读到
                System.out.println("输入的不是整数,重新输");
                
            }
        }
        System.out.println(max);

    }
	public static void main(String[] args) {
        //1.匿名对象做参数,方法用来输入和并打印输入的数
        method1(new Scanner(System.in));
    }

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第1张图片

2. 匿名对象做返回值,接收后调用输入内容

	public static Scanner method2(){
        Scanner sc = new Scanner(System.in);
        return sc;
    }
 	public static void main(String[] args) {
        Scanner sc = method2();
        System.out.println(sc.next());
    }

3 Random

1. 练习生成3~9之间的随机数

A:用Math和Random类两种生成随机数

 //想生成,[3,9]的随机数
        for (int i = 0; i < 10; i++) {
            Random r1 = new Random();
            System.out.print("Random:" + (r1.nextInt(7) + 3));

            System.out.print(" Math:" + (int)(3 + Math.random() * 7) );
            System.out.println();
        }

2. 猜数字小游戏,产生一个随机数,获取输入并判断。

A:

boolean flag = true;
        System.out.println("请输入猜的数字,范围1~100");
        int tmp = new Random().nextInt(100) + 1;
        int time = 0;
        while(flag){
            time++;
            Scanner sc = new Scanner(System.in);
            if(sc.hasNextInt()){
                int num = sc.nextInt();
                if(num > tmp){
                    System.out.println("猜大了");
                }else if(num < tmp){
                    System.out.println("猜小了");
                }else{
                    System.out.println("恭喜你猜对了!本轮用了" + time + "次");
                }
            }else{
                System.out.println("输错了,不是整数,重新输");
            }

4 对象数组

要求定义一个数组,用来存3个Person对象
默认值为null,分别创建Person对象入数组
A:

	public static void main(String args){
		Person[] arr1 = new Person[3];
        Person p1 = new Person("barbie", "女", 100);
        Person p2 = new Person();
        Person p3 = new Person("ken", "男", 30);

        arr1[0] = p1;
        arr1[1] = p2;
        arr1[2] = p3;

        System.out.println(arr1[0].getName());
        System.out.println(arr1[2].getAge());
  }

5 ArrayList

复习ArrayList,按照添加顺序的顺序存储,可以重复存储,有索引从0开始
标准定义: ArrayList list = new ArrayList<>();
打印:直接打印,出现的是内容,而不是地址值。数组和对象直接打印才是地址值

1. 生成6个1~33之间的随机整数,添加到集合,并遍历

public class Exercise1List {
    public static void main(String[] args) {
        for (int n = 0; n < 1000; n++) {//测试100次
            Random r = new Random();
            ArrayList<Integer> list = new ArrayList<>();
            for (int i = 0; i < 6; i++) {
                int num = r.nextInt(33) + 1;
                list.add(num);
                
            }
            System.out.println(list);

        }
    }
}

2. 自定义4个学生对象,添加到集合,并遍历

public class Exercise2List {
    public static void main(String[] args) {
        Student stu1 = new Student("barbie",true,"研二");
        Student stu2 = new Student("ken",false,"大一");
        Student stu3 = new Student("小明",true,"一年级");
        Student stu4 = new Student("小李",false,"幼儿园");

        ArrayList<Student> list = new ArrayList<>();
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);
        list.add(stu4);
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i).name);
        }
    }

3. 按指定格式遍历集合字符串即ArrayList

  • 定义以指定格式打印集合的方法(ArrayList类型作为参数)使用{}扩起集合,使用@分隔元素,
  • 格式参照{元素1@元素2@元素3@元素4}
public class Exercise03List {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("一");
        list.add("二");
        list.add("三");

        printArray(list);

    }
    public static void printArray(ArrayList<String> list){
        System.out.print("{");
        for (int i = 0; i < list.size(); i++) {
            if(i == list.size() - 1){
                System.out.print(list.get(i));
            }else{
                System.out.print(list.get(i) + "@");
            }
        }
        System.out.println("}");
    }
}

4. 筛选集合中的随机数

用一个大集合存入20个随机数字,然后筛选其中的偶数,放到小集合当中。要求使用自定义的方法来实现筛选,集合当返回值

public class Exercise04List {
    public static void main(String[] args) {
        System.out.println(evenNumber(20));
    }

    //参数:确定传入大集合的随机数个数
    public static ArrayList<Integer> evenNumber(int size){
        ArrayList<Integer> maxList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            Random r = new Random();
            maxList.add(r.nextInt());
        }
        System.out.println(maxList);

        ArrayList<Integer> minList = new ArrayList<>();
        for (int i = 0; i < maxList.size(); i++) {
            if(maxList.get(i) % 2 == 0){
                minList.add(maxList.get(i));
            }
        }
        return minList;
    }

}

5. 创建一个ArrayList集合,不限制泛型,可以存储任何引用类型,并进行添加,删除,获取操作。打印格式:{元素1¥元素2¥元素3}

A: 无泛型的ArrayList定义方式,List list = new ArrayList();可以添加任意类型的元素,包括自定义类

public class Code01 {
    public static void printArray(List list){
        System.out.printf("{");
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i));
            if(i != list.size() - 1){
                System.out.print('¥');
            }
        }
        System.out.printf("}");
    }
    public static void main(String[] args) {
        List list1 = new ArrayList();
        list1.add(23);
        list1.add("erxd");
        list1.add(new Person("人1", "女", 30));
        list1.add('4');
        Person p1 = new Person("人2", "男", 18);
        list1.add(p1);

        System.out.println(list1.get(1));
        printArray(list1);
        list1.remove(4);
        printArray(list1);
    }
}

6 字符串

  • 字符串在java.lang包下,所以不用导入

  • 程序当中所有的双引号字符串,都是String类的对象。(就算没有new String 也照样是)

  • 字符串的特点

    • 字符串的内容永不可变
    • 因为字符串不可改变,所以字符串是可以共享的
    • 字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组
  • 字符串的构造方法3+1种(3种构造方法,1种直接创建)

    • public String(); 创建一个空白字符串,不含有任何内容
    • public String(char[] array);根据字符数组的内容,来创建对应的字符串
    • public String(byte[] array);根据字节数组的内容,来创建对应的字符串
    • 1种直接创建:String str = "Hello";直接写上双引号,就是字符串对象,只要是字符串对象准是对象
  • 注意:直接创建的字符串在常量池,若内容相同即为共享一个对象。3种构造方法的字符串不在常量池也不是共享,是由字符数组或字节数组在堆中转化为字节数组的地址,内容相同也不是同一个对象。

  • 字符串的常用方法

    • int length();获取字符串长度,即几个字符就多长
    • String concat(String str);将原字符串和参数字符串拼接并返回,注意:并不会改变原字符串和参数字符串
    • char charAt(int index);根据索引找到字符串对应位置的字符返回,索引从0 开始算
    • int indexOf(String str);根据参数字符串,找到原字符串中第一次出现参数的位置索引并返回
    • String substring( int index);截取字符串的index位置一直到字符串末尾,并返回这个新字符串
    • String substring(int begin, int end);截取 [begin,end) 部分的字符串并返回这个新字符串
    • char[] toCharArray();把原字符串转化为char数组并返回
    • byte[] getBytes();转化为byte数组并返回
    • String replace(CharSequence oldString, CharSequence newString);把字符串中的固定字符串转化为新字符串,CharSequence简单理解可接受String类型
    • String[] split(String regex);根据参数划分字符串为字符串数组并返回,不可用.划分,用.的话就用转义字符\\.

1. 定义一个数组,把数组{1,2,3}按照指定格式拼接成一个字符串 ,格式:[word1#word2#word3]

A:
利用任何数据类型与String类+后,都会自动转化为字符串并拼接的特点。依次遍历数组内容,并通过+=将数组元素一个个连同分隔符#加到字符串中,并返回即可。

public class Class01<T>{
    //定义一个数组,把数组{1,2,3}按照指定格式拼接成一个字符串,格式:[word1#word2#word3]
    public static<T> String splicing(T[] arr){
        String str1 = "[";

        for (int i = 0; i < arr.length; i++) {
            str1 += arr[i];//任何数据类型和字符串+,就会自动拼接
            if(i == arr.length - 1){
                continue;
            }
            str1 += '#';
        }
        str1 += ']';
        return str1;
    }

}

public static void main(String[] args) {
        //测试Class01
        Integer[] arr1 = {12, 23, 123, 564, 345, 23};
        String atr1 = splicing(arr1);
        System.out.println(atr1);

        String[] arr2 = {"!@", "#$", "%^&"};
        Character[] arr3 = {48, '#', '*', 97, 65};
        System.out.println(splicing(arr2));
        System.out.println(splicing(arr3));

    }

结果

[12#23#123#564#345#23]
[!@##$#%^&]
[0###*#a#A]

2. 统计输入的字符串中各种字符的个数

键盘输入一个字符串,并且统计其中各种字符出现的次数。种类有:大写字母、小写字母、数字、其他。
A:
将字符串转化为字符数组用char[] toCharArray(); 再根据字符串的长度int length();遍历字符串进行统计,或者转化后的字符数组长度也可以。

  • Scanner中next()和nextLine()的区别
    next() 与 nextLine() 区别
next():
1、一定要读取到有效字符后才可以结束输入。
2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
next() 不能得到带有空格的字符串。
nextLine():
1、以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
2、可以获得空白。
public class Class01 {
    // 2. 统计输入的字符串中各种字符的个数
    //键盘输入一个字符串,并且统计其中各种字符出现的次数。
    // 种类有:大写字母、小写字母、数字、其他。

    //数字0,48~57;a,97~122;A,65~90;
    public int[] countChar(String str){
        char[] ch = str.toCharArray();
        int[] count= new int[4];//三个元素分别代表,数字字符个数,小写字母个数,大写字母个数,其他字母个数
        for (int i = 0; i < str.length(); i++) {
            if(ch[i] >= 48 && ch[i] <= 57){
                count[0]++;
            }else if(ch[i] >= 97 && ch[i] <= 122){
                count[1]++;
            }else if(ch[i] >= 65 && ch[i] <= 90){
                count[2]++;
            }else{
                count[3]++;
            }
        }

        return count;
    }

}
 public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一串随机的字符,回车结束:");
        String str = sc.nextLine();
        int[] arr = new Class01().countChar(str);
        //int[] arr = new Class01().countChar("1234%^ttehd#$234@#3%6742EWgfvQ");
        //printArray(arr);
        System.out.println("这串字符中,数字字符个数:" + arr[0]
        + ",小写字母个数:" + arr[1] + ",大写字母个数:" + arr[2] + ",其他字符个数:" + arr[3]);
    }

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第2张图片

3. 把字符串“i. said. remember. this. moment\n in. the. back .of .my . mind\n”按照分隔符“.”分隔为字符串数组,再将字符串数组转化为char数组和byte数组。不限分隔符字符串中的字符类型。(优化:字符串和分割字符串都自己输入)

A: 用String[] split(String regex); 根据参数分割字符串并返回分割后的字符串数组,用+把字符串数组拼接为字符串,用char[] toCharArray();把字符串转化为字符数组,用byte[] getBytes();把字符串转化为字节数组

  • 其中,split方法的参数其实是一个“正则表达式”,如果按英文句点.做参数划分必须写\\.,两个反斜杠。所以再用String replace(String old, String new)在分割之前就把.替换成\\.。包括\n,要匹配,只能用\\n做分隔符,代表\n
		String str3 = "ewr.e..wfs...as.a.d";
        String[] atr = str3.split("\\.");
        printArray(atr);

        String str4 = "ewr\ne.\nwfs.n.as.d";
        String[] atr2 = str4.split("\\n");
        printArray(atr2);
[ewr,e,,wfs,,,as,a,d]
[ewr,e.,wfs.n.as.d]
public class Class02 {
    // 把字符串按照分隔符“.”分隔为字符串数组,再将字符串数组转化为char数组和byte数组。
    //把字符串“i. said. remember. this. moment\n in. the. back .of .my . mind\n”

    public String[] conversion(String str, String sep){
        if(sep.indexOf(".") != -1){//说明有要替换为转义字符\\.
            sep = sep.replace(".", "\\.");
        }
        if(sep.indexOf("\n") != -1){//说明有要替换为转义字符\\.
            sep = sep.replace("\n", "\\n");
        }
        return str.split(sep);
    }
    public char[] toChar(String[] str){
        //把字符串数组拼接成一个字符串,再用方法
        String str2 = new String();
        for (int i = 0; i < str.length; i++) {
            str2 += str[i];
        }
        return str2.toCharArray();
    }
    public byte[] toByte(String[] str){
        String str2 = new String();
        for (int i = 0; i < str.length; i++) {
            str2 += str[i];
        }
        return str2.getBytes();

    }
}

	public static void main(String[] args) {
		/*测试Class02*/
        Class02 c2 = new Class02();
        Scanner sc2 = new Scanner(System.in);
        System.out.println("输入要用来分割的字符串,回车结束:");
        String str1 = sc2.nextLine();
        System.out.println("输入作为分隔符的字符串,回车结束:");
        String str2 = sc2.nextLine();

        String[] strArr1 = c2.conversion(str1, str2);
        System.out.println("分割后的字符串数组:");
        printArray(strArr1);
        System.out.println("转为字符数组后打印如下:");
        printArray(c2.toChar(strArr1));
        System.out.println("转为字节数组后打印如下:");
        printArray(c2.toByte(strArr1));
   }

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第3张图片
【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第4张图片
失败尝试:\n还是不能做分隔符,直接使用在split中可以,要读取字符串中的\n符号不行
【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第5张图片

4. (1)比较以下几个字符串是否是同一个String对象。(2)忽略大小写比较字符串"esEreW#212&REE","EserEw#212&rEe"是否相等

 		String str1 = new String("abc");
        char[] ch1 = {'a', 'b', 99};
        String str2 = new String(ch1);
        String str22 = new String(ch1);

        byte[] by1 = {97, 98, 99};
        String str3 = new String(by1);

        String str4 = "abc";
        String str5 = "ab" + "c";
        String str6 = "a".concat("bc");

A(1): 3+1种字符串创建方式的字符串,且内容相同。
注意:

  • 创建字符串的方法中,只有1种直接创建的字符串存在堆中的常量池,所以内容相同就是同一个对象同一个地址,包括+号拼接的字符串。
  • 其他创建方法,包括concat拼接的字符串,生成的字符串都在堆中单独存在,哪怕用的是同一个数组创建的字符串,底层也是new一个新的对象,指向参数的数组。所以内容相同,地址也绝对不同,也不是同一个对象
    【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第6张图片
		System.out.println(str1 == str2);//false
        System.out.println(str1 == str3);
        System.out.println(str1 == str4);
        System.out.println(str1 == str5);
        System.out.println(str1 == str6);
        ……

结果:用== 比较的是引用类型的地址,只有str4 == str5是true,其他全部不等为false
A(2):

 System.out.println("esEreW#212&REE".equalsIgnoreCase("EserEw#212&rEe"));//true

5. (1)将 字符串“Qweken#4”与字符串“Tyuken87*90+)_”和字符串“!@3ken4s”拼接成一个字符串。

(2)在字符串“23ken4#¥ken8dczxken”字符串中,返回字符串“ken”第一次出现的位置。
(3)再把其中的字符串“ken”统一换为“barbie”。
(4)返回4,8,12索引位置的字符。
(5)截取位置12到结尾的字符串返回,截取[4,8]这一段位置的字符串返回打印。

A: 注意,这些字符串相关方法,只会返回处理的结果,并不会改变原字符串,除非用原字符串名重新接收返回值。
A(1):

String str1 = "Qweken#4".concat("Tyuken87*90+)_").concat("!@3ken4s");
System.out.println(str1);

A(2):

String str1 = "23ken4#¥ken8dczxken";
        System.out.println("字符串:" + str1 + ",ken字符串第一次出现的索引是:");
        System.out.println(str1.indexOf("ken"));

A(3):

 		System.out.println("字符串:" + str1 + "中的ken换为barbie以后:");
        String str2 = str1.replace("ken", "barbie");
        System.out.println(str2);

A(4):

System.out.println("字符串str1:" + str1 + "索引4,8,12的字符分别是:");
        System.out.println(str1.charAt(4));
        System.out.println(str1.charAt(8));
        System.out.println(str1.charAt(12));

A(5):

 		System.out.println("截取字符串" + str1 + "索引12到结尾的部分:");
        System.out.println(str1.substring(12));
        System.out.println("截取字符串" + str1 + "索引[4,8]的部分:");
        System.out.println(str1.substring(4,9));

        System.out.println("再次输出str1,可以发现与最开始并没有变");
        System.out.println(str1);

7 static

1. 创建一个学生类对象,要求属性:班级,学号,姓名,年龄,性别。其中班级号固定为同一个班级,学号不可随意更改,根据入学即创建学生对象的先后次序自动生成。

A:

public class Student {
  
    private static String room;
    private static int idCount;//用来自增给id赋值,意为学生人数
    private int id;
    private String name;
    private boolean sex;
    private int age;

    public Student(String name, boolean sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.id = ++idCount;
    }
    public Student(){
        this.id = ++idCount;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public static int getIdCount() {
        return idCount;
    }


    public boolean isSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }

    public void showInfo(){
        System.out.println("班级:" + this.room + "学号:" + id +
                "姓名:" + this.name + "性别:" + sex + "年龄:" + age);
    }
 public static void main(String[] args) {
        Student stu1 = new Student("张三", false, 45);
        Student stu2 = new Student("灵儿", true, 16);
        Student stu3 = new Student();

        stu1.showInfo();
        stu2.showInfo();
        stu3.showInfo();
 }
班级:null学号:1姓名:张三性别:false年龄:45
班级:null学号:2姓名:灵儿性别:true年龄:16
班级:null学号:3姓名:null性别:false年龄:0

2. 画出创建两个学生类对象过程的内存图,重点:静态成员

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第7张图片
赋的值也在静态区,静态成员就存储在静态区

3. 用静态代码块给学生类中的静态变量赋值

A: 在Student类中加上这段,注意。静态代码块只在类第一次被使用时执行唯一的一次,所以inCount 初始化0并不会影响后续idCount++。

static{
        room = "九年级五班";
        idCount = 0;
}
班级:九年级五班学号:1姓名:张三性别:false年龄:45
班级:九年级五班学号:2姓名:灵儿性别:true年龄:16
班级:九年级五班学号:3姓名:null性别:false年龄:0

4. 判断下列代码错误点分析修改,根据描述模拟情况

(1)

private static String room;
    private static int idCount;//用来自增给id赋值,意为学生人数
    private int id;
    private String name;
    private boolean sex;
    private int age;
    public void showInfo(){
        System.out.println("班级:" + this.room + "学号:" + id +
                "姓名:" + this.name + "性别:" + this.sex + "年龄:" + age);
    }
    public static void stMethod1(){
        showInfo();
        System.out.println(this.sex);
    }

(2)写静态方法调用非静态方法,静态方法调用静态方法的区别。包括同包不同类即外部类和类内部两种情况。

(3)写非静态方法调用非静态方法,非静态方法调用静态方法。内外部类方法调用的区别

(4)因为静态导入的情况下,可以在本类的静态方法中,直接调用导入类的静态成员而不是用类名调用,那如果内部类与外部类的静态成员同名,并静态导入。直接调是识别哪一个成员?

A(1):

  • 静态方法不可以直接访问非静态,因为内存中现有静态后有非静态。
  • 不可以在静态方法中用this,因为静态成员是属于类的,没有对象,就没有this可用。
	private static String room;
    private static int idCount;//用来自增给id赋值,意为学生人数
    private int id;
    private String name;
    private boolean sex;
    private int age;
    public void showInfo(){
        System.out.println("班级:" + this.room + "学号:" + id +
                "姓名:" + this.name + "性别:" + this.sex + "年龄:" + age);
                // ● this.room没错,只是多余。room是静态变量,就算在非静态方法中可以使用this调用非静态,也无效,会编译为类名.静态,若是类内部的就是直接静态名
    }
	public static void stMethod1(){
		//showInfo(); ● 错误点,静态方法不可以直接访问非静态,因为内存中现有静态后有非静态。
        //System.out.println(this.sex); ● 错误点,静态方法与对象无关,不可以使用this
        new Student().showInfo();//静态方法中通过new对象访问非静态方法和变量
        System.out.println(idCount);//本类的静态成员可以直接访问
        System.out.println(new Student().sex);
    }

A(2):

总结:

  • 静态方法中
    调用本类的静态方法/变量,直接方法名();变量名
    调用外部类的静态方法/变量,类名.方法名(); , 类名.变量名
    调用非静态方法/变量,无论类内部或类外部统一 类对应的对象名.方法名(); , 对象名.变量名

重点看Class01的静态方法1,stc1Method1

import static code01.Class02.*;
	public class Class01 {
     public static void stc1Method1(){
        System.out.println("------Class01的静态方法1 成功执行------");

        Class01 c1 = new Class01();
        Class02 c2 = new Class02();
        num1 = 10;// ● 内部静态直接使用
        c1.num2 = 20;//  ● 哪怕是本类的变量,但只要是非静态在静态方法中调用就必须用对象名才可以
        Class02.num3 = 30;// ● 外部静态,用外部类名
        c2.num4 = 40;// ● 外部非静态,用外部类的对象名

        System.out.println("Class01的num1,num2:" + num1 + ", " + c1.num2);
        System.out.println("Class02的num3,num4:" + Class02.num3 + "," + c2.num4);

        stc1Method2();//同上,内部静态
        c1.c1Method1();//同上,内部非静态

        Class02.stc2Method1();//同上,外部类静态
        stc2Method2();//因为这里静态导入了外部类,所以也可以直接方法名使用外部静态。
        c2.c2Method1();//同上,外部非静态
        System.out.println("-----------------------");

    }
    public static void stc1Method2(){
        System.out.println("Class01的静态方法2 成功执行");

    }
    public void c1Method1(){
        System.out.println("Class01的方法1 成功执行");

    }
    public void c1Method2(){
        System.out.println("Class01的方法2 成功执行");

    }
}
public class Class02 {
    public static void stc2Method1(){
        System.out.println("Class02的静态方法1 成功执行");
    }
    public static void  stc2Method2(){
        System.out.println("Class02的静态方法2 成功执行");

    }
    public void c2Method1(){
        System.out.println("Class02的方法1 成功执行");

    }
    public void c2Method2(){
        System.out.println("Class02的方法2 成功执行");

    }
}

 public static void main(String[] args) {
        Class01.stc1Method1();
    }

A(3):
总结:

  • 非静态方法中
    调用本类的方法/变量,无论静态或非静态,直接方法名();变量名
    调用外部类的静态方法/变量,类名.方法名(); , 类名.变量名
    调用外部类的非静态方法/变量,类对应的对象名.方法名(); , 对象名.变量名

根据前一个问题的代码,只修改Class02的c2Method1方法内容

 public void c2Method1(){
        System.out.println("--------Class02的方法1 成功执行--------");
        Class01 c1 = new Class01();

        Class01.num1 = 50;// ● 外部静态用类名
        c1.num2 = 60;//  ● 外部非静态用对象名

        num3 = 70;// ● 内部静态或非静态都是直接调用
        num4 = 80;
        this.num3 = 90;// ● 当然非要写类名或者对象名调用也可以,只是多余,没必要
        Class02.num3 = 100;
        this.num4 = 110;

        System.out.println("Class01的num1,num2:" + Class01.num1 + ", " + c1.num2);
        System.out.println("Class02的num3,num4:" + num3 + "," + num4);

        stc2Method2();//同上,内部静态
        c2Method2();//同上,内部非静态,只要是内部统统直接调

        Class01.stc1Method2();//同上,外部类静态
        c1.c1Method2();//同上,外部非静态
        System.out.println("-------------------------------------");

    }

A(4):
假设Class03和Class04两个类中存在静态的同名变量和方法

package code01;
public class Class03 {
    int num1;
    static int num2;
    static void stMethod(){
        Class03 c3 = new Class03();
        c3.num1 = 10;
        num2 = 20;
        System.out.println("num1:" + c3.num1 + "num2:" + num2);
        System.out.println("Class03的静态方法执行");
    }
}
package code01;
import static code01.Class03.*;
public class Class04 {
    int num1;
    static int num2;
    static void stMethod(){
        Class04 c4 = new Class04();
        c4.num1 = 30;
        num2 = 40;
        System.out.println("num1:" + c4.num1 + "num2:" + num2);
        System.out.println("Class04的静态方法执行");
    }

    public static void main(String[] args) {
        stMethod();
    }
}
num1:30num2:40
Class04的静态方法执行

改变Class04中重名静态成员的名称,其他不变。之前的直接调用是调用本类的静态成员,就变成了调用外部类的静态成员。

  • 说明静态导入的情况下,外部类的静态成员与本类的静态成员名称相同则导入失效,就近原则,优先默认为本类的静态成员。只有当不同名时,静态导入后,直接调用外部类静态成员可以调成功
package code01;
public class Class03 {
    int num1;
    static int num2;
    static void stMethod(){
        Class03 c3 = new Class03();
        c3.num1 = 10;
        num2 = 20;
        System.out.println("num1:" + c3.num1 + "num2:" + num2);
        System.out.println("Class03的静态方法执行");
    }
}

package code01;
import static code01.Class03.*;
public class Class04 {
    int num1;
    static int num3;//  ● 只改变了这两个名称
    static void stMethod1(){// ● 
        Class04 c4 = new Class04();
        c4.num1 = 30;
        num2 = 40;
        System.out.println("num1:" + c4.num1 + "num2:" + num2);
        System.out.println("Class04的静态方法执行");
    }

    public static void main(String[] args) {
        stMethod();
    }
}

num1:10num2:20
Class03的静态方法执行

【JavaSE】P114~P147 ArrayList集合,Scanner类,Random,字符串及相关常用方法,静态static_第8张图片

你可能感兴趣的:(Java语法,java,开发语言)