Java基础学习笔记

(1)Java学习路线图(暑期阶段)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(2)常见cmd命令(输入法要用英文字符)

d:                   #转到D盘
dir                  #列出当前目录下的所有目录文件名字和文件名字
md class1            #在当前目录下创建一个叫做class1的文件夹
cd class1            #移动到叫做class1的文件夹里面去
cd class1/tech1      #移动到叫做class1的文件夹下面的tech1的文件夹里面去
cd ..                #回退到上一个文件夹目录
rd class1            #删除文件夹class1
del 1.txt            #删除1.txt这个文件
del *.txt            #删除所有txt文件,del命令可以拓展文其他的文件
左右箭头移动,上下箭头可以找出用过的命令

(3)Java的一些基础知识

①Java平台分类
在这里插入图片描述
在这里插入图片描述
②Jre(Java运行环境)和JDK(下面为图解)
(1)JDK=Jre+java相关的开发工具(例如用于编译的javac)
(2)Jre=JVM(Java虚拟机)+Java SE标准类库
在这里插入图片描述
③Java运行的流程
(1)把Java代码编写在**.java结尾的源代码文件里面
(2)编译:用
javac把源代码编译成字节码文件**,具体指令是javac helloword.java
(3)运行:用字节码文件运行,具体指令是java 字节码文件名
在这里插入图片描述

(4)变量与标识符

①变量

