javaSE知识梳理(一)
一.面向对象编程
1.面向对象的基本元素:类(class)和对象
①类的声明
语法格式:
[修饰符] class 类名{属性声明;方法声明;
}
②对象的创建(new)
语法格式:
//方式1:给创建有名对象
类名 对象名 = new 类名();//方式2:创建匿名对象
new 类名()
③对象调用属性和方法
语法格式:
对象名.属性
对象名.方法
④匿名对象
- 如果一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
- 我们经常将匿名对象作为实参传递给一个方法调用。
2.对象的内存解析:
①内存分为三个区间(目前我们只需要了解这么多)
堆 :储存对象实例(new出来的对象)。
栈:存储局部变量(boolean、byte、char、short、int、float、long、double)、对象引用(对象在堆内存的首地址)。
方法区:储存类信息、常量、静态变量、即时编译器编译后的代码等数据。
②图解
③注意事项
1.创建一个类的多个对象(比如p1、p2),则每个对象都拥有当前类的一套"副本"(即属性)。当通过一个对象修改其属性时,不会影响其它对象此属性的值。
2.当声明一个新的变量使用现有的对象进行赋值时(比如p3 = p1),此时并没有在堆空间中创建新的对象。而是两个变量共同指向了堆空间中同一个对象。当通过一个对象修改属性时,会影响另外一个对象对此属性的调用。
总结:所以一定要理清楚赋值和创建对象
3.类的成员之一:成员变量(属性)
①成员变量vs局部变量
声明成员变量的要求:必须在类中,方法外;可以显式赋值,也可以不赋值,使用默认值;储存在堆中;
声明局部变量的要求:必须在方法的内部声明,形参,代码块局部变量;储存在栈中;必须手动初始化;
②对象属性的默认初始化
4.类的成员之二:方法(函数)
①方法的声明
语法格式:
[修饰符] 返回值类型 方法名([形参列表])[throws 异常列表]{方法体的功能代码
}
②调用实例的方法
语法格式:
对象.方法名([实参列表])
使用的注意点:必须先声明后使用,且方法必须定义在类的内部。
③类里面,的方法可以直接相互调用
④方法调用的内存解析
1.方法 没有被调用 的时候,都在 方法区 中的字节码文件(.class)中存储。
2.方法 被调用 的时候,需要进入到 栈内存 中运行。方法每调用一次就会在栈中有一个 入栈 动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值。
3.当方法执行结束后,会释放该内存,称为 出栈 ,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。
4.再谈方法
①方法的重载
方法名相同,只需要参数列表必须不同(参数个数或参数类型)。与修饰符、返回值类型无关。
②可变个数的形参
解释:形参的类型可以确定,但是形参的个数不确定,那么可以考虑使用可变个数的形参。
语法格式:
方法名(参数的类型名 ...参数名) //这是新的写法,之前用的时数组。
注意事项:
1.在一个方法的形参中,最多只能声明一个可变个数的形参,且需要放在形参声明的最后。
2.方法参数部分指定类型的参数个数是可变多个:0个,1个或多个。3.可变个数形参的方法与同名的方法之间,彼此构成重载。
4.可变参数方法的使用与方法参数部分使用数组是一致的,二者不能同时声明,否则报错。
③方法的参数传递机制
Java里方法的参数传递方式只有一种: 值传递 。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
所以在传递基本数据类型的时候,在方法里面对变量更改,是无法影响实参的;而引用数据类型传的是堆中的一串地址,所以我们改变引用数据类型的时候,是会影响实参的。
5.包(package),导入(import)
①package
语法格式:
package 顶层包名.子包名 ;
注意事项:
1.一个源文件只能有一个声明包的package语句。
2.package语句作为Java源文件的第一条语句出现。若缺省该语句,则指定为无名包。
3.包对应于文件系统的目录,package语句中用 “.” 来指明包(目录)的层次,每"."一次就表示一层文件目录。
为了使用定义在其它包中的Java类,需用import语句来显式引入指定包下所需要的类。相当于 import语句告诉编译器到哪里去寻找这个类 。
②import
语法格式:
import 包名.类名;
注意事项:
1.import语句,声明在包的声明和类的声明之间。
2.如果需要导入多个类或接口,那么就并列显式多个import语句即可
3.如果使用 a.* 导入结构,表示可以导入a包下的所有的结构。举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
4.如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
5.如果已经导入java.a包下的类,那么如果需要使用a包的子包下的类的话,仍然需要导入。
6.如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的是哪个类。
6.封装性(private)
①类的权限修饰符:public,缺省
解释说明:
1.用public修饰的类可以在其他的包中访问,且一个包中只能有一个public类。
2.缺省的则不可以在其它包中被访问。
②成员变量、成员方法、构造器、成员内部类的权限修饰符:public 、 protected 、 缺省 、 private 。
修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
---|---|---|---|---|
private | √ | × | × | × |
缺省 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
7.类的成员变量之三:构造器
构造器其实也是一种特别的方法:他用于构造对象。
语法格式:
[修饰符] class 类名{[修饰符] 构造器名(){// 实例初始化代码} [修饰符] 构造器名(参数列表){// 实例初始化代码}
}
注意事项:
1. 构造器名必须与它所在的类名必须相同。
2.它没有返回值,所以不需要返回值类型,也不需要void。3.构造器的修饰符只能是权限修饰符。
4.当我们没有显式的声明类中的构造器时,系统会默认提供一个无参的构造器并且该构造器的修饰符默认与类的修饰符相同。
5.当我们显式的定义类的构造器以后,系统就不再提供默认的无参的构造器了,所以当我们定义了有参的构造器之后,如果我们需要在调用无参的构造器,我们需要自己写,然后构造器是可以重载的。
8.this
①实例方法或构造器中使用当前对象的成员
情景提出:如果在一个类中定义的成员变量和方法的形参同名,我们写下名字的时候我们就无法辨别是那个,所有我们就需要this关键字,来调用本类中成员变量,所以可以用来辨别是成员变量还是局部变量。
语法格式:
this.局部变量名
②同一个类中构造器互相调用
语法格式:
this() //调用本类的无参构造器
this(实参列表) //调用本类的有参构造器
注意事项:
1.this()和this(实参列表)只能声明在构造器首行。
9.继承(extends)
语法格式:
[修饰符] class 类A {...
}
[修饰符] class 类B extends 类A {...
}
继承中的细节说明:
1.当子类对象被创建时,在堆中给对象申请内存时,就要看子类和父类都声明了什么实例变量,这些实例变量都要分配内存。
2.当子类对象调用方法时,编译器会先在子类模板中看该类是否有这个方法,如果没找到,会看它的父类甚至父类的父类是否声明了这个方法,遵循 从下往上 找的顺序,找到了就停止,一直到根父类都没有找到,就会报编译错误。
注意事项:
1.子类不能直接访问父类中私有的(private)的成员变量和方法。
2.支持一个父类可以被多个子类继承。3.java中声明类,如果没有显示声明他的父类的时候,则默认继承java.lang.Object这个类
10.方法的重写
子类中的方法名和父类中的方法名相同且形参也相同,就构成了重写。
重写的一些注意事项:
1.子类重写的方法的返回值类型 不能大于 父类被重写的方法的返回值类型。(子类<父类)(返回值是void的话必须相同)
2.子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限。但是注意父类的私有方法不能重写,跨包的父类缺省的方法也不能重写,因为他们都不提供被访问。
3.子类方法抛出的异常不能大于父类被重写方法的异常。
4.此外,子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
11.再谈四种权限修饰符号
protected是继承中新产生的一种权限修饰符。
修饰符 | 本类 | 本包 | 其他包子类 | 其他包非子类 |
---|---|---|---|---|
private | √ | × | × | × |
缺省 | √ | √(本包子类非子类都可见) | × | × |
protected | √ | √(本包子类非子类都可见) | √(其他包仅限于子类可见) | × |
public | √ | √ | √ | √ |
注意事项:
1.成员权限修饰符>类的权限修饰符也没有意义(这点很容易理解)
12.super
①子类中调用父类被重写的方法
改关键字的作用:如果我们子类已经重写了父类的方法,但是还是想要调用父类中的该方法这时候我们就需要super这个关键字了。
语法格式:
super.父类的方法名
注意事项:
1.前面没有super或者没有this和有this:先从子类找匹配方法,如果没有,再从直接父类找,再没有,继续往上追溯。
2.前面有super:从当前子类的直接父类找,如果没有,继续往上追溯。
②子类中调用父类中同名的成员变量
super.父类的属性名
注意事项:
1.变量前面没有super.和this:在构造器、代码块、方法中如果出现使用某个变量,先查看是否是当前块声明的局部变量;如果不是局部变量,先从当前执行代码的本类去找成员变量;如果从当前执行代码的本类中没有找到,会往上找父类声明的成员变量(权限修饰符允许在子类中访问的)
2.变量前面有this:通过this找成员变量时,先从当前执行代码的本类去找成员变量;如果从当前执行代码的本类中没有找到,会往上找父类声明的成员变量(权限修饰符允许在子类中访问的)
3.变量前面super:通过super找成员变量,直接从当前执行代码的直接父类去找成员变量(权限修饰符允许在子类中访问的);如果直接父类没有,就去父类的父类中找(权限修饰符允许在子类中访问的)
③子类构造器中调用父类的构造器
语法格式
super(形参)
1.子类继承父类时,不会继承父类的构造器。只能通过super调用父类指定的构造器。
2.如果要显示调用父类的构造器必须要写在首行(这点和this调用构造器时类似)(因为this和super都必须写在首行所以这两个只能写其中一个)。
3.如果在子类构造器的首行既没有显示调用this或者super,则子类的构造器默认调用父类的空参构造器。(所以得出结论:子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器)(所以在子类中我们一般会显示调用this或者super)。
13.子类对象实例化的过程
①先加载父类在加载子类
这个很好理解因为this和super都写在第一行嘛。
14.多态性:衍生出了,抽象和接口,instanceof
①使用要求和特点(重要)
形成多态的条件:① 类的继承关系 ② 方法的重写(必须要重写意味着:不能调用用子类添加的新的方法,也恰好说名了,多态的弊端)。③通过父类的引用调用重写的方法。
多态的特点:编译时看左边,运行时看右边(很重要一定要理解清楚这句话)。
②使用场景(一份代码一个文件)
public class Pet {private String nickname; //昵称public String getNickname() {return nickname;} public void setNickname(String nickname) {this.nickname = nickname;} public void eat(){System.out.println(nickname + "吃东西");} }
public class Dog extends Pet {//子类重写父类的方法public void eat() {System.out.println("狗子" + getNickname() + "啃骨头");} //子类扩展的方法public void watchHouse() {System.out.println("看家");} }
1.方法的形参声明体现多态
public class Person{private Pet pet;public void adopt(Pet pet) {//形参是父类类型,实参是子类对象this.pet = pet;} public void feed(){pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同} }
public class TestPerson {public static void main(String[] args) {Person person = new Person();Dog dog = new Dog();dog.setNickname("小白");person.adopt(dog);//实参是dog子类对象,形参是父类Pet类型,这里体现了多态person.feed();} }
2.方法返回值类型体现多态
public class PetShop {//返回值类型是父类类型,实际返回的是子类对象,这里返回值体现了多态public Pet sale(String type){switch (type){case "Dog":return new Dog();} return null;} }
public class TestPetShop {public static void main(String[] args) {PetShop shop = new PetShop();Pet dog = shop.sale("Dog");dog.setNickname("小白");dog.eat();} }
③多态的好处和弊端
好处:变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。
弊端:一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法,于是就有了下面的解决方案。
④向上转型与向下转型
向上转型(多态):子类变成了父类,所以叫做向上,而且向上转型是自动完成的。
多态中出现了一个问题:不能调用子类拥有,而父类没有的方法,所以我们这里就需要向上转型。
向下转型: 当左边的变量的类型(子类)<右边对象/变量的编译时类型(父类),我们就称为向下转
语法格式:
子类类型 变量名 = (子类类型)编译是父类但实际确是子类变量 //这点和强制转换有点类似
然后我们这时候我们在用上面的变量就可以调用 子类拥有,而父类没有的方法了。
但是我们这里强行转换容易出现问题,因为编译是父类但实际是子类变量 的子类可能和我们要强制转换的子类不一样就会导致出错,所以我们这里引出了一个新的关键字 instanceof
instanceof关键字的语法格式:
对象a instanceof 数据类型A //检验对象a是否是数据类型A的对象,返回值为boolean型
但是我们这里还需要注意一点:如果对象a属于类A的子类B,a instanceof A值也为true。
//然后下面这段代码是来测试instanceof关键字的
public class Main {public static void main(String[] args) {Pet pet = new Dog();pet.setNickname("111");if(pet instanceof Dog) { //pet是Dog的对象所以运行通过System.out.println("11111");}if(pet instanceof Pet){ //pet是Pet的子类对象所以运行通过System.out.println("22222");}}
}
⑤多态的其他注意事项
1.成员变量没有多态性
2.子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚方法。(应该和c++中的虚函数差不多一个意思)
14.object
1.objiect是所有类的祖先类
2.如果一个类没有特别指定父类,那么默认则继承自Object类。
object的类方法:
①equals()
equals 和 ==:
1.在==中,基本类型两个变量值相等为true,在引用类型中指向同一个对象时才会返回true。
2.equals中,对类File、String、Date及包装类来说比较的是值相等,其实在object实现的是==来判断,但是这些类都重写equals,所以可以用来比较值相等,所以我们一般在比较自己写的类的时候都要自己重写equals。
②toString()
Person now=new Person(); System.out.println(now); //同等于下面的代码 System.out.println(now.toString());
对于上面的代码我们没有重写 toString 的时候打印的对象的地址值(其实也不算是地址吧),我们重写之后一般就是用来打印对象的内容的,像String,File,Date或包装类等Object的子类,它们都重写了Object类的toString(),在调用toString()时,返回当前对象的实体内容。
15.静态修饰符号(static)
用static修饰的特点:随着类的加载而加载,优先于对象存在;修饰的成员被所有对象所共享;访问权限允许时,可不创建对象,直接被类调用。
①静态成员变量(或类变量,类属性)
//调用方法
对象.静态变量
类名.静态变量
②静态方法
//调用方法
对象.静态方法
类名.静态方法
静态方法的特点:
1.在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
2.静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用。
3.静态方法可以被子类继承,但不能被子类重写。
4.因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。如果有重名问题,使用“类名.”进行区别。
16.类的成员之四:代码块
语法格式:
【修饰符】 class 类{static{静态代码块}
}
①静态代码块
作用:
1.可以对类的属性、类的声明进行初始化操作。
2.不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。(一般是给静态成员变量初始化的)
3.静态代码块的执行要先于非静态代码块。
4.静态代码块随着类的加载而加载,且只执行一次。
②非静态代码块(构造代码块)
作用:
1.和构造器一样,也是用于实例变量的初始化等操作。
2.可以对类的属性、类的声明进行初始化操作(构造代码块一般用于初始化实例成员变量)。
3.除了调用非静态的结构外,还可以调用静态的变量或方法。
4.每次创建对象的时候,都会执行一次。且先于构造器执行。
③实例变量的赋值顺序
16.final关键字:最终的,不可更改的
①修饰类
表示这个类不能被继承,没有子类。提高安全性,提高程序的可读性。
②修饰方法
表示这个方法不能被子类重写。
③修饰变量
final修饰某个变量(成员变量或局部变量),一旦赋值(这里是赋值不是初始化,说明可以在声明的时候不赋值,而是在之后赋值,赋值的位置有:显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值),它的值就不能被修改,即只能赋值一次。
17.抽象类和抽象方法(abstract)
抽象类的语法:
[权限修饰符] abstract class 类名{
}[权限修饰符] abstract class 类名 extends 父类{
}
抽象方法的语法:
[其他修饰符] abstract 返回值类型 方法名([形参列表]);
//注意没有方法体
注意事项:
1. 抽象类不能创建对象。
2. 抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
18.接口(interface)
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型,接口没有构造器和静态代码块。
①语法格式
[修饰符] interface 接口名{// 接口的成员列表:公共的静态常量公共的抽象方法公共的默认方法(JDK8以上)公共的静态方法(JDK8以上)私有方法(JDK9以上) }
②接口的成员说明
在JDK8.0 之前,接口中只允许出现:
(1)公共的静态的常量:其中 public static final 可以省略。
(2)公共的抽象的方法:其中 public abstract 可以省略。
在JDK8.0 时,接口中允许声明 默认方法 和 静态方法 :
(3)公共的默认的方法:其中public 可以省略,建议保留,但是default不能省略。
(4)公共的静态的方法:其中public 可以省略,建议保留,但是static不能省略。
③类实现接口
//接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法 public class 类名称 implements 接口名称{// ... }
④接口的多实现
//一个类只能继承一个父类,而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现,并且一个类能继承一个父类,同时实现多个接口。 [修饰符] class 实现类 extends 父类 implements 接口1,接口2,接口3...{// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写 }//注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
⑤接口的多继承
一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。 public interface 子接口 extends 父接口1,父接口2... {//.... }
⑥接口与实现类对象构成多态引用
实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间, 也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类 对象实现的方法体。
⑧使用接口的静态成员
接口不能直接创建对象,但是可以通过接口名直接调用接口的静态方法和静态常量。
⑦使用接口的静态方法和非静态方法(这个好像不常用)1.使用接口的静态方法
对于接口的静态方法,直接使用“ 接口名. ”进行调用即可,也只能使用“接口名."进 行调用,不能通过实现类的对象进行调用。
2.使用接口的非静态方法
对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用接口不能直接 创建对象,只能创建实现类的对象。
⑧还有一些命名冲突问题实在是太复杂了,开发一般也不会这样写,而且写起来语法我看起来非常的怪,所以这里就不在讲了。
19.类的成员之五:内部类(语法很特别)
①成员内部类
成员内部类分为静态局部内部类和非静态局部内部类:
1.创建内部类
[修饰符] class 外部类{[其他修饰符] [static] class 内部类{} }
2.实例化内部类
// 实例化静态内部类 外部类名.静态内部类名 变量 = 外部类名.静态内部类名(); 变量.非静态方法(); // 调用里面的方法//实例化非静态内部类 外部类名 变量1 = new 外部类(); // 需要先创建非静态内部类 外部类名.非静态内部类名 变量2 = 变量1.new 非静态内部类名(); 变量2.非静态方法();
3.内部类中访问外部类的成员
// 静态内部类访问外部类的成员 //如果是静态的可以直接访问 //如果是非静态的需要创建外部类的对象才可以访问//非静态内部类访问外部类的成员 //内部类想调用他外面这一层类的方法或者变量: //外部类名.this.方法名/成员变量 //这个写法我自己就感觉非常奇怪
③匿名内部类( 也可以叫做匿名子类)(这两点非常重要一定要理解重要)
1.使用
new 父类([实参列表]){重写方法... } //这个好像不可以用父类接受new 父接口(){重写方法... } //这个好像可以被父接口变量接受
2.个人感觉这有点像继承/实现过来重写了一下,但是不知道理解的是不是对的。
20.包装类
①基本的数据类型和包装类
基本数据类型 | 包装类 | 缓存对象 |
---|---|---|
byte | Byte | -128 ~ 127 |
short | Short | -128 ~ 127 |
int | Integer | -128 ~ 127 |
long | Long | -128 ~ 127 |
float | Float | 没有 |
double | Double | 没有 |
char | Character | 0 ~ 127 |
boolean | Boolean | true 和 false |
②装箱和拆箱
1.装箱和拆箱
int i = 10;// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中 Integer i1 = Integer.valueOf(i); Integer i2 = new Integer(i);// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中 int j = i1.intValue();
2.自动装箱和拆箱
int i = 10;Integer i1 = i; // 自动装箱 Integer i2 = (Integer)i; // 自动装箱int m = i1; // 自动拆箱 int n = (int)i1; // 自动拆箱
③还有其他知识不过太细节感觉没啥用这里就不在过多的赘述了。
21.注解
目前以我的了解是用来帮助帮助开发的一些规范的,可以提升效率,可以防止代码犯一些低级错误,现在可以先不用了解。
二.异常处理
编译时异常:
在程序编译期间发生的异常,称为编译时异常,也称为受检查异常
运行时异常:
在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常。 RunTimeException以及其子类对应的异常,都称为运行时异常。
①异常的抛出
1.由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,那么针对当前代码,就会在后台自动创建一个对应异常类的实例对象并抛出。
2.由开发人员手动创建
throw new 异常类名(参数);
注意事项:
- 如果抛出编译时异常类型的对象,需要使用throws或者try...catch处理,否则编译不通过(这里必须要理解,我刚开始这里听的非常迷糊)。
- 抛出的异常必须是Throwable或其子类的实例
- 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的.
②异常的捕获
①try-catch-finally捕获异常
try{...... //可能产生异常的代码 } catch( 异常类型1 e ){...... //当产生异常类型与异常类型1相同或是异常1的子类的时候,异常被捕获。 } catch( 异常类型2 e ){...... //当产生异常类型与异常类型2相同或是异常2的子类的时候,异常被捕获。 } finally{...... //无论是否发生异常,都无条件执行的语句 }
finally的作用:finally中的代码一定会执行的,一般在finally中进行一些资源清理的扫尾工作。
②throws捕获异常
处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常.
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{...}
③异常的处理流程
1.程序先执行 try 中的代码
2.如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
3.如果找到匹配的异常类型, 就会执行 catch 中的代码
4.如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
5.无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
6.如果上层调用者也没有处理的了异常, 就继续向上传递.
7.一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.
④自定义异常类
自定义异常前需要注意的点;
1.自定义异常通常会继承自 Exception 或者 RuntimeException。
2.建议大家提供至少两个构造器,一个是无参构造,一个是(String message)构造器。
3.自定义的异常只能通过throw抛出。//代码示例 class UserNameException extends Exception {public UserNameException(String message) {super(message);} }
三.泛型
1.定义泛型类
语法:
// 示例一: class 泛型类名称<类型形参列表> {// 这里可以使用类型参数 } class ClassName<T1, T2, ..., Tn> { }// 示例二: class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {// 这里可以使用类型参数 } class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {// 可以只使用部分类型参数 }
2.泛型类的使用
语法:
泛型类<类型实参> 变量名; // 定义一个泛型类引用 new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
示例:
MyArray<Integer> list = new MyArray<Integer>(); // 也可以写成下面这样,原因是 类型推导 MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!
3.泛型是如何编译的
擦除机制:在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。
4.泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。
语法:
class 泛型类名称<类型形参 extends 类型边界> {... }
示例:
public class MyArray<E extends Number> {... }// 只接受 Number 的子类型作为 E 的类型实参 MyArray<Integer> l1; // 正常,因为 Integer 是 Number 的子类型 MyArray<String> l2; // 编译错误,因为 String 不是 Number 的子类型
了解: 没有指定类型边界 E,可以视为 E extends Object
复杂示例:(这个还是要看一看,但是感觉不是很重要)
public class MyArray<E extends Comparable<E>> {... } // E必须是实现了 Comparable 接口的 // 然后E就可以在这个类里面比较大小的
5.泛型方法
语法:
方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { }
示例:
public class Util {//静态的泛型方法 需要在static后用<>声明泛型类型参数public static <E> void swap(E[] array, int i, int j) {E t = array[i];array[i] = array[j];array[j] = t;} }
6.通配符
①通配符的使用
class Message<T> {private T message ;public T getMessage() {return message;}public void setMessage(T message) {this.message = message;} }public class TestDemo {public static void main(String[] args) {Message<Integer> message = new Message() ;message.setMessage(55);fun(message);} // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改public static void fun(Message<?> temp){//temp.setMessage(100); 无法修改!System.out.println(temp.getMessage());} }
②通配符的上界,不能进行写入数据,只能进行读取数据。
语法:
<? extends 上界> <? extends Number>//可以传入的实参类型是Number或者Number的子类
这个图片表示:泛型的内容可以是这些类: (Message<? extends Fruit> temp)
示例:
class Food { } class Fruit extends Food { } class Apple extends Fruit { } class Banana extends Fruit { } class Message<T> { // 设置泛型private T message ;public T getMessage() {return message;}public void setMessage(T message) {this.message = message;} } public class TestDemo {public static void main(String[] args) {Message<Apple> message = new Message<>() ;message.setMessage(new Apple());fun(message);Message<Banana> message2 = new Message<>() ;message2.setMessage(new Banana());fun(message2);} // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改// 可以想象,如果传进来的是GreenApple类,我们要改成 Banana,Apple都是存在问题的public static void fun(Message<? extends Fruit> temp){//temp.setMessage(new Banana()); //仍然无法修改!//temp.setMessage(new Apple()); //仍然无法修改!System.out.println(temp.getMessage());} }
③通配符的下界,不能进行读取数据,只能写入数据。
语法:
<? super 下界> <? super Integer>//代表 可以传入的实参的类型是Integer或者Integer的父类类型
这个图片表示:泛型的内容可以是这些类: (Plate<? super Fruit> temp)
示例:
class Food { } class Fruit extends Food { } class Apple extends Fruit { } class Plate<T> {private T plate ;public T getPlate() {return plate;}public void setPlate(T plate) {this.plate = plate;} } public class TestDemo {public static void main(String[] args) {Plate<Fruit> plate1 = new Plate<>();plate1.setPlate(new Fruit());fun(plate1);Plate<Food> plate2 = new Plate<>();plate2.setPlate(new Food());fun(plate2);}public static void fun(Plate<? super Fruit> temp){// 此时可以修改!!添加的是Fruit 或者Fruit的子类temp.setPlate(new Apple());//这个是Fruit的子类temp.setPlate(new Fruit());//这个是Fruit的本身//Fruit fruit = temp.getPlate(); 不能接收,这里无法确定是哪个父类System.out.println(temp.getPlate());//只能直接输出} }
相关文章:
javaSE知识梳理(一)
一.面向对象编程 1.面向对象的基本元素:类(class)和对象 ①类的声明 语法格式: [修饰符] class 类名{属性声明;方法声明; } ②对象的创建(new) 语法格式: //方式1:给创建有名对象 类名 对象名 new 类名();//方式2࿱…...
k8s statefulset pod重启顺序
在 Kubernetes 中,StatefulSet 的 Pod 重启顺序由以下规则和机制决定: 1. StatefulSet 的核心设计原则 StatefulSet 旨在管理有状态应用,其核心特性包括: 稳定的唯一标识:Pod 名称格式为 <statefulset-name>-&…...
记录学习的第十九天
现在这篇是记录一下4.1的学习。今天还没开始。 这篇是关于简单的动态规划的题目,思路比较清晰类似。 在这里先说一下有关动态规划的四个步骤: 1.确定子问题 2.确定dp数组的递推关系(dp数组也叫子问题数组) 3.确定求解的计算顺序 4.空间优化(初学者可…...
【实用技巧】电脑重装后的Office下载和设置
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言下载设置总结互动致谢参考目录导航 前言 在数字化办公时代,Windows和…...
模拟集成电路设计与仿真 : Mismatch
前情提要 此為作者針對 mismatch ,進行資料統整,以便日後查詢原理 1. Mismatch (失配) random offset 靜態消除 : trimming動態消除 : auto zero ,choppingCMRRlinearity 理想差動對只有奇次諧波,沒有偶次諧波,但 mismatch 會引入殘存的偶次諧波PSRR2. Input Offset Volt…...
深度学习查漏补缺:4.数据分布的度量
一、数据分布差异的度量 1.KL散度(Kullback-Leibler Divergence) 什么是KL散度? KL散度是一种用来衡量两个概率分布之间差异的工具。你可以把它想象成一个“距离测量器”,但它不是传统意义上的距离(比如两点之…...
银河麒麟V10 aarch64架构安装mysql教程
国产操作系统 ky10.aarch64 因为是arm架构,故选择mysql8,推荐安装8.0.28版本 尝试8.0.30和8.0.41版本均未成功,原因不明☹️ 1. 准备工作 ⏬ 下载地址:https://downloads.mysql.com/archives/community/ 2. 清理历史环境 不用管…...
【NLP 52、多模态相关知识】
生活应该是美好而温柔的,你也是 —— 25.4.1 一、模态 modalities 常见: 文本、图像、音频、视频、表格数据等 罕见: 3D模型、图数据、气味、神经信号等 二、多模态 1、Input and output are of different modalities (eg: tex…...
[NCTF2019]Fake XML cookbook [XXE注入]
题目源代码 function doLogin(){var username $("#username").val();var password $("#password").val();if(username "" || password ""){alert("Please enter the username and password!");return;}var data "…...
I²C总线高级特性与故障处理分析
IC总线高级特性与故障处理深度分析 目录 1. IC基础回顾 1.1 IC通信基本原理1.2 IC总线时序与协议1.3 寻址方式与读写操作 2. IC高级特性 2.1 多主机模式2.2 时钟同步与伸展2.3 高速模式与Fast-mode Plus2.4 10位寻址扩展 3. IC总线故障与锁死 3.1 断电锁死原理3.2 总线挂起与…...
【力扣hot100题】(039)二叉树的直径
这题在简单题中有点难度,主要是不要把边数和深度搞混(我就这样)。 我想了很久,发现如果当前节点没有右节点,就将它的右长度设为0,左节点同理,并且在递归是不会加一,而是将加一的操作…...
L2-001 紧急救援
注意题目没有说边的数量,实际最多有5e5条边,开小了第四个样例会错!!! - 思路: Dijkstra 求最短路并且维护路径条数和最大人数。 #include<bits/stdc.h> using namespace std;typedef pair<int, int> pii…...
分组背包问题
与01背包的区别是,多了一个限制条件,将物品打包,每组物品只能用一个 #include <iostream> #include <algorithm>using namespace std;const int N 110;int v[N][N], w[N][N], s[N]; int f[N]; int n, m;int main() {cin >>…...
【工业场景】用YOLOv12实现饮料类别识别
饮料类别识别任务的意义在于帮助人们更快速地识别和区分不同类型的饮料,从而提高消费者的购物体验和满意度。对于商家而言,饮料类别识别可以帮助他们更好地管理库存、优化货架布局和预测销售趋势,从而提高运营效率和利润。此外,饮…...
宽带空时波束形成算法原理及MATLAB仿真
宽带阵列信号处理 空时波束形成、空时波束形成方向图 卫星导航空时抗干扰算法 MATLAB仿真 文章目录 前言一、空时波束形成结构二、空时波束形成方向图三、MATLAB仿真四、MATLAB源代码总结 前言 \;\;\;\;\; 空时波束形成(Space-Time Beamforming)是一种结…...
406. 根据身高重建队列
链接 406. 根据身高重建队列 - 力扣(LeetCode) 题目 思路 可能的一个思路是先对高的人进行处理,这样后面插入矮的人时不会影响高的人的位置。比如,如果先处理高个子,那么当插入一个矮个子的时候,前面的高…...
机器学习:人工智能的核心驱动力
近年来,机器学习(Machine Learning,简称ML)已成为人工智能(AI)领域的核心驱动力。它不仅广泛应用于图像识别、自然语言处理、医疗诊断等领域,还推动了自动驾驶、智能推荐系统等前沿技术的发展。…...
机器视觉中的传统视觉与深度视觉
工业视觉是现代制造业中一个非常重要的应用领域,广泛用于产品质量检测,尤其是在生产线上。几乎所有的工业产品在流入市场之前,都要经历严格的缺陷检测环节,以确保它们符合质量标准。而在这一过程中,工业视觉检测系统发…...
机器学习开发全流程详解:从数据到部署的完整指南
机器学习项目的成功不仅依赖算法选择,更在于系统化的开发流程。本文详细拆解各阶段的核心任务、工具及注意事项,并通过表格总结帮助开发者快速掌握关键要点。 1. 数据获取与准备 数据是机器学习的基础,需确保数据的质量与代表性。 关键任务…...
春晚魔术[蓝桥]
这里 考虑到N很大则快速幂无法处理,因为它并没有被取模 欧拉定理: 当是质数时 是质数 两边同时取mod, // // Created by yumo_ // #include<bits/stdc.h>using namespace std; #define scin std::cin #define scout std::cout using …...
CF580B Kefa and Company(滑动窗口)
题目描述 Sergei B., the young coach of Pokemons, has found the big house which consists of n flats ordered in a row from left to right. It is possible to enter each flat from the street. It is possible to go out from each flat. Also, each flat is connecte…...
多模态RAG实践:如何高效对齐不同模态的Embedding空间?
目录 多模态RAG实践:如何高效对齐不同模态的Embedding空间? 一、为什么需要对齐Embedding空间? 二、常见的对齐方法与关键技术点 (一)对比学习(Contrastive Learning) (二&#…...
linux 时钟
chronyc sourcestats 查看所有的源以及那个比较稳定 chronyc tracking 查看当前使用的是那个 ntpstat synchronised to NTP server (119.28.183.184) at stratum 3 time correct to within 57 ms polling server every 1024 s chronyc tracking | grep "Reference ID&quo…...
【leetcode100】每日温度
1、题目描述 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 示例 1: 输…...
华为交换综合实验——VRRP、MSTP、Eth-trunk、NAT、DHCP等技术应用
一、实验拓扑 二、实验需求 1,内网Ip地址使用172.16.0.0/16分配 2,sw1和SW2之间互为备份 3, VRRP/STP/VLAN/Eth-trunk均使用 4,所有Pc均通过DHCP获取IP地址 5,ISP只能配置IP地址 6,所有电脑可以正常访问IsP路由器环回 三、需求分析 1、设备连接需求 二层交换机(LS…...
边缘检测技术现状初探2:多尺度与形态学方法
一、多尺度边缘检测方法 多尺度边缘检测通过在不同分辨率/平滑度下分析图像,实现: 粗尺度(大σ值):抑制噪声,提取主体轮廓细尺度(小σ值):保留细节,检测微观…...
【JavaScript】十四、轮播图
文章目录 实现一个轮播图,功能点包括: 自动播放鼠标经过暂时播放鼠标离开继续播放点击切换按钮手动切换 div盒子嵌套先写出静态HTML,再使用JS来修改样式和数据,渲染页面: <!DOCTYPE html> <html lang"…...
19信号和槽_信号和槽的基本概念
①Linux 信号 Signal 是系统内部的通知机制. 是进程间通信的方式 (给进程发信号kill命令,像情景内存泄漏,管道一端关闭另一端还是读,会给进程发信号) ②信号三要素 信号源: 谁发的信号 信号的类型: 哪种类别的信号 信…...
云端革命:数字文明的重构与新生
引言:算力大爆炸时代 2023年,当ChatGPT在全球掀起AI狂潮时,很少有人意识到,支撑这场智能革命的正是背后庞大的云计算基础设施。每天,全球云计算平台处理的数据量超过500EB,相当于5亿部高清电影;…...
论文阅读笔记:Denoising Diffusion Implicit Models (4)
0、快速访问 论文阅读笔记:Denoising Diffusion Implicit Models (1) 论文阅读笔记:Denoising Diffusion Implicit Models (2) 论文阅读笔记:Denoising Diffusion Implicit Models (…...
红帽Linux怎么重置密码
完整流程 ●重启操作系统,进入启动界面 ●然后按进入选择项界面 ●找到linux单词开头的那一行,然后移动到该行末尾(方向键移动或者使用键盘上的end),在末尾加入rd.break ●按ctrl x进入rd.break模式 ●在该模式下依次…...
关于存储的笔记
存储简介 名称适用场景常见运用网络环境备注块存储高性能、低延迟数据库局域网专业文件存储数据共享共享文件夹、非结构化数据局域网通用对象存储大数据、云存储网盘、网络媒体公网(断点续传、去重)海量 存储协议 名称协议块存储FC-SAN或IP-SAN承载的…...
java根据集合中对象的属性值大小生成排名
1:根据对象属性降序排列 public static <T extends Comparable<? super T>> LinkedHashMap<T, Integer> calculateRanking(List<ProductPerformanceInfoVO> dataList, Function<ProductPerformanceInfoVO, T> keyExtractor) {Linked…...
蓝桥杯嵌入式16届—— LED模块
使用主板 是STMG431RBT6 STMG431RBT6资源 资源配置表 跳线说明表 引脚状况 PC8~PC15分别对应着LD1~LD8 SN74HC573ADWR 是一种锁存器 当 LE(锁存使能)为高电平,输出 Q 实时跟随输入 D 的变化。当 LE 为低电平,输出锁定为最后…...
【IOS webview】源代码映射错误,页面卡住不动
报错场景 safari页面报源代码映射错误,页面卡住不动。 机型:IOS13 技术栈:react 其他IOS也会报错,但不影响页面显示。 debug webpack配置不要GENERATE_SOURCEMAP。 解决方法: GENERATE_SOURCEMAPfalse react-app…...
206. 反转链表 92. 反转链表 II 25. K 个一组翻转链表
leetcode Hot 100系列 文章目录 一、翻转链表二、反转链表 II三、K 个一组翻转链表总结 一、翻转链表 建立pre为空,建立cur为head,开始循环:先保存cur的next的值,再将cur的next置为pre,将pre前进到cur的位置…...
绘制动态甘特图(以流水车间调度为例)
import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np from matplotlib import cm# 中文字体配置(必须放在所有绘图语句之前) plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Fa…...
生成式AI应用带来持续升级的网络安全风险
生成式AI应用带来持续升级的网络安全风险概要 根据Netskope最新研究,企业向生成式AI(GenAI)应用共享的数据量呈现爆炸式增长,一年内激增30倍。目前平均每家企业每月向AI工具传输的数据量已达7.7GB,较一年前的250MB实现…...
C++17更新内容汇总
C17 是 C14 的进一步改进版本,它引入了许多增强特性,优化了语法,并提升了编译期计算能力。以下是 C17 的主要更新内容: 1. 结构化绑定(Structured Bindings) 允许同时解构多个变量,从 std::tup…...
conda activate激活环境失败问题
出现 CondaError: Run conda init before conda activate 的错误,通常是因为 Conda 没有正确初始化当前的命令行环境。以下是解决方法: 1. 初始化 Conda 运行以下命令以初始化 Conda: conda init解释: conda init 会修改当前 S…...
TensorFlow实现逻辑回归
目录 前言TensorFlow实现逻辑回归 前言 实现逻辑回归的套路和实现线性回归差不多, 只不过逻辑回归的目标函数和损失函数不一样而已. TensorFlow实现逻辑回归 import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import mak…...
第十四届蓝桥杯大赛软件赛省赛Python 大学 C 组:6.棋盘
题目1 棋盘 小蓝拥有 nn 大小的棋盘,一开始棋盘上全都是白子。 小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)。 请输出所有操作做完后棋盘上每个棋子的颜色。 输入格…...
电商场景下高稳定性数据接口的选型与实践
在电商系统开发中,API接口需要应对高并发请求、动态数据更新和复杂业务场景。我将重点解析电商场景对数据接口的特殊需求及选型方案。 一、电商API必备的四大核心能力 千万级商品数据实时同步 支持SKU基础信息/价格/库存多维度更新每日增量数据抓取与历史版本对比…...
内网服务器centos7安装jdk17
1. 下载 JDK 17 安装包(在外网环境操作) 在可联网的机器上下载 JDK 17 的压缩包(推荐使用 OpenJDK): OpenJDK 官方源: Adoptium Eclipse Temurin Azul Zulu 直接下载命令示例(在外网机器上执行…...
Git 使用教程
Git 使用教程 Git 是目前最流行的分布式版本控制系统,它能够高效地管理代码,并支持团队协作开发。本文将介绍 Git 的基本概念、常用命令以及如何在实际项目中使用 Git 进行版本控制。 1. Git 基本概念 在使用 Git 之前,需要了解以下几个基…...
【无标题】跨网段耦合器解决欧姆龙CJ系列PLC通讯问题案例
欧姆龙CJ系列PLC不同网段的通讯问题 一、项目背景 某大型制造企业的生产车间内,采用了多台欧姆龙CJ系列PLC对生产设备进行控制。随着企业智能化改造的推进,需要将这些PLC接入工厂的工业以太网,以便实现生产数据的实时采集、远程监控以及与企业…...
13_pandas可视化_seaborn
导入库 import numpy as np import pandas as pd # import matplotlib.pyplot as plt #交互环境中不需要导入 import seaborn as sns sns.set_context({figure.figsize:[8, 6]}) # 设置图大小 # 屏蔽警告 import warnings warnings.filterwarnings("ignore")关系图 …...
【C++进阶四】vector模拟实现
目录 1.构造函数 (1)无参构造 (2)带参构造函数 (3)用迭代器构造初始化函数 (4)拷贝构造函数 2.operator= 3.operator[] 4.size() 5.capacity() 6.push_back 7.reserve 8.迭代器(vector的原生指针) 9.resize 10.pop_back 11.insert 12.erase 13.memcpy…...
14使用按钮实现helloworld(1)
目录 还可以通过按钮的方式来创建 hello world 涉及Qt 中的信号槽机制本质就是给按钮的点击操作,关联上一个处理函数当用户点击的时候 就会执行这个处理函数 connect(谁发的信号, 信号类型, 谁来处理这个信息, 怎么处理的&…...
嵌入式EMC设计面试题及参考答案
目录 解释 EMC(电磁兼容性)的定义及其两个核心方面(EMI 和 EMS) 电磁兼容三要素及相互关系 为什么产品必须进行 EMC 设计?列举至少三个实际工程原因 分贝(dB)在 EMC 测试中的作用是什么?为何采用对数单位描述干扰强度? 传导干扰与辐射干扰的本质区别及典型频率范围…...