面向过程
是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。
面向对象
是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。
类: 就是一个大框比如 c 中的结构体或者int main(){…}这个大框框都可以叫做类,类中可以有其它的小类。例如“人类”是一个类!
对象:对象是类的实例,人类“张三”是对象。
方法:相当与 c 中的函数。
关键字:
静态static:静态static修饰成员变量讲解、静态static修饰方法的讲解
类似全局变量,一经定义,不用 new 直接 类名.方法名() 调用。
静态static修饰成员变量:如果一个类中某个元素要求所有创建的对象某成员的值要相同,为了节约空间,可直接在类中用static关键字。当在对象中设置该元素的大小时,这个元素不属于该对象而属于该类,在新建一个对象时,该对象的这个元素也是上面你设置的元素大小。
静态static修饰方法:静态方法不属于对象而属于类,一般调用某类中的方法时要先定义一个对象名(假如名为dxm),再通过 “dxm.方法名()”调用,但是静态方法就可以直接“类名.方法名()”不要定义对象。无论是成员变量还是成员方法被static修饰,都推荐用类名称直接调用。在主体类中我们设置方法也是public static void name(),在main中使用直接 “name()”调用方法
注意:1.静态不能访问非静态 2.静态方法中不能使用this
静态代码块:
1.当第一次使用本类时,静态代码块执行唯一的一次。
2.静态内容总是优于非静态内容,所以会优先执行静态的内容。
《典型用途是一次性地对非静态成员变量进行赋值》
public static 类名{
static{
静态代码块的内容
}
}
Java内容:
数组创建:
1. int[] arr=new int[6];
2. int[] x={1,2,3,4};
数组长度:int len = arr.length;
this.成员变量: 当局部变量与类的成员同名时,
根据就近原则优先使用局部变量。
如果要访问本类中的成员变量,如要 this.name(成员变量名)
API:相当于现成的函数,相当于数据库,字典。
有些东西我们可以通过阅读API文档去查找
从键盘上输入:
导包:import java.util.Scanner;
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
nextInt()和next()与nextLine()区别详解:
https://blog.csdn.net/qq_40903237/article/details/95458089
匿名对象:匿名对象只能使用一次,下次再用就要再创建。
一般是 :类名称 对象名 = new 类名称
例如现在有一个类 Person
匿名对象:Person().成员变量 // 一次性用一次
Random随机数的使用方法:
导包:import java.util.Random;
Random r = new Random();//在括号内添加数字表示3:(0,3]取随机数
int num = r.nextInt(10);
System.out.printfln(num);
或者:int num = new Random().nextInt(10);
对象数组:
假设创建一个类Person
person[] t = new person[10];//定义一个对象数组
t[1] = new person(... , ...);
ArrayList类:数组-动态数组
导包:import java.util.ArrayList;
创建叫list的一个String的ArrayList类:
ArrayList<String> list = new ArrayList<>;
加入数据用到 add: list.add("古力娜扎");
如果list里面没存东西会打印出:[]
存了东西会打印:System.out.println(list); -> [古力娜扎,李云龙,...]
常用操作:
1.添加: list.add("String");
2.删除: list.remove(0); // 把下标为 0 的元素删除
3.求数组长度:int len = list.size();
4.通过下标查找目标元素:String name = list.get(2); //下标从0开始
ArrayList<>的尖括号内不能填基本类型,只能填引用类型的:
比如说 ArrayList<int>是错误的用法
但是有解决办法:用基本类型对应的包装类型
基本类型 包装类型
byte Byte
short Short
int Integer [特殊]
long Long
float Float
double Double
char Charactor [特殊]
boolean Boolean
有: ArrayList<Integer> list = new ArrayList<>();
int num = list.add(100);
(从JDK 1.5+ 支持自动装箱 自动拆箱)
自动装箱:基本类型 一〉包装类型 自动拆箱:包装类型 一〉基本类型
字符串String
创建常见的3+1种方法:
1.String str1 = new String();
2.char[] charArray = {'a', 'b', 'c'};
String str2 = new String(charArray);
3.byte[] byteArray = {97, 98, 99};
String str3 = new String(byteArray);
还有一种就直接弄:String str3 = "String";
字符串String的比较(==):Java中字符串如果一样是共用的 所以他们的地址也相同
1.对于引用类型来说,== 进行的是地址值的比较。
2.双引号直接写的字符串在常量中,new的不在池内。
=〉所以当new创建的跟直接创建的比较时是不相等的。
有直接比较字符串内容的方法(str1.equals(str2)):
参数可以是任何对象,但只有参数三字符串并且内容相同时才给true
System.out.println(str1.equals(str3));//true or false
System.out.println("Hellow".equals(str3));
推荐:"abc".equals(str); 不推荐:str.equals("abc");
字符串的获取相关方法:
长度:int len = "Hellow".length();
拼接:str3 = str1.concat(str2);
搜索指定位置的单字符:char ch = "Hellow".charAt(1);
查找参数字符串在本来字符串出现的第一次引索位置:
String str1 = "HellowWord";
int index = str1.indexOf("Word"); 没有在返回-1
字符串的截取:
str2 = str1.substring(2);//截取第二个位置到最后
str2 = str1.substring(3, 5);//截取位置3到位置4
字符串的转换相关方面:
字符串转化为字符数组:char ch[] = "Hellow".toCharArray();
字符串转换为字节数组:byte bytes[] = "Hellow".getBytes();
字符串内容替换:
String str1 = "How dou you do?";
String str2 = str1.replace("o", "*"); //"H*w d*u y*u d*?"
分割字符串的方法:
String str1 = "aaa,bbb,ccc";
string[] array1 = str1.split(",");//这个字符串数组的长度为3
//array1[0] = "aaa" array1[1] = "bbb" array[2] = "ccc";
注意:split()的括号内需要填的是“正则表达式” 如果输入 . 在括号内则无法使用,需要输入 //.才行
数组工具类Arrays
导包:import java.util.Arrays;
它是一个与数组相关的工具类,里面提供了大量的静态方法,用来实现数组常见操作。
将数组按默认格式变成字符串:
int[] arr = {1,3,2};
String str = Array.toString(arr);
按默认升序排序(数字、字符)
Array.sort(arr);
注意:如果是自定义类型,那么这个自定义的类需要有comparable或者是comparator接口的支持。
数学工具类Math
导包:import java.util.Math;
是数学相关的工具类,里面提供了大量的静态方法,完成与数学相关的操作。
取绝对值:Math.abs(-10 or -1.15 or 0); //10.0 or 1.15 or 0 有多种重载
向上取整:Math.ceil(10.1)// 11.0
想下取整:Math.floor(10.9)// 10.0
四舍五入:Math.round(20.5);// 21 (不带小数点)
圆周率: Math.PI // 代表近似的圆周率 (是double值)
继承
定义父类的格式: //跟一般的类一样
public class 父类名{
....
}
定义子类的格式:
public class 子类名 extends 父类名{
....
}
子类属于父类 子类拥有父类的内容并且也有自己不同的内容
一、如果父类中有一个num=10,子类成员变量也有一个num=20,子类方法中的局部变量num=30冲突时如何访问???
System.out.println(num); //局部变量直接访问 30
System.out.println(this.num); //本类中中的 20
System.out.println(super.num); //父类中的 10
二、如果父类和子类中的方法重名如何执行的?
创建的对象是谁的电脑就会优先用谁的方法先,但是如果子类中没有就会向上面找。
注意:无论是成员方法还是成员变量,没有的话都是向上找父类,不能向下找子类。
继承关系中子类构造方法的访问特点
1.子类构造方法中有一个默认隐藏的'super()'的调用,所以执行时会先调用父类在调用子类构造。
2.子类构造可以通过super()关键字字来调用父类构造。
3.super()父类构造调用必须是子类构造方法的第一个语句,不能一个子类构造调用多个super()构造。
总结:子类必须调用父类构造方法,不写则默认前面加个super,写了则用指定的super调用,super只能有一个必须
super的三种使用方法:
1.在子类的成员方法中,访问父类的成员变量 //super.num;
2.在子类的成员方法中,方法父类的成员方法 //super.method();
3.在子类的构造方法中,访问父类的构造方法 //public zi(){super();...}
this关键字用来访问本类内容,也有三种用法:
1.在本类的成员方法中,访问本类的成员变量。// this.num;
2.在本类的成员方法中,访问本类的另一个成员方法。// this.num();
3.在本类的构造方法中,访问本类的拎一个构造方法。 //this();
在第三种用法中要注意:
A.this(...)调用也必须是构造方法的第一个语句,唯一一个。
B.super和this两种构造调用,不能同时使用。
覆盖重写:子类中的方法名和参数名跟父类中的一样,但是内容你可以修改或添加。
1.保证父子类之间的方法名相同,参数列表也相同。
@Override 这个注释写在覆盖重写的前面可以检验对错,可以不写
2.子类的返回值必须【小于等于】父类返回值的范围。
小拓展:java.long.Object类是所有类的公共最高父类,java.long.String是它的子类。还可以写public Object(int/void) fangfa(){};
3.子类方法的权限必须【大于等于】父类方法的权限修饰符。
小拓展:public > protected > (default默认)无 > private
使用覆盖重写的时候super.show()这样在方法内添加父类方法的原来内容,在后面可以添加新的内容。
抽象方法和抽象类的使用:
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。
抽象类: 抽象方法所在的类,必须是抽象类才行,在class前面加上abstract即可。
如何使用抽象类和抽象方法:
1.不能直接创建new抽象类对象。
2.必须用一个子类来继承抽象父类。
3.子类必须覆盖重写抽象父类当中的所有抽象方法。
public abstract class Animal(){ public abstract void eat(); }
覆盖重写(实现):子类去掉抽象方法中的abstract关键字,然后补上方法体大括号。
public class Cat extends Animal(){}
4.创建子类对象进行使用。
正确:public static void main(){ Cat cat = new Cat() };
错误;public static void main(){ Animal cat = new Animal() };
接口:接口是多个类的公共规。接口是一种应用数据类型,最重要的内容是其中的抽象方法,
如果是Java7,那么接口中可以包含常量和抽象方法。
如果是Java8,那么额外包含默认按方法和静态方法。
如果是Java9,那么额外再包含私有方法。
>>=>接口的格式:
public interface 接口名称{
接口内容(要定义抽象abstract方法,也可以定义默认方法)
}
>>=>实现类的格式:
public calss 实现类名 implements 接口名{
覆盖重写抽象方法
}
(复习)抽象方法的定义格式: //pubulic跟abstract可省略
pubulic abstract 返回参数类型 方法名称();
一、接口的抽象方法的使用步骤:
1.接口不能直接使用,必须有一个“实现类”来“实现”该接口。
2.接口的实现类必须覆盖重写(实现)接口的所有的抽象方法方法。
实现:去掉abstract关键字加上方法体大括号。
3.实现类的对象进行使用。
注意事项:如果实现类没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
(跟那个抽象类抽象方法的使用一样。)
>>=>接口里定义默认方法的格式:
public default 返回参数类型 方法名称(参数列表){
方法体
}
备注:接口当中的默认方法可以解决接口升级的问题。
接口的升级是指当实现类中的某方法很多人在用的时候就不能随便去改,我们就可以在接口中写上一个默认方法,默认方法内可以进行添加新的内容。
二、接口当中静态方法的使用:
public interface 接口名称{
public static void method(){
System.out.println("这是接口的静态使用方法!")
}
}
注意事项:不能接口接口实现类的对象调用接口当中的静态方法。
正确方法:通过接口名称,直接调用其中的静态方法。
(这个跟静态成员的使用和静态方法的使用一样)
三、接口中私有方法的使用:
可能两个方法中有一段代码是重复的,我们可以再创建一个类,把这些重复的写进去,然后让这两个代码调用这一个方法就行。
1.普通私有方法:解决多个默认方法之间重复代码问题
格式:private 返回值类型 方法名(参数列表){
方法体
}
2.静态私有方法:解决多个静态方法之间代码重复问题
格式:private static 返回值类型 方法名(参数列表){
方法体
}
四、接口中常量的定义(无法修改的量)
public static final int NUM = 10; // 必须赋值,不写就是0也改不了
(其中public static final可省略,不写电脑也会给你加上)
访问它:System.out.println(接口名.NUM);
注意:在使用接口时!
1.接口是没有静态代码块和构造方法的。。
2.一个类的直接父类是唯一的,但是一个类可以同时拥有多个接口。 //public class 实现类名 implements 接口A名, 接口B名{覆盖重写方法};
3.如果实现类所实现的多个接口中存在重复的抽象方法,那么只需要覆盖重写一次即可。
4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。
5.如果实现类所实现的接口中存在重复的默认方法,那么一定要对冲突的默认方法进行重写。
6.一个类如果直接父类当中的方法与接口中的默认方法存在冲突,优先用父类当中的方法。
接口与接口之间的多继承:
1.类与类之间是单继承的,直接父类只有一个。
2.类与接口是多实现的,一个类可以有多个接口。
3.接口与接口之间是多继承的。
注意事项:
1.多个父接口的抽象方法如果重复,没有关系。
2.多个父接口的多个默认方法如果重复,那么子接口必须进行默认方法的覆盖重写(且带着 default 关键字)
多态的使用:
代码当中体现多态性其实就一句话:父类引用指向子类对象。
格式:
父类名 对象名 = new 子类名();
接口名 对象名 = new 实现类名();
子类就是一个父类:一只猫被当作动物来看待,是可以的。
用法就跟以前一样就行!!!!!!!
其实就这样理解:一个儿子相当爸爸,他就模仿他老爸,不能暴露。
当一个成员变量在子类中时直接访问是不行的,因为他不能暴露,但是他可以通过方法去访问,子类中覆盖重写,这种方式是先调用子类的,没有再向上找。
对象的向上转型,其实就是多肽的写法
格式: 父类名 对象名 = new 子类名称(); Animal animal = new Cat();
含义: 右侧创立一个子类对象,把它当作父类看待使用。 创建了一只猫,当作动物看待,没问题。
注意事项:向上转型一定安全的。从小范围转向大范围,从小范围的猫,向上转向换成更大范围的动物。
类似于: double num = 100; int ----〉 double 自动转换类型。
向下类型转换,其实就是一个[还原]的动作
格式: 子类名 对象名 = (子类名称) 父类对象
含义: 将父类对象,[还原]成本来的子类对象
当子类Cat中有方法,我们无法访问,解决办法如下:
Animal animal = new Cat(); // 本来是猫向上转型成动物
Cat cat = (Cat)animal; // 本来是猫,已经被当成了动物,还原成原来的猫
instanceof关键字的使用:当我们不知道 Animal animal 所使用的子类是谁,可以用来判断。
Animal animal = new Cat(); 还是 Animal animal = new Dog();
if(animal instanceof Dog) { Cat dog = (Dog)animal; }
if(animal instanceof Cat) { Cat cat = (Cat)animal; }
final关键字代表最终、不可改变的
常见的四种:
1.可以用来修饰一个类
这个类没有如何子类 (太监类)
public final class 类名称 {
...
}
2.可以用来修饰一个方法
被修饰的方法叫最终方法,也就是不能被覆盖重写。
注意:对于类和方法来说,abstract与final不能同时使用
3.还可以用来修饰一个局部变量
final int num = 100; 一次赋值终身不变
finnal的引用类型的变量:
final stu = new student("高圆圆");
错误: stu = new student("刘德华");
正确:stu.setName("刘德华");
final不许改变的是地址,如果地址没有被改变,那就可以用。
4.还可以用来修饰一个成员变量
对于成员变量来说,由于成员变量具有默认值,所以final之后必须手动赋值,不会再给默认值。
对于final成员变量来说,要么直接赋值,要么通过构造方法赋值,二选一。
必须保证所有重载的构造方法,都最终会对final的成员变量进行赋值。
四种权限修饰符:
public > protected > (default) > private
同一个类(我自己) Yes Yes Yes Yes
同一个包(我邻居) Yes Yes Yes No
不同包子类(我儿子) Yes Yes No No
不同包非子类(陌生人) Yes No No No
内部类的使用:汽车与发动机的关系 身体与心脏的关系
public class 外部类名称 {
public class 内部类名称 {
//...
}
//...
}
分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
注意:内外用,所以访问,外内用,需要内部类对象
============================================
如何使用成员内部类?有两种方法:
1.间接方式:在外部类的方法中,使用内部类,然后main只是调用外部类的方法。
public void method() { new Heart().beat(); }
2.直接方式:
参考: 类名称 对象名 = new 类名称();
【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】
Body.Heart xz = new Body().Heart();
拓展:如果存在内部类,文件夹储存的名中会出现 Body$Heart.class和Body.class
如果出现了重名现象,那么格式为:外部类名称.this.外部类成员变量名
public class Outer {
int num = 10;
public class Inner {
int num = 20;
public void method() {
int num = 30;
System.out.println(num); // 30 局部变量
System.out.println(this.num); // 20 内部类的成员变量
System.out.println(Outer.this.num); // 10 外部类的成员变量
}
}
}
局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。“局部”只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
定义格式:
public class Body {
public void fang_fa() {
class 局部内部类名称 {
//...
}
}
}
上面权限修饰符规则:
public > protected > (default) > private
1.外部类: public / (default)
2.成员内部类: public / protected / (default) / private
3.局部内部类: 什么都不能写!!!
局部内部类中。如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】
备注:从Java 8+开始,是要局部变量事实不变,那么final关键字可以省略。
public class Outer {
public void method() {
(final) int num = 10; // 数值不能变
//因为下面局部类的生命周期比上面的 num 长,所以当我们需要访问上面的 num 时它已经死了,所以我们这样做可以访问!
class Inner {
System.out.println(num);
}
}
}
重要:匿名内部类
当我们想用一个接口时就避免不了去写一个实现类,很麻烦。
所以我们可以用到 匿名内部类 这样就不会要去写一个实现类
如果接口的实现类(或者时父类的子类)只需要用到唯一的一次,
那么这种情况就可以省略该类的定义,而改为使用【匿名内部类】
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称 {
//覆盖重写所有的抽象方法
}
pubulic class DemoMain {
public static void main(String[] args) {
//MyInterface 为一个接口
//使用匿名内部类
MyInerface obj = new MyInterface() {
@Override
public void method() {
System void method(){
System.out.println("实现了匿名内部类");
}
}
}//.method(); 如果用匿名对象的画要这样改
obj.method(); //执行!!!
}
}
类可以作为成员变量类型:
public class Weapon {
private String code;
public Weapon() {
}
public Weapon(String code) {
this.code = code;
}
public String getCdoe(){
return code;
}
public String getCdoe(String code){
return code;
}
}
然后你就可以像使用 private String name;
private Weapon weapon;
public hero(String name, Weapon weapon) {
this.name = name;
this.weapon = weapon;
}
Object类的toString方法:在long包中
它可以返回该【对象】的字符串表示:也就是地址
Person p = new person(name, age);
String s = P.toString();//返回的是它的地址
但是呢,返回他的地址是没有意义的!所以需要覆盖重写:
@Override
public String toString() {
return "...";
}
但是又快捷键!代码+生成+toString方法!
Object类的equals方法:
它可以比较两个方法的是否相等(通过比较地址)
boolean g = a.equals(b);
但是比较地址对我们来说还是不方便:所以要覆盖重写:
也有快捷键哦!!!代码+生成+.....
Date类返回时间相关
导包:import java.util.Date;
//返回当前的时间
Date date = new Date();
System.out.println(date);//Mon Oct 25 10:00:30 CST 2021
//返回1970年6月1日的时间 这个时间为起点 如果准换为毫秒则为0
Date date1 = new Date(0L);
System.out.println(date1);//Thu Jan 01 08:00:00 CST 1970
//把日期转换为毫秒
long time = date.getTime();
System.out.println(time);//1635127230708
日期传话为字符串 与 字符串转化为日期:要用到 Dateforrmate
public static void main(String[] args) throws ParseException {
/* SimpleDateFormat 是 DateFormat 儿子,继承抽象方法的Dateformat的内容 */
SimpleDateFormat std = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");//括号内为指定格式,可以去网上查格式
Date date = new Date();
System.out.println(date);
String d = std.format(date);//format可以把 日期 格式化按照指定格式转化为 字符串(日期 -》 字符串)
System.out.println(d);
Date date1 = std.parse("2088年08月08日 15时51分54秒");//把指定格式的 字符串 转化为 日期(字符串-》日期)
System.out.println(date1);
}
Calendar类:日历类
public static void main(String[] args) {
/*
Calendar类常用的成员方法:
1.public int get(int field): 返回给定的日历字段的值(一开始为当前你电脑时间)
2.public void set(int field, int value): 将给定的日历字段设置为定制
3.public abstract void add(int field, int amount): 根据日历规则,为给定的日历字段添加或减去指定的时间量
4.public Date getTime(): 返回一个表示Calendar时间值(从历元到现在的毫秒偏移量)的Date对象。
public static final int YEAR = 1; 年
public static final int MONTH = 11; 月
public static final int DATE = 28; 月中的某一天
public static final int DAY_OF_MONTH = 1; 月中的某一天
public static final int HOUR = 22; 时
public static final int MINUTE = 30; 分
public static final int SECOND = 20; 秒
*/
//这是多态,因为Calendar是抽象类,无法直接创建对象使用,所以它内部有个静态方法叫getInstance()返回Calendar类的子类对象
Calendar c = Calendar.getInstance();
1.int k = c.get(Calendar.YEAR);
System.out.println(k);
2.c.set(Calendar.DATE,28);//设置日为 28号
c.set(2001,3,25);
3.c.add(Calendar.DATE, -1);//日 减少一天
4.Date date = getTime();
System.out.println(date);//输出一个日期
注意:西方的月是按照0~11的 我们要+1
}
System类的常用方法:
Java.long.System类中提供了大量的静态方法,可以获取与系统相关的信息或者系统级操作,在System类的API文档中,常用方法有:
1.public static long currentIimeMillis(); //返回以毫秒为单位的当前时间
public static void main(String[] args) {
long s = System.currentTimeMillis();
for(int i=1; i<=9999; i++) {
System.out.println(i);
}
long e = System.currentTimeMillis();
System.out.println("程序共耗时"+(e-s)+"毫秒");
}
2.public static void arraycopy(Object src, int srcPos, Object dest,int destPos, int length) //将数组中指定的数据拷贝到另一个数组中去。
public static void main(String[] args) {
int[] src = {1,2,3,4,5};
int[] dest = {6,7,8,9,10};
System.arraycopy(src, 0, dest, 0, 3);
//dest就变成了 {1,2,3,9,10}
}
StringBuilder:java.lang.StringBuillder类:字符串缓冲区,可以提高字符串的效率。
字符串缓冲区,可以提高字符串操作效率(看成一个长度可以变化的字符串)
底层也是一个数组,但是没有被final修饰,可以改变长度。
String的值在创建后不能更改的,字符串的底层是一个被final修饰的数组,是一个常量 private final byte[] value,所以在进行"a"+"b"的时候是再创建了一个数组,很麻烦。
构造方法:
StringBuilder() 构造一个不带任何字符的字符串生成器,起初是容量为 16 个。
StringBuilder(String str) 构造一个字符串生成器,并初始化为指定字符串。
空参构造方法:
StringBuilder bu1 = new StringBuilder();//bu1内部为空
带字符串的构造方法
StringBuilder bu2 = new StringBuilder("abc");//bu:"abc"
StringBuilder常用的方法有两个:
public StringBuilder append(...):添加任意类型的字符串形式,并返回当前对象自身。
public String toString():将当前StringBuilder对象转换为String对象。(String -> StringBuilder)
StringBuilder bu1 = new StringBuilder();
bu2 = bu1.append("123").append("abc").append("666");
// bu2 = bu1: 123abc666
String str = bu1.toString();
//把 StringBuilder 变成 String
自动装箱与自动拆箱:
简单一点说,装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
构造方法:
1.装箱: 基本数据类型 -> 包装类
(自动装箱子!)
Integer in1 = "1"; //in是包装类对象 现在是把"1"存进包装类中(String)
Integer in2 = 2; //把2存进包装类中 (int)
//System.out.println() 都是返回 int 值
2.拆箱:包装类->基本数据类型
int i = in1.intValue();
3.自动拆箱:
in = in + 2;
in是包装类,无法直接进行计算,先把in拆箱为基本数据类型,计算后再自动装箱。
静态方法:
Integer in3 = Integer.valueOf("1");//转化为Integer类型
Integer in4 = Integer.valueOf(3); //转化为Integer类型
回顾:可以去看看ArrayList<Integer> list = new ArrayList<>();
基本类型与字符串类型的相互转换
一、基本类型-》字符串类型(string)
1.基本类型的值+"" 最常用的方法(工作中常用)
2.包装类的静态方法toString(参数),不是Object类的toString()重载
String s2 = Integer.toString(100);//s2:100
3.String类的静态方法valueOf(参数)
String s3 = String.valueOf(100);//s3: 100
二、字符串(string)-》基本类型
使用包装类的静态方法parseXXX("字符串");
Integer类: Static int parseInt(String s)
int i = Integer.parseInt(s1);// i:100
Double类: Static double parseDouble(String s)
double i = Double.parseDouble(String s);// i:100.0
P213~215的发红包案例
p239
集合框架介绍:
java.util.Collection接口
所有单列集合顶层的接口,里面定义了所有单列集合共性的方法
人以的单列集合都可以使用collection接口中的方法
共性的方法:举例:Collection<String> coll = new ArrayLise<>();
public boolean add(E e):巴士顶的对象添加到当前的集合中.
coll.add("张三");
public void clear():清空集合,但是集合还是存在
coll.clear();
public boolean remove(E e):把指定对象在集合中删除
coll.remove("张三");
public boolean contains(E e):判断当前集合中是否包含给定的对象
if(coll.contains("张三"))
public boolean isEmpty():判断当前集合是否为空
if(coll.isEmpty())
public int size()
int sizes = coll.size();
public Object[] toArray():把集合中的元素储存到数组中
Object[] arr = coll.toArray();
迭代器:
Iterator接口:
//多态 接口 实现类对象
Iterator<String> it = coll.iterator();
//在Iterator接口中方法iterator可以返回接口的实现类对象
迭代器的使用步骤:
1.使用集合中的方法iterator()获取迭代器的实现类对象,使用Iterator接口接收(多态)
2.使用Iterator接口中的方法hasNext判断下还有没有下一个元素
3.使用Iterator接口中的方法next取出集合中的下一个元素
whlie(it.hasNest()) { //判断下一个是否还存在元素
String e = it.next(); //获取下一个元素 指针下移移一个
System.out.println(e);
}
增强for循环:以后只遍历就用增强for循环 把for忘了吧!
for(集合/数组的数据类型 变量名: 集合名/数组名){
sout(变量名);
}
例如:
for(int i: arr) {
System.out.println(i);
}
泛型的使用
泛型是先不知道是什么数据类型,当创建对象的时候才知道是什么类型,创建完后也中能用创建的类型。
例如:
1.含有泛型的类
public class GenericClass<E> {
private <E> name;
public <E> getName() {
return name;
}
public <E> setName(E name) {
this.name = name
}
}
GenericClas<String> fangfa = new GenericClas<String>();
fangfa.setName("Xiaoming");
2.含有泛型的方法: //<>内的字母随便
public <M> void method(M m) {
System.out.println(m);
}传递的类型是什么就是什么类型!
静态方法:
public Static <S> method(S s) {
System.out.println(s);
}
两种调用方案:推荐用类名调用,不推荐创建对象后调用.
3.定义和使用含有泛型的接口
public class GnericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
GenericInterfaceImple<Double> gi3 = new GenericInterfaceImpl2<>();
gi3.method(8.8);
泛型通配符
ArrayList<Integer> arr1 = new ArrayList<>();
ArrayList<String> arr2 = nwe ArrayList<>();
public static printarr(ArrayList<?> list) {
Iterator<?> it = new iterator();
while(it.hasNext()) {
Object o = it.Nest(); //Object可以接收任何类型
System.out.println(o);
}
}
泛型的上限与下限
类与类之间的继承关系:
Integer extends Number extends Object
String extends Objext
public static void get1(Collection<? extends Number> coll){}
//泛型的上线: 此时的泛型?必须是Nuber类型或者是Number类型的子类
public static void get2(Collection<? Super Number> coll){}
//泛型的下线:此时的泛型?必须是NUmber类型或者是Number类型的父类
List集合的介绍:可以看下上边的截图
特点:
1.有索引,包含了一些带索引的方法
2.允许储存重复元素
List接口中带索引的方法:先创建:List<String> List = new ArrayList<>(); 索引从 0 开始
public void add(int index, E element)
List.add(2); //在数组的最后一个位置加上2
List.add(3, 5); //在3的位置着里添加一个5然后把原来在这里的元素往后挤
public E get(int index) // 返回集合中指定的位置的元素
public E remove(int index) // 一处列表中指定的元素
public E set(int index, E element) //用指定元素替换指定位置的元素,返回值的更新前的元素
注意:
操作索引的时候,一定要防止索引越界异常
List的子类:LinkedList 底层是链表 (队列!!!!)
addFirst(E e) 将指定元素插入列表的开头
addLost(E e) 将指定元素插入列表的结尾
push(E e) 将元素推入此列表所表示的栈堆中
getFirst() 返回此列表的第一个元素
getLast() 返回此列表的最后一个元素
removeFirst() 移除并返回此列表的第一个元素
removeLast() 移除并返回列表的最后一个元素
pop() 从列表所表示的堆处弹出一个元素
isEmpty() 如果列表不包含元素返回false
哈希表:
一、HashSet<String> set = new HashSet<>();//尖括号内可以是 类 哦
String s1 = new String("abc");
set.add(s1);
set.add("hahaha");
如果已经有了这个哈西值那就不会再存
System.out.println(set);// 会一个个打出 无序 不允许重复
二、LinkedHashed集合特点
LinkedHashSet<String> linked = new LinkedHashe<>();// 有序 不允许重复
linked.add("aaa");
可变参数
使用前提:
当方法的列表数据已经确定,但是参数的个数没有确定,可以使用可变参数
使用格式:定义方法时使用
修饰符 返回值类型 方法名(数据类型)
Collection集合工具类方法:java.utils.Collection
ArrayList<String> list = new ArrayList<>();
1.往集合中添加一些元素:
Collections.addAll(list, "a", "b", "c"); //静态方法直接用 add只能一个个的放
2.打乱集合顺序
Collections.shuffle(list);
3.将集合中的元素按照默认方法排序(升序)
Collections.sort(list);
还可以给类排序,只要重写compareTo重写默认排序规则
注意:例如在Person类中重写
//首先要让Person类继承Comparable接口,这样才能重写CompareTo并使用
public class Person implements Comparable {...}
@Override
public int compareTo(Person o) {
//return 0;认为元素都是相同的
//自定义表规则 比较年龄
return this.getAge() - o.getAge();//升序 反过来就是降序
//this(自己) - 参数 :是升序
}
4.将集合中的元素按照指定方法排序
1.对ArrayList的基本类型集合指定排序
ArrayList<Iteger> list01 = new ArrayList<>();
list01.add(1);
list01.add(3);
list01.add(2);
注意:重写 Compator接口中的compare方法,这个方法是用来比较东西的!
Collections.sort(lsit, Comparator<Iteger>()) {
//重写比较方法
@Override
public int compare(Integer o1, Integer o2) {
//return o1-o2; //升序
return o2 - o1 //降序
}
}
2.对ArrayList类集合进行指定排序
ArrayList<Student> list02 = new ArrayList<>();
list02.add(new Student("a古力娜扎", 18));
list02.add(new Student("b迪丽热巴", 20);
注意:重写 Compator接口中的compare方法,这个方法是用来比较东西的!
Collections.sort(list02, new Comparator<Strudent>()) {
@Override
public int compare(Student o1, Student o2) {
//先按照年龄升序 年龄相同按照名字首字母升序大小
int result = o1.getAge() - o2.getAge();
if(result == 0) result = o1.getName() - o2.getName();
return result;
}
}
Comparator和Comparable的区别
Comparable:自己(this)和别(参数)比较,自己需要实现Comparable接口,重写比较的规则comparaTo方法
Comparator:相当于找一个第三方裁判,比较两个
Map集合概述:java.util.Map<k, v>集合(类似C++STL中的map:key 与 value)类也可以充当value或者key!!!
一、Map集合常用的实现类:
1.HashMap<k, v> :hashMap<k,v>集合 implements Map<k,v>接口
HashMap集合特点:底层是哈希表,查询速度特别快
2.LinkedHashMap<k, v> :LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
LinkedHashMap集合是一个无序的集合,储存元素和取出的元素的顺序可能不一致。
底层是哈希表+链表 保证迭代顺序 且他是一个有序的集合,存入取出一致
二、Map接口中常用的方法:Map<Srring, string> map = new HashMap<>();
1.put(key, value):把指定的键与指定的值添加到Map集合中
储存键值对的时候,key不重复,返回值value是null
储存键对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value
map.put("李晨","范冰冰");
2.remove(Object key):把指定的键 所对应的元素在Map集合中删除,返回被删除的元素的值
key存在,value返回被删除的值
key不存在,value返回null
map.remove("李晨");
3.get(Object key):根据指定的键,在Map集合中获取对应的值。
key存在,返回被对应的value值
key不存在,返回null
map.get("李晨");
4.set(key) :获取Map集合中所有的键,储存到Set集合中
5.set<Map.Entry<key, value>> entrySet():获取到Map集合中所有的键值对对象的集合(Set集合)
Map集合遍历键找值方式:
1.keySet()
Map<String,Integer> map = new HashMap<>();
map.put("杨颖", 168);
map.put("凌志玲", 165);
map.put("赵丽颖", 178);
Set<String> set = map.keySet();
Iterator<String> it = set.iterator();
while(it.hasNext()) {
String key = it.next();
Integer value = map.get(key);
System.out.println(key+"="+value);
}
或者
for(String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key+"="+value);
}
2.Set<map.Entry<k, v>> entrySet()
Map<String,Integer> map = new HashMap<>();
map.put("杨颖", 168);
map.put("凌志玲", 165);
map.put("赵丽颖", 178);
Set<Map.Entry<String, Integer>> set = map.entrySet();
Iterator<Map.Entry<String, Integer>> it = set.iterator();
while(it.hasNext()) {
Map.Entry<String, Integer> entry = it.next();
Integer value = entry.getValue();
System.out.println(key+"="+value);
}
或者
for(Map.Eentry<String, Integer> entry : set) {
String key = entry.getKey();
Integer value - entry.getValue();
System.out.println(key+"="+value);
}
理解:Entry是Map中一项key与value的对应,通过访问每一个键值队(Entry)可以获得对应的value和key
key = entry.getKey();
value = entry.getValue();
三、LinkedHashMap集合:
java.util.LinkedHashMap<K,V> entends HashMap<K,V>
无需,你存的时候的的顺序和取出来时候的顺序可能不一样
底层原理:
哈希表+链表(记录元素顺序)
Jdk9的新特性:一些集合只能用add、put来单个的添加,很麻烦,所以有了of
List接口,set接口,Map接口:里面增加了一个静态方法of,可以给集合一次性添加多个元素
static <E> list<E> of (E... elements)
使用前提:
当前集合中储存的元素的个数已经确定了,不在改变时使用
注意:
1.of方法只适用于list接口,Set接口,Map接口,不适用于接接口的实现类
2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常
例如:
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b");
IDEA Debug 操作;https://www.bilibili.com/video/BV1Lf4y1U7Cz?p=280&spm_id_from=pageDriver
p280
总结下
异常
如果是Exception,那么有两种解决方式:Alt + Enter
1.抛给虚拟机来处理:
一般的错误虚拟机能处理,但是如果是写错什么东西了,用虚拟机去成立就是报出错误停止运行(throw)
2.通过
它会跳过
try{
//可能出现异常的代码
}catch{
//异常的处理逻辑
拓展:再这里添加 return ;会终止代码结束程序
}
异常处理:
java异常处理的五个关键字:try,catch,finally,throw,throws
现在我们来讲解上面的两种方法:
一、抛出异常throw
当某方法内部抛出异常的时候,那么我们就必须处理这个异常对象
可以使用 throws 关键字处理这个异常对象
格式如下,讲解会写在格式的下面
//当然可以直接写Exception因为是他们所有的父类
修饰符 返回值类型 方法名(参数列表) throws AAAException,BBBException...{
throw new AAAException("产生原因");
throw new BBBException("产生原因");
....
}
就是把异常给方法的调用者,如果方法调用者也出现了异常,那么就再给调用者添加个throw直到给JVM处理,但是必须先声明这个异常,如果我事先声明或者事先不知道,那就搞不了了。
注意:
1.throw关键字必须写在方法声明处
2.throw关键字后面声明的异常必须是Exception或者是它的子类
3.方法内部如果抛出了多个异常对象,那么throws后面必须也声明多个异常
如果抛出多个异常的方法有父子类的关系,那么直接声明父类异常即可。
4.调用一个声明抛出异常的方法,我们就必须处理声明的异常
要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
要么try...catch自己处理异常
二、try....catch
就是自己来处理 try中代码是可能出现异常的代码,
如果try中有异常,那么执行catch中异常处理逻辑去处理异常,
如果try中没有异常,那么就不会处理catch中的代码。
不管有没有异常,处理完后都会继续处理try...catch后面的代码
finally代码块
有一些特定的代码无论是否异常,都要执行,另外,因为异常会引发程序跳转,导致有些语句执行不到,而finally就是解决这个问题的。finally中的代码一定会执行。当然它也是用来关闭关联文件资源的,最后不管程序结果如何,都必须把这个资源关闭掉。后面学习的 IO 流中将学到。
try{
//可能产生异常的代码
}catch(..){
//处理异常的逻辑
}finally{
//无论是否出现异常都会执行
}
尽量不要再finally中写return 因为return返回的时fanally中的语句 例如finally中也有个int a = 100,那么return a;会返回finally中的a而不是try中的
注意事项-多异常的捕获处理
1.多个异常分别处理
2.多个异常一次捕获,多次处理
3.多个异常一次捕获,一次处理
例如:
int[] arr = {1,2,3};
System.out.println(arr[3]);//越界异常
List<Integer> list = List.of(1,2,3);
System.out.println(list.get(3));//越界异常
方法一:
分别try..catch
方法二:
try{
}catch(A){
...
}catch(B){
...
}
A是B的子类 如果有父子类关系 父类放后面(因为多肽有影响)
方法三:
try{
}catch(B){
...
}
B是父类!用多肽可以一次处理!
注意:父类什么异常,子类什么异常
子类重写父类方法时,抛出和父类相同的异常
子类重写父类方法时,父类有异常,抛出父类异常的子类
子类重写父类方法时,父类没有异常,子类也没有异常,不抛出异常,若此时子列抛出了异常,只能捕获处理,不能抛出。
java提供的异常类,不够我们用时,选哟自己定义一些异常类
格式:
public class XXXException(RuntimeException){
添加一个空参数的构造方法
添加一个带异常消息的构造方法
}
注意:1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须继承Exception或者时RuntimeException
继承Exception:那么自定义的类异常就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws要么try..catch
继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机中断处理
▲记住!!!!RuntimeException是Exception的子类,
继承RuntimeException,不用写try..catch或者throw,
有异常一定会被虚拟机自动中断,
继承Exception,用try..catch可以执行下去,用throw会中断
例如:
public RegisterException extends Exception{
public RegisterException(){
super();
}
public RegisterException(String message){
super(message);
}
}
293