在这里插入图片描述
在这里插入图片描述
字符类型的使用方法
①使用单引号(’ ')括起来的:例如:char c1 = 'a'; char c2 = '中'; char c3 = '9';
②直接使用 Unicode值或者ACSII码来表示字符型常量:‘\uXXXX’。其中,XXXX 代表一个十六进制整数。例如:char c1=\u0023 表示 ‘#’。
③Java 中还允许使用转义字符‘\’来将其后的字符转变为特殊字符型常量。例如char c3 = '\n';

整型的使用方法
在这里插入图片描述
bool类型的使用方法
在这里插入图片描述

基本数据之间的类型转换
自动类型提升:将取值范围小的类型自动提升为取值范围大的类型
在这里插入图片描述
具体情况是:①把取值范围小的值赋给取值范围大的值 ②许多取值范围的变量混合运算 ③当 byte,short,char 数据类型的变量进行算术运算时,按照 int 类型处理,例如byte b3 = b1 + b2;编译报错,b1 + b2 自动升级为 int ,把结果赋给b3就不行
强制类型转换:将取值范围大的类型强制转换成取值范围小的类型,例如把3.14赋值给int,具体的方法是:数据类型 1 变量名 = (数据类型 1)被强转数据值; 例如int i = (int)3.14;
③任意八种基本数据类型的数据与 String 类型只能进行连接“+”运算,且结果一定也是 String 类型,String 类型不能通过强制类型()转换,转为其他的类型 ,要转换的话要用一些其他的办法:
int num = Integer.parseInt(str);

②运算符

在这里插入图片描述
(1)++i是先加再用,i++是先用再加(记忆法“++”在前面就是先加再用,反之陈丽)。单独运算没有区别,复合运算时候有区别;例如

int i=7,j=7;
int x=(++i)*5;                    x值为40
int y=(j++)*5;                    y值为35

PS:一种特殊情况此时m=2
在这里插入图片描述

(2)“+”的两种不同用法:
①对于+两边都是数值的话,+就是加法的意思 ;
②对于+两边至少有一边是字符串的话,+就是拼接
(3) += 的操作不会改变变量本身的数据类型。其他拓展的运算符也如此,且有以下情况:

short s = 3; 
s = s+2;                 编译报错 ,因为2int类型,s+2回自动转为int类型,int不可以赋值给short
s += 2;                 

(4)比较运算符的结果都是 boolean 型,也就是要么是 true,要么是 false。介绍一种一种新的比较运算符instanceof:用于查找某个变量是否是某个类的实例,用法是引用类型变量(object) instanceof 类(class)

boolean b1="Hello" instanceof String;           b1一直是true
System.out.println(b1)

(5)一些逻辑运算符
在这里插入图片描述
在这里插入图片描述
(6)位运算符号
在这里插入图片描述
其中i>>5代表i除以32,i<<5代表i乘以323<<4 类似于 3*2 的 4 次幂,右移是除法,左移是乘法(左乘右移
在这里插入图片描述
(7)条件运算符int i = (1==2 ? 100 : 200); 此时i的值为200凡是可以使用条件运算符的地方,都可以改写为 if-else 结构。反之,不成立。 开发中,如果既可以使用条件运算符,又可以使用 if-else,推荐使用条件运算符。因为执行效率稍高
在这里插入图片描述
该运算符可以用于实现找两数之间的最大值int max=i>j?i:j;

(3)一些语句

分支语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在 switch 语句中,如果 case 的后面不写 break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个 case 的值,直接向后运行,直到遇到 break 或者整个 switch 语句结束,执行终止

int i = 3, test = 3;
        switch (i) {
            case 3:
                test = test + 2;
            case 2:
                test = test + 2;
            case 1:
                test = test + 3;
        }

此时test的值为10

循环语句

①for循环语句
在这里插入图片描述
代码如下所示:

在这里插入图片描述
②while 循环
在这里插入图片描述
在这里插入图片描述
③do-while 循环
在这里插入图片描述
在这里插入图片描述
最简单"无限"循环格式:while(true) , for(;;)

④Java的continue和break和C和C++相比多了一个优点:在多层嵌套的循环的时候可以通过标签指明要break或者continue的是哪一层语句,如下所示:
在这里插入图片描述
而C和C++的这两个语句只可以对当前层的循环起作用

使用Scanner类进行输入

import java.util.Scanner;                                        导入Scannerclass Main{                                                      
    public static void main(String args[])
    {
        Scanner input=new Scanner(System.in);        
        //创建名为input的一个Scanner对象,参数是System.in
        System.out.print("请输入意向输入的数字:");
        int i=input.nextInt();      //调用input的nextInt()方法,还有很多别的next方法
        System.out.println(i);
    }
}

使用Math.random()产生随机数(不用import Math

在这里插入图片描述

数组

①数组的概念:是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。 下面是一维数组和二维数组的图示:
在这里插入图片描述
②数组的声明:在 Java 中数组的符号是[],[]表示一维,[][]表示二维。元素的类型可以是任意的 Java 的数据类型。例如:int、String、Student 等。Java 语言中声明数组时不能指定其长度(数组中元素的个数),必须用动态初始化才能确定。

int[] arr; //直接打印arr的话会打印出内存地址
int arr1[]; 
String[] arr3; //引用类型变量数组 
int[][] grades;  //存储多组姓名 
String[][] names;//二维数组声明,直接打印name和name[i]的话会打印出内存地址
int[] x, y[];    //x 是一维数组,y 是二维数组

③数组的初始化

int array[]={0,1,2,3,4,5};  //静态初始化
int array[]=new int[5];    //动态初始化用于指定数组长度,里面是默认值
String[][] grade = {{"段誉","令狐冲","任我行"},{"张三丰","周芷若"},{"赵敏","张无忌","韦小宝","杨过"}};                     //二维数组的静态初始化
int array[][]=new int[3][3];//二维数组的动态初始化

对于每一行的长度不一样的二维数组动态初始化的方法:先指定行数+为每一行分配空间

int array[][]=new int[3][];   //int array[][]=new int[][3]; 是违法的
array[0]=new int[2];
array[1]=new int[3];
array[2]=new int[4];

动态初始化的默认值如下:
在这里插入图片描述

④数组的遍历(利用数组名.length直接获取所需数组的长度)
(1)一维数组
在这里插入图片描述

(2)二维数组
在这里插入图片描述

⑤Arrays 工具类的使用:java.util.Arrays 类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。Arrays类里的方法都是静态方法可以通过Arrays.方法名()直接调用,比较经典的方法有:toString()//用于打印数组,sort(),equal(),binarySearch(),
在这里插入图片描述


在这里插入图片描述

import java.util.Scanner;
import java.util.Arrays;
class Main{
    public static void main(String args[])
    {
        int array[]={2,4,1,3,5,10,7,9,8};
        int array2[]={19,34,24,11,25,18};
        String arr=Arrays.toString(array);//用于打印数组
        Scanner input=new Scanner(System.in);
        System.out.println("array经过toString转换而来的结果是"+arr);
        Arrays.sort(array,0,array.length);//排序,左开右闭
        for(int i=0;i<array.length;i++)
        System.out.print(array[i]+" ");
        System.out.println("\n请输入你想在array查找的数字:");
        int i=input.nextInt();
        int target=Arrays.binarySearch(array,i);
        if(target<0) {
            System.out.println("该元素不存在");
        }
        else {
            System.out.println("待查找元素的下标是:"+target);
        }
        boolean flag=compare(array,array2);
        if(flag) System.out.println("array和array2是一样的");
        else System.out.println("array和array2是不一样的");
        
    }
    public static boolean compare(int arr1[],int arr2[])
    {
        boolean flag=Arrays.equals(arr1,arr2);//Arrays类里面用于比较数组的方法
        return flag;
    }
}

在这里插入图片描述

面向对象程序设计

(1)面向对象基础

在这里插入图片描述
面向过程和面向对象之间的区别
在这里插入图片描述
②类的成员
在这里插入图片描述

③对象的相关内存知识
在这里插入图片描述
具体的如下所示:在Main方法当中创建对象,PS:p1 p2是引用类型,指向实际对象的内存首地址
在这里插入图片描述

所以可以根据该引用类型引入对象数组这一概念
在这里插入图片描述

④区分成员变量(声明在类内类方法外,存在对象实例的堆里面)和局部变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

⑤方法

(1)方法的声明:例如public int fibonacci(int n),目前和C++相比多了个修饰符和捕捉异常
在这里插入图片描述
(2)方法的参数
在这里插入图片描述
(3)方法重载:存在一个以上的同名方法,只要参数列表不一样就行
在这里插入图片描述
方法重载的两不同一同:只看名字和参数列表,这两个一样方法就一样,和返回值无关,
在这里插入图片描述
(4)可变参数个数的形参的方法:例子public int digui(int ... num)
在这里插入图片描述
(5)值传递机制
在这里插入图片描述

packageimport
(1)package:放在类文件的开头,用于指出该类文件所在的目录
在这里插入图片描述
具体使用如下所示:(可以看出package后面的地址正是RecursionTest所在的文件目录
在这里插入图片描述
package的应用拓展:MVC设计模式
在这里插入图片描述
在这里插入图片描述
下列是JDK当中主要的包
在这里插入图片描述
(2)import:把其他包导入进来(告诉编译器该类文件的目录
在这里插入图片描述
⑦封装:实现类方法和成员变量的可见性范围,先记住两个极端:protected出了类不能用,public都可以用
在这里插入图片描述
具体实例如下所示:
在这里插入图片描述
在这里插入图片描述
⑧构造器:new完对象以后可以直接赋值,并且构造方法可以构成方法重载
在这里插入图片描述
具体实例如下:
在这里插入图片描述
总结:给成员变量赋值的方法:
在这里插入图片描述

(2)面向对象进阶

this关键字(this的意思就是指当前对象实例,用于调用当前类的方法和变量
在实例方法或构造器中,如果使用当前类的成员变量或成员方法可以在其前面添加 this,增强程序的可读性。不过,通常我们都习惯省略 this。 但是,当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加 this 来表明该变量是类的成员变量。即我们可以用 this 来区分,如下所示:
在这里插入图片描述
也就是说有this修饰的话就是成员变量,没有this的话就是局部变量this(形参列表)也可以用于实现同一个类内构造方法的重载。具体的情况如下所示:
this():调用本类的无参构造器
this(实参列表):调用本类的有参构造器
在这里插入图片描述

②继承:生活中的继承就是接受并且发扬光大,但在代码当中可以看成“抽取共性
在这里插入图片描述
下面是Java当中的继承的一些相关知识
在这里插入图片描述
在这里插入图片描述

当子类的对象被创建的时候,会遵循以下情况:
在这里插入图片描述
子类不能直接访问父类当中private的成员变量和方法
在这里插入图片描述

方法重写(Override):子类所继承的父类方法不能满足需求,需要对方法进行覆盖。
在这里插入图片描述
④super关键字:用于调用父类的成员变量和方法,和this一样用于防止名字混淆,还可以在方法进行重写之后再掉用父类的同名方法。
在这里插入图片描述
super也可以用super(形参列表)的形式用于调用父类的构造器来构建属于自己的构造器
在这里插入图片描述
具体的如下所示:
在这里插入图片描述
下列是子类对象实例化的调用过程以及内存分析,(重点关注“找不到方法就跑到父类去找,知道找Object为止”这段过程):
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
super和this的一种理解就是:把super替换成直系父类的名字,this替换为当前类的名字
下列是二者的总结和上述知识的代码测试(两个类Mankind和Kids):
在这里插入图片描述

public class Mankind {
    int sex;
    int salary;
    public Mankind(){

    }
    public Mankind(int sex){
        this();
        this.sex=sex;
    }
    public Mankind(int sex,int salary){
        this(sex);
        this.salary=salary;
    }
    public void manOrwoman(){
        if(this.sex==1) System.out.println("这个人类的性别是男");
        else if(this.sex==0) System.out.println("这个人类的性别是女");
    }
    public void employee(){
        if(this.salary==0) System.out.println("没有工作");
        else System.out.println("有工作");
    }
    public void setsalary(int salary){
        this.salary=salary;
    }
    public void setsex(int sex){
        this.salary=sex;
    }
}

public class Kids extends Mankind {
    int yeasold;
    public Kids(int sex,int salary,int yearsold){
        super(sex,salary);
        this.yeasold=yearsold;
    }
    public void printAge(){
        System.out.println("这个孩子的年龄是:"+this.yeasold);
    }
}

多态:多态性,是面向对象中最重要的概念,在 Java 中的体现是对象的多态性:父类的引用指向子类的对象 。子类的对象可以替代父类的对象使用。所以,一个引
用类型变量可能指向(引用)多种不同类型的对象(既可以指向该类的对象实例也可以指向该类子类的对象实例)具体如下所示:

Mankind k1=new Kids(1,20000,10);  // Mankind是Kids的父类
可以知道Kids确实是Mankind的一种,这样算是一种动态绑定,写代码更灵活

多态的好处和弊端如下:
好处:变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。
弊端:一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
接着多态的定义可以引入Java的虚方法调用:在 Java 中虚方法是指在编译阶段不能确定方法的调用入口地址,在运行阶段才能确定的方法,即可能被重写的方法

Person e = new Student(); 
e.getInfo(); //调用 Student 类的 getInfo()方法 

子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚方法,父类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。 如下所示:
在这里插入图片描述
PS:成员变量不具有这样的多态性,只有方法才满足这个性质

因为“多态”会出现父类调用不了子类独有方法的情况,所以为了解决这问题引入了向上转型与向下转型 ,想要调用子类特有的方法,必须做类型转换,使得编译通过。具体的过程如下所示:
在这里插入图片描述
具体的代码示例如下所示:向下转型可以用 instanceof来判断是否可以这样转换。

Pet pet = new Dog();      //向上转型(向父类转型)自动实现
Dog dog1=Dog(pet);   //向下转型(向子类转化)强制转换

在这里插入图片描述

⑤Object类:Java内所有类的父类,因此方法是通用的,也都可以重写。
在这里插入图片描述
Object 类当中包含的方法有 11 个。这里我们主要关注其中的 6 个:

①equals()

在这里插入图片描述
具体的代码为:p1.equals(p2),返回boolean类型如果p1==p2的话就返回true,不是的话返回false
下面是”==“和equals()方法的区别:
在这里插入图片描述
toString() :默认情况下,toString()返回的是“对象的运行时类型 @ 对象的 hashCode 值的十六进制形式" 。在进行 String 与其它类型数据的连接操作时,自动调用 toString()方法,我们直接 System.out.println(对象)默认会自动调用这个对象的toString() 。因为 Java 的引用数据类型的变量中存储的实际上时对象的内存地址,但是 Java 对程序员隐藏内存地址信息,所以不能直接将内存地址显示出来,所以当你打印对象时,JVM 帮你调用了对象的 toString()。 可以根据需要在用户自定义类型中重写 toString()方法
clone()复制的作用,具体的代码如下:Animal a2 = (Animal) a1.clone();
finalize() :当对象被回收时,系统自动调用该对象的 finalize() 方法。永远不要主动调用某个对象的 finalize 方法,应该交给垃圾回收机制调用。当某个对象没有任何引用时,JVM 就认为这个对象是垃圾对象,就会在之后不确定的时间使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize()方法。 子类可以重写该方法,目的是在对象被清理之前执行必要的清理操作。比如,在方法内断开相关连接资源
getClass():获取对象的运行时类型
hashCode():返回每个对象的 hash 值

(3)面向对象高级

static关键字:如果想让一个成员变量被类的所有实例所共享,就用 static 修饰即可,称为类变量(或类属性)。无论产生了多少对象,某些特定的数据在内存空间里只有一份

在这里插入图片描述
静态变量的一些特点:
在这里插入图片描述
静态变量的内存分析(以一个Chinense类为例子,nation为静态变量,其在方法区,可供所有对象实例共享):

class Chinese{ 
 //实例变量 
 String name; 
 int age; 
 //类变量 
 static String nation;//国籍 
 public Chinese() { 
 } 
 public Chinese(String name, int age) { 
 this.name = name; 
 this.age = age; 
 } 
  
 @Override 
 public String toString() { 
 return "Chinese{" + 
 "name='" + name + '\'' + 
 ", age=" + age + 
 ", nation='" + nation + '\'' + 
 '}'; 
 } 
}

在这里插入图片描述
同样,有static关键字修饰的方法就被称为静态方法,这里方法可以此类方法有着以下的特点:
静态方法在本类的任意方法、代码块、构造器中都可以直接被调用。
①只要权限修饰符允许,静态方法在其他类中可以通过“类名.静态方法“的方式调用。也
可以通过”对象.静态方法“的方式调用(但是更推荐使用类名.静态方法的方式)。
②在 static 方法内部只能访问类的 static 修饰的属性或方法,不能访问非 static 的结构
③静态方法可以被子类继承,但不能被子类重写
④静态方法的调用都只看编译时类型。
⑤因为不需要实例就可以访问 static 方法,因此 static 方法内部不能有 this,也不能有
super
。如果有重名问题,使用“类名.”进行区别。下面是直接调用静态方法的代码案例:

Chinese.self_introduction();          //就是这个时候当把Chinese类加载进来
public class Chinese {               //此时static修饰的静态代码块在加载进来的时候执行
    private static String country;
    private String name;
    
    static {                        
        country = "中国";
        System.out.println("静态代码块");
    }           
                           
    public static void self_introduction(){
        System.out.println("I am chinese");
    }
}

②代码块:用于初始化类的变量等等
(1)静态代码块:代码块的前面加 static,就是静态代码块,类加载的时候执行,具体的如下所示:
在这里插入图片描述
(2)非静态代码块每次创建对象实例的时候,都会执行一次。且**先于构造器执行。**具体的格式以及特点如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是给实例变量赋值的顺序:
在这里插入图片描述

final关键字
(1)final 修饰类表示这个类不能被继承,没有子类。提高安全性,提高程序的可读性。 例如:String 类、System 类、StringBuffer 类 ,具体如下:

final class Eunuch{//太监类 
 
} 
class Son extends Eunuch{//错误 
 
}

(2)final 修饰方法:表示这个方法不能被子类重写。下个例子中method不能被重写

class Father{ 
 public final void method(){ 
 System.out.println("father"); 
 } 
} 
class Son extends Father{ 
 public void method(){//错误 
 System.out.println("son"); 
 } 
} 

(3)final 修饰某个变量(成员变量或局部变量):一旦赋值,它的值就不能被修改,即常量,常量名建议使用大写字母。 final的赋值方法有三种:显示赋值,构造器赋值和代码块赋值

④抽象类与抽象方法( abstract 关键字)
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类(例如下面的几何图形类,根本无法创建对象)
我们声明一些几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长。那么这些共同特征应该抽取到一个共同父类:几何图形类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现(也就是重写)。那么父类在声明这些方法时,只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法
抽象类和抽象方法的具体的代码声明如下:
在这里插入图片描述
下面是二者的一些特征:
在这里插入图片描述
PS:不能用 abstract 修饰变量、代码块、构造器; 不能用 abstract 修饰私有方法、静态方法、final 的方法、final 的类
下面是抽象类的一次实际的代码练习

public abstract class human {
    String name;
    String xingbie;
    public human(String name,String xingbie){
        this.name=name;
        this.xingbie=xingbie;
    }
    public abstract void eat();
}

public class China extends human{
    public China(String name,String xingbie){
        super(name,xingbie);
    }
    public void eat(){
        System.out.println(name+"用筷子吃饭");
    }
}

public class America extends human{
    public America(String name,String xingbie){
        super(name,xingbie);
    }
    public void eat(){
        System.out.println(name+"用刀叉吃饭");
    }
}

 America A=new America("Lisa","girl");
 China C=new China("Mayun","boy");
 A.eat();
 C.eat();

运行的结果如下:
在这里插入图片描述

④接口(interface)也就是implement关键字:接口就是规范,定义的是一组规则,体现了现实世界中**“如果你是/要…则必须能…”的思想。继承是一个"是不是"的 is-a 关系,而接口现则是 "能不能"的has-a 关系**,具体的如下所示:
在这里插入图片描述
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class 文件,但一定要明确它并不是类,而是另外一种引用数据类型。接口的定义方式如下图所示:

public interface USB3{ 
 //静态常量 
     long MAX_SPEED = 500*1024*1024;//500MB/s 
 //抽象方法 
     void in(); 
     void out(); 
  //默认方法 
     default void start(){ 
     System.out.println("开始"); 
      }  
     default void stop(){ 
     System.out.println("结束"); 
     } 
   //静态方法 
     static void show(){ 
     System.out.println("USB 3.0 可以同步全速地进行读写操作"); 
     } 
    }

接口的使用规则如下:
①类实现接口(类似于把接口安在类上面):接口不能创建对象,但是可以被类实(implements ,类似于被继承)。 类与接口的关系为实现关系,即类实现接口。如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法。默认方法可以选择保留,也可以重写。 接口中的静态方法不能被继承也不能被重写对于接口的静态方法,直接使用“接口名.”进行调用即可,不能通过实现类的对象进行调用。对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用
在这里插入图片描述
接口的多实现(implements):之前学过,在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
在这里插入图片描述

③接口的多继承(extends): 一个接口能继承另一个或者多个接口接口的继承也使用 extends 关键字,子接口继承父接口的方法
在这里插入图片描述
⑤内部类:具体来说,当一个事物 A 的内部,还有一个部分需要一个完整的结构 B 进行描
述,而这个内部的完整的结构 B 又只为外部事物 A 提供服务,不在其他地方单独使用
,那么整个内部的完整结构 B 最好使用内部类。 内部类也有分类:
在这里插入图片描述
(1)成员内部类:如果成员内部类中不使用外部类的非静态成员,那么通常将内部类声明为静态内部类,否则声明为非静态内部类。语法的格式如下:
在这里插入图片描述
成员内部类的使用特征,概括来讲可以作为类的内部成员和一个真正的类来说明
在这里插入图片描述
成员内部类的代码调用如下图所示:
①静态内部类 (StaticInnerOuter的内部类)

//创建静态内部类实例,并调用方法 
 Outer.StaticInner inner = new Outer.StaticInner(); 
 inner.inFun(); 
 //调用静态内部类静态方法 
 Outer.StaticInner.inMethod();

②非静态内部类(这个要先实例化外部类,①不用)

//创建非静态内部类实例(方式 1),并调用方法 
 Outer outer = new Outer(); 
 Outer.NoStaticInner inner1 = outer.new NoStaticInner(); 
 inner1.inFun(); 
 
 //创建非静态内部类实例(方式 2) 
 Outer.NoStaticInner inner2 = outer.getNoStaticInner(); 
 inner1.inFun(); 

(2)局部内部类:又称“方法内部类”,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围只限于方法内部。 在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法。具体的可分为两种:

非匿名内部类
在这里插入图片描述

这种类的特点如下:
在这里插入图片描述
匿名内部类:因为考虑到这个子类或实现类是一次性的,那么我们“费尽心机”的给它取名字,就显得多余。那么我们完全可以使用匿名内部类的方式来实现,避免给类命名的问题。 最本质的还是一个类,是一个内部类,该类没有名字(但是系统会分配一个代号在内存中)。以下面的那个应用场景作例子:正常的话是声明一个内部类来实现接口A,这样的话太过啰嗦。直接匿名类的话会节省很多步骤
在这里插入图片描述

⑤枚举类:枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。枚举类的例子举不胜举, 例如星期:Monday到Sunday
下列是JDK5之前定义枚举类的方法:

public class Season {
    private final String SEASONNAME;//季节的名称
    private final String SEASONDESC;//季节的描述
    private Season(String seasonName,String seasonDesc){
        this.SEASONNAME = seasonName;
        this.SEASONDESC = seasonDesc;
    }
    //固定的几个对象实例
    public static final Season SPRING = new Season("春天", "春暖花开 ");
    public static final Season SUMMER = new Season("夏天", "夏日炎炎 ");
    public static final Season AUTUMN = new Season("秋天", "秋高气爽 ");
    public static final Season WINTER = new Season("冬天", "白雪皑皑 ");
    
    public void output(){
        System.out.println("季节的名称是"+this.SEASONNAME);
        System.out.println("季节的描述是"+this.SEASONDESC);
    }
}

实现的方式就是:①构造方法私有化 ②在类里面声明几个固定的对象实例可以直接调用,例如Season.AUTUMN.output();
JDK5之后的方法就是使用enum关键字,和上面枚举类的等价具体的如下所示:

public enum Season {
    //这几个都是常量,注意最后一个是分号,其余的是逗号
    SPRING("春天", "春暖花开 "),
    SUMMER("夏天", "夏日炎炎"),
    AUTUMN("秋天", "秋高气爽"),
    WINTER("冬天", "无比寒冷");
    
    //下面是Season的属性
    private final String SEASONNAME;//季节的名称
    private final String SEASONDESC;//季节的描述
    private Season(String seasonName,String seasonDesc){
        this.SEASONNAME = seasonName;
        this.SEASONDESC = seasonDesc;
    }
    public void output(){
        System.out.println("季节的名称是"+this.SEASONNAME);
        System.out.println("季节的描述是"+this.SEASONDESC);
    }
}

并且enum还可以实现接口,但是每一个常量都要实现接口里面的所有的抽象方法,具体的如下所示(区别仅仅在于提供固定常量实例那里而已):

interface Info{ 
 void show(); 
} 

enum Season1 implements Info{ 
 //1. 创建枚举类中的对象,声明在 enum 枚举类的首位 
 SPRING("春天","春暖花开"){ 
 public void show(){ 
 System.out.println("春天在哪里?"); 
 } 
                         }, 
 SUMMER("夏天","夏日炎炎"){ 
 public void show(){ 
 System.out.println("宁静的夏天"); 
 } 
                         }, 
 AUTUMN("秋天","秋高气爽"){ 
 public void show(){ 
 System.out.println("秋天是用来分手的季节"); 
 } 
                         }, 
 WINTER("冬天","白雪皑皑"){ 
 public void show(){ 
 System.out.println("2002 年的第一场雪"); 
 } 
                         }; 
 
 //剩下的和上面一样

⑥包装类:Java 针对八种基本数据类型定义了相应的引用类型:包装类(封装类)。有了
类的特点,就可以调用类中的方法,Java 才是真正的面向对象。
在这里插入图片描述
内存结构对比如下图所示:
在这里插入图片描述
下面是包装类的一些常用的方法:

在这里插入代码片

String类型

(1)String的特性

在这里插入图片描述
String str1 = “abc”String str2 = new String(“abc”) 这两句话也是有区别的,具体的如下:

在这里插入图片描述
具体的表现如下
在这里插入图片描述

(2)intern() 方法

在这里插入图片描述

(3)String 的常用 API

①构造器
在这里插入图片描述
具体代码如下:

//字面量定义方式:字符串常量对象 
String str = "hello"; 
 
//构造器定义方式:无参构造 
String str1 = new String(); 
 
//构造器定义方式:创建"hello"字符串常量的副本 
String str2 = new String("hello"); 
 
//构造器定义方式:通过字符数组构造 
char chars[] = {'a', 'b', 'c','d','e'};  
String str3 = new String(chars); 
String str4 = new String(chars,0,3); 
 
//构造器定义方式:通过字节数组构造 
byte bytes[] = {97, 98, 99 }; 
String str5 = new String(bytes); 
String str6 = new String(bytes,"GBK"); 

②常用方法
在这里插入图片描述
③用于查找的方法:
(11)boolean contains(xx):是否包含 xx
(12)int indexOf(xx):从前往后找当前字符串中 xx,即如果有返回第一次出现的下标,要是没有返回-1
(13)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
(14)int lastIndexOf(xx):从后往前找当前字符串中 xx,即如果有返回最后一次出现的下标,要是没有返回-1
(15)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索

④字符串截取:
在这里插入图片描述
⑤开头与结尾 :
在这里插入图片描述
⑥替换
在这里插入图片描述

(4)可变字符序列:StringBuffer、StringBuilder

因为 String 对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低,空间消耗也比较高。因此,JDK 又在 java.lang包提供了可变字符序列 StringBuffer 和 StringBuilder 类型。具体对比如下:

//情况 1: 
String s = new String("我喜欢学习"); 
//情况 2: 
StringBuffer buffer = new StringBuffer("我喜欢学习"); 
buffer.append("数学");

StringBuilder、StringBuffer 的 API
在这里插入图片描述
此外JAVA还有一些用于日期的API例如:java.lang.System 类的方法,java.util.Date ,java.text.SimpleDateFormat,java.util.Calendar(日历)

Java 比较器

在这里插入图片描述
Java 实现对象排序的方式有两种
– 自然排序:java.lang.Comparable
– 定制排序:java.util.Comparator
(1)java.lang.Comparable :继承Comparable并实现CompareTo方法,可以说是在类内部就定好了排序的方式
在这里插入图片描述
具体代码如下:

public class STU implements Comparable{
    private int id;
    private String name;
    private int score;
    private int age;

    public STU(int id, String name, int score, int age) {
        this.id = id;
        this.name = name;
        this.score = score;
        this.age = age;
    }
    //可以根据这个调换顺序
    public int compareTo(Object o){
        return ((STU)o).id-this.id;
    }
    
    //重写这个方法用于每个对象的信息
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", id="+id+
                ",age="+age+
                '}';
    }
}

        STU[] arr = new STU[5];
        arr[0] = new STU(3, "张三", 90, 23);
        arr[1] = new STU(1, "熊大", 100, 22);
        arr[2] = new STU(5, "王五", 75, 25);
        arr[3] = new STU(4, "李四", 85, 24);
        arr[4] = new STU(2, "熊二", 85, 18);
        Arrays.sort(arr);//直接用sort函数排序就行

(2)java.util.Comparator :专门写一个 Comparator类用于控制排序,可以把Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
在这里插入图片描述
重写 compare(Object o1,Object o2)方法,具体的代码如下:

public class STU implements Comparable{
    private int id;
    private String name;
    private int score;
    private int age;

    public STU(int id, String name, int score, int age) {
        this.id = id;
        this.name = name;
        this.score = score;
        this.age = age;
    }
    //可以根据这个调换顺序
    public int compareTo(Object o){
        return ((STU)o).id-this.id;
    }
    
    //重写这个方法用于每个对象的信息
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", id="+id+
                ",age="+age+
                '}';
    }
}

//定义一个实现Comparator接口的类
public class StudentScoreComparator implements Comparator { 
 @Override 
 public int compare(Object o1, Object o2) { 
 Student s1 = (Student) o1;  
 Student s2 = (Student) o2; 
 int result = s1.getScore() - s2.getScore(); 
 return result != 0 ? result : s1.getId() - s2.getId(); 
 } 
}

//
 Student[] students = new Student[5]; 
 students[0] = new Student(3, "张三", 90, 23); 
 students[1] = new Student(1, "熊大", 100, 22); 
 students[2] = new Student(5, "王五", 75, 25); 
 students[3] = new Student(4, "李四", 85, 24); 
 students[4] = new Student(2, "熊二", 85, 18); 
 
 System.out.println(Arrays.toString(students)); 
 //定制排序 ,就把这个类的实例传入sort函数即可
 StudentScoreComparator sc = new StudentScoreComparator(); 
 Arrays.sort(students, sc);

PS:使用if-else语句还可以实现基于多个变量的综合排序。比如STU对象排列综合优先考虑score而后考虑id,则可以计算s1.score-s2.score,要是不等于0直接返回,等于0的话返回s1.id-s2.id

Java 集合框架

在这里插入图片描述

(1)Collection(集合) 接口及方法

在这里插入图片描述

在这里插入图片描述
具体的方法代码如下所示:

import java.util.ArrayList; 
import java.util.Collection;

//添加
(1) add():添加一个单独的元素
Collection coll = new ArrayList();
coll.add("小李广");
coll.add("扫地僧");
coll.add("石破天");
System.out.println(coll);

(2)addall():把一个集合直接添加过来
coll2.addAll(coll);

//判断
int size():获取当前集合中实际存储的元素个数 
boolean isEmpty():判断当前集合是否为空集合 
boolean contains(Object obj):判断集合中是否存在一个与 obj 对象相同的元素 
boolean containsAll(Collection coll):即 coll 集合是否是当前集合的“子集” 
boolean equals(Object obj):判断当前集合与 obj 是否相等

//删除
void clear():清空集合元素 
boolean remove(Object obj) :从当前集合中删除第一个找到的与 obj 对象 一样的元素。 
boolean removeAll(Collection coll):从当前集合中删除所有与 coll 集合中相同的元素。
即 this = this - this ∩ coll 
boolean retainAll(Collection coll):从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与 coll 集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即 this = this ∩ coll;

//

(2)Iterator(迭代器)接口

在这里插入图片描述在这里插入图片描述

Iterator iterator = coll.iterator(); //默认指向coll的第一个元素
System.out.println(iterator.next()); //指向第二个,每次调用next方法得到一个全新迭代器
System.out.println(iterator.next()); //指向第三个元素
System.out.println(iterator.next()); //指向第四个元素
iterator.remove();                   //删除iterator所指向的元素,这样可以根据条件删除

(3)foreach 循环:一种高级的用于遍历数组和集合

foreach循环其实就是使用 Iterator 迭代器来完成元素的遍历的
在这里插入图片描述
PS:上面用Object就是万能的,用其他可能报错。具体的如下:

//遍历集合
Collection coll = new ArrayList(); 
coll.add("小李广"); 
coll.add("扫地僧"); 
coll.add("石破天"); 
for (Object o : coll) { 
   System.out.println(o); 
  }

//遍历数组
int[] nums = {1,2,3,4,5}; 
 for (int num : nums) { 
 System.out.println(num); 
 } 

 String[] names = {"张三","李四","王五"}; 
 for (String name : names) { 
 System.out.println(name); 
 } 

(4)Collection 子接口List

在这里插入图片描述
List 接口的实现类常用的有:ArrayList、LinkedList 和 Vector。 List 除了从 Collection 集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(5)Collection 子接口 Set

在这里插入图片描述
Set 主要实现类:HashSet
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值