文章目录
Objcet根父类
是所有类的直接或者间接父类
如果一个类没有显示的继承另一个类,那么默认继承Objcet类
数组的父类也是Object
toString()
如果输出对象名,则会自动调用toString();方法
public class Person {
private String name;
private int age;
private double height;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Person() {
}
public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("张三",18,1.83);
System.out.println(person);
}
}
getClass()
获取运行时类型
多态创建的那个实际对象
public class Animal {
public void eat(){
System.out.println("吃");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("小狗吃肉");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("小猫吃鱼");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
System.out.println(animal.getClass());
Animal animal1 = new Cat();
System.out.println(animal1.getClass());
}
}
finalize()
对象被回收之前会调用finalize()方法
public class Test {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1 = null;
s2 = null;
//通知垃圾回收站回收
System.gc();
}
}
class Student{
private String name;
private int age;
private double height;
@Override
protected void finalize() throws Throwable {
System.out.println("HelloWorld!");
}
public Student() {
}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
hashCode()
用于返回当前对象的hash码
哈希表:顺序表+链表
尽量让不同的对象产生的hash码是不一样的:重写hashCode()
hashCode的常规协定
- 如果两个对象的hash值是不同的,那么这两个对象一定不相等
- 如果两个对象的hash值是相同的,那么这两个对象不一定相等
equals()
- == :比较基本类型数据,比较的是值
比较引用类型数据,比较的是地址值 - equals():只能比较引用类型数据
- equals():如果没有重写,比较的是地址值
- 重写equals():当两个对象的属性完全一样的时候,就认为俩对象是一个对象
import java.util.Objects;
public class Test {
public static void main(String[] args) {
Student s1 = new Student("张三",2,1.83);
Student s2 = new Student("李四",1,1.78);
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println("===================================");
Student s3 = new Student("李四",1,1.78);
System.out.println(s3.hashCode());
System.out.println(s3.equals(s2));//true
System.out.println(s3.equals(s1));//false
System.out.println("===================================");
Student s4 = null;//对象空
System.out.println(s2.equals(s4));
//注:使用自己确定的值调用方法,防止出现空指针异常
System.out.println(s4.equals(s2));//NullPointerException空指针异常
}
}
class Student{
private String name;
private int age;
private double height;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
//因为浮点类型存储的是约束,不建议使用==比较浮点类型
// Double.compare(浮点数1, 浮点数2)
//浮点数1==浮点数2 返回0;浮点数1>浮点数2 返回1;浮点数1<浮点数2 返回-1
return getAge() == student.getAge() && Double.compare(student.getHeight(), getHeight()) == 0 && getName().equals(student.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge(), getHeight());
}
public Student() {
}
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
抽象类
是一组功能的集合,若是我子类,必须有这些功能;或者子类也变为抽象类
- 定义抽象类
[权限修饰符] abstract class 类名 - 定义抽象方法
[权限修饰符] abstract 返回值类型 方法名(形参); - 抽象类不能创建对象,所有的功能都需要子类实现
- 如果一个类继承了抽象类,此类必须实现父类所有的抽象方法
- 抽象类中可以没有抽象方法
- 抽象类中可以存在普通资源(变量、方法)
- 抽象方法必须存在于抽象类中
- 一个类实现接口或继承抽象类后,不想实现父类中的方法,则自己必须变成抽象类
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
Dog dog1 = new Dog("大黄",5);
System.out.println(dog1);
}
}
//抽象类
abstract class Animal{
//6. 抽象类中可以存在普通资源(变量、方法)
String name;
int age;
//抽象方法
public abstract void eat();
public abstract void sleep();
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//4. 如果一个类继承了抽象类,此类必须实现父类所有的抽象方法
class Dog extends Animal{
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("小狗吃肉");
}
@Override
public void sleep() {
System.out.println("小狗睡觉");
}
}
//8. 一个类实现接口或继承抽象类后,不想实现父类中的方法,则自己必须变成抽象类
abstract class Cat extends Animal{
@Override
public void eat() {
System.out.println("小猫吃鱼");
}
}
接口
用来定义规范的
- 声明接口
[权限修饰符] interface 接口名{} - 使用接口
class 类名 implements 接口名{} - 如果一个类实现了一个接口,那么此类可以看做是此接口的子类
可以应用多态 - 一个类可以实现多个接口
- 接口的成员
- 全局静态常量:默认被public static final修饰
- 抽象方法:默认被public abstract 修饰
- 默认方法:默认被public修饰
- 静态方法:默认被public修饰
- 接口可以多继承
如果一个类实现了继承了多个接口的接口,那么不仅要实现此接口的抽象方法,也要实现继承接口的抽象方法 - 一个类可以先继承一个父类,再去实现多个接口,顺序不能改变
- 当出现同名方法,则必须进行重写,否则报错(不知道使用哪一个)
可以在重写的方法里通过:接口名.super.方法名();去调对应接口的方法
public class Test{
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
superMan.fly();
//3. 如果一个类实现了一个接口,那么此类可以看做是此接口的子类
Fly fly = new Bird();//可以使用多态
fly.fly();
Plane plane = new Plane();
plane.addOil();
}
}
//1. 声明接口:[权限修饰符] interface 接口名{}
interface Fly {
int F = 10;//全局静态常量:默认被public static final修饰
void fly();//接口中的抽象方法:默认被public abstract修饰
//默认方法:默认被public修饰
default void addOil(){
System.out.println("加油");
}
}
interface Eat{
void eat();
}
//6. 接口可以多继承
interface Sleep extends Fly,Eat{
void sleep();
}
//2. 使用接口:[权限修饰符] class 类名 implements 接口名{}
class SuperMan implements Fly{
@Override
public void fly() {
System.out.println("超人起飞");
}
}
//4. 一个类可以实现多个接口
class Bird implements Fly,Eat{
@Override
public void fly() {
System.out.println("小鸟起飞");
}
@Override
public void eat() {
System.out.println("小鸟吃虫");
}
}
class Plane implements Fly{
@Override
public void fly() {
System.out.println("飞机起飞");
}
@Override
public void addOil() {
System.out.println("飞机加油");
}
}
class Animal{
}
//7. 一个类可以先继承一个父类,再去实现多个接口,顺序不能改变
class dog extends Animal implements Sleep{
@Override
public void fly() {
System.out.println("小狗不能飞");
}
@Override
public void eat() {
System.out.println("小狗吃肉");
}
@Override
public void sleep() {
System.out.println("小狗睡觉");
}
}
Comparable:内部比较器
内部比较器:在比较对象类的内部完成了比较规则的指定
java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable接口
public class Test {
public static void main(String[] args) {
Student s1 = new Student("张三",18,99.5);
Student s2 = new Student("李四",19,88.5);
Student [] students = {s1,s2};
for (Student s:students) {
System.out.println(s);
}
//SortUtils.sort(students);//通用排序方法
SortUtils.sort1(students);//优化通用方法
//mineSort(students);
System.out.println("排序后");
for (Student s:students) {
System.out.println(s);
}
}
private static void mineSort(Student[] students) {
for (int i = 0; i < students.length-1; i++) {
for (int j = 0; j < students.length-i-1; j++) {
//当前一个数大于后一个数交换两数位置
if (students[j].compareTo(students[j+1]) > 0) {
Student temp = students[j];
students[j] = students[j+1];
students[j+1] = temp;
}
}
}
}
}
//定义一个类实现Comparable接口
class Student implements Comparable{
String name;
int age;
double score;
@Override
public int compareTo(Object o) {//写比较规则
Student s = (Student)o;
return this.age-s.age;
}
public Student() {
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class SortUtils {
public static void sort(Object[] objects){//多态Object objects = students
for (int i = 0; i < objects.length-1; i++) {
for (int j = 0; j < objects.length-1-i; j++) {
//为了更加通用:向下转型
Comparable s =(Comparable) objects[j];
Comparable s1 = (Comparable) objects[j+1];
if(s.compareTo(s1)>0){
Object temp = objects[j];
objects[j] = objects[j+1];
objects[j+1] = temp;
}
}
}
}
//优化方法
public static void sort1(Comparable[] objects){//Comparable objects = students
for (int i = 0; i < objects.length-1; i++) {
for (int j = 0; j < objects.length-1-i; j++) {
if(objects[j].compareTo(objects[j+1])>0){
Comparable temp = objects[j];
objects[j] = objects[j+1];
objects[j+1] = temp;
}
}
}
}
}
Comparator:外部比较器
在比较对象类的外面新建了一个类专门用于比较
- 定义一个类,实现Comparator接口
- 重写compare()方法, 传递两个参数
- 制定比较规则
- 使用时先创建比较规则的对象
通过对象调用compare()方法,再传入对象
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
Person p1 = new Person("张三",20,50000);
Person p2 = new Person("李四",19,20000);
Person p3 = new Person("王五",18,30000);
Person p4 = new Person("赵六",18,40000);
//创建比较规则对象
PersonSortOfAgeAndSalary personSortOfAgeAndSalary = new PersonSortOfAgeAndSalary();
int num = personSortOfAgeAndSalary.compare(p1,p2);
Person[] people = {p1,p2,p3,p4};
//mineSort(people,personSortOfAge);
SortUtils.sort(people,personSortOfAgeAndSalary);//通用排序方法
for (Person p:people) {
System.out.println(p);
}
}
private static void mineSort(Person[] people, PersonSortOfAgeAndSalary personSortOfAge) {
for (int i = 0; i < people.length-1 ; i++) {
for (int j = 0; j < people.length-1-i; j++) {
if(personSortOfAge.compare(people[j],people[j+1])>0){
Person temp = people[j];
people[j] = people[j+1];
people[j+1] = temp;
}
}
}
}
}
class SortUtils{
/**
* 通用排序方法
* @param objects 要排序的数组
* @param comparator 比较规则
*/
public static void sort(Object[] objects,Comparator comparator){
for (int i = 0; i < objects.length-1; i++) {
for (int j = 0; j < objects.length-1-i; j++) {
if (comparator.compare(objects[j],objects[j+1]) > 0) {
Object temp = objects[j];
objects[j] = objects[j+1];
objects[j+1] = temp;
}
}
}
}
}
class Person{
String name;
int age;
double salary;
public Person() {
}
public Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
class PersonSortOfAgeAndSalary implements Comparator {
@Override
public int compare(Object o1, Object o2) {//多态
//Object o1 = p1, Object o2 = p2
//制定比较规则:按年龄,年龄相等时按薪资
Person p1 = (Person) o1;
Person p2 = (Person) o2;
if(p1.age==p2.age){
return Double.compare(p1.salary, p2.salary);
}
return p1.age - p2.age;
}
}
枚举
版本迭代后
- 构造器默认私有
- 枚举中的属性,不许位于枚举元素的下面
- 所有的自定义枚举默认继承自Enum类
- 枚举类不能在继承其他的类
- 枚举类可以实现一个接口
- 枚举对象可以根据自身需求,灵活判断是否需要自定义接口内的方法
public class Test {
public static void main(String[] args) {
Gender man = Gender.MAN;
man.run();
}
}
interface Run{
void run();
}
enum Gender implements Run{
MAN{
@Override
public void run() {
System.out.println("大步流星");
}
},WOMAN{
@Override
public void run() {
System.out.println("婀娜多姿");
}
};
}
包装类
- 常见的包装类型有:
Byte、Short、Integer、Long、Float、Double、Character、Boolean - 基本类型数据与包装类之间的转换:
- 基本类型数据——》对应的包装类数据
- 老方式一:通过构造器 Integer 标识符 = new Integer(基本类型数据);
- 老方式二:Integer 标识符 = Integer.valueOf(基本类型数据);
- 新方法:直接采用自动装箱:
直接将基本类型数据赋值为引用类型的对象
Integer in = 基本类型数据;
自动装箱的底层采用的是Integer.valueOf(基本类型数据);方法
- 包装类型——》基本类型数据
- 方法一:调用包装类对象的 intValue();方法
- 方法二:自动拆箱:
直接将引用类型数据变为基本类型数据:
基本类型数据 标识符 = 包装对象;
- 基本类型数据——》对应的包装类数据
- 字符串与基本类型数据/包装类型的转换
- 字符串——》基本类型数据
- 方法一:Integer.parseInt(“字符串纯数字”);
如果不是纯数字会报异常NumberFormatException
注意:char中没有此方法(“ab”.charAt(0);0代表第一个字符) - 方法二:Integer in = new Integer(“字符串纯数字”);
如果不是纯数字会报异常NumberFormatException
- 方法一:Integer.parseInt(“字符串纯数字”);
- 基本类型数据——》字符串
- 方法一:“”+基本数据类型数值
- 方法二:String.valueOf();
- 字符串——》基本类型数据
- 包装数据类型只能接收对应的包装类型,不能在采用类型自动提升
- 包装类型有一个缓存区
包装类 缓存对象 Byte -127~128 Short -127~128 Integer -127~128 Long -127~128 Float 没有 Double 没有 Character 0~127 Boolean true和false
内部类
内部类:把一个类定义到另一个类内部
外部类:内部类外边的类:只能被public 与 default 修饰
静态内部类
一、语法结构:
class 外部类{
//内部类定义
[权限修饰符4种] static [final] class 内部类名{
}
}
二、作用:
1.可以打破java单继承的性质
2.在内部类中做更多的功能,为外部类服务
3.可以实现资源的隐藏
三、特点
1.静态内部类可以访问外部类的静态属性、静态方法
2.外部类使用内部类资源:
如果是静态资源,可以直接通过: 内部类名.资源名
如果是非静态资源,那么需要通过: 内部类的对象.资源名
3.当类中有内部类的时候:外部类$内部类名
非静态内部类
不加static修饰的内部类
一、语法结构:
class 外部类{
//内部类定义
[权限修饰符4种] class 内部类名{
}
}
二、特点
1.非静态内部类可以直接使用外部类的所有资源
2.外部类使用内部类资源
1.首先创建非静态内部类的对象,才能使用内部类中的资源
2.如果是内部类中的静态常量,可以直接使用
3.外部类的静态方法不能使用内部类资源
3.非静态内部类中不能存在静态的方法静态的属性,但是可以存在静态的常量
4.有几个非静态内部类就会生成几个字节码文件
格式:外部类名$内部类名
5.每一个类中都有一个this代指当前对象
获取外部类中的this:外部类名.this.属性名
局部内部类
一、语法结构:
外部类 类名{
[权限修饰符] [static] 返回值类型 方法名(形参列表){
[修饰符] class 类名{
}
}
}
二、注意
1. 局部内部类只能被default修饰
2. 局部内部类可以被final / abstract修饰
3. 局部内部类使用外部类资源要看外部类的方法是静态还是非静态
方法为非静态:可以使用外部类静态或者非静态资源
方法为静态:可以直接使用外部类中静态资源
4. 局部内部类编译成功后,也会产生对应的字节码文件
外部类名字$序号内部类名字
5. 局部内部类中不能存在静态的属性但是可以存在静态的常量
6. 调用:在方法内创建内部类对象,通过内部类对象调用内部类中的方法
7. 当在局部内部类的方法中使用局部变量时,那么变量前会自动加一个final(jdk1.8)
匿名内部类
没有名字的类
一、语法结构
方式一∶
new 父类(){
重写父类的方法
}
创建了一个子类但是子类是没有名字的
方式二:
new 父类(实参列表){
重写父类的方法
}
创建了一个子类但是子类是没有名字的
方式三:
new 父接口(){
重写接口中的方法
}
创建了一个子类但是子类是没有名字的
二、注意
1. 匿名内部类也会生成独立的字节码文件
外部类的名字$ 序号.class
2. 匿名内部类不可以存在静态的变量,但是可以存在静态的常量
三、内部类的使用
3. 在完成内部类的声明的时候,已经创建了内部类的对象
4. 匿名内部类创建的是子类对象,可以使用子类重写父类的方法,以及从父类继承过来的资源
5. 可以使用接口或者抽象类作为形参传递一个子类
注解
注解:用来给编译器看的
常用注解:
@Override 判断当前方法是不是重写的方法
@Deprecated 标记类或方法过时(过时指不推荐使用,使用不会报错)
@SuppressWarnings 抑制警告
异常
异常体系:
Throwable:是所有异常的根类
- Error:错误是不能处理的(系统内部错误,运行时报错,系统问题)
- StackOverflowError:栈溢出溢出
- OutOfNemoryError
- Exception:可以处理的异常
- 运行时异常RuntimeException:代码写完不报错,运行起来才报错
- 编译时(检查)异常checkedException:写完代码就报错
- 发生异常时,如果没有进行处理,会一层一层的向上抛出,最终交给JVM处理,终止程序,输出对应信息
使用try{}cath(){}处理异常
- 语法结构
try{
可能发生异常的代码
}catch (异常类型 标识符){//此位置已经创建了一个异常对象
对异常进行处理
}
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3};
try{
System.out.println(arr[3]);//在此处发生了异常ArrayIndexOutOfBoundsException
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();//打印异常类型、发生原因、异常位置
System.out.println("异常原因:"+e.getMessage());
}
}
}
- 注意
- 变量的作用域
try中声明的变量,仅仅在try中有效 - 当发生异常后,try语句块内,异常下面的代码不在执行,进到catch内,处理异常,然后进行try{}catch(){}下面的代码
- 如果没有发生异常,则不会执行catch()中的代码
- 如果发生了没有捕获(声明)的异常,则程序立即终止,不会继续执行
- 当try语句块代码可能发生多个异常时,我们可以声明多个异常
- 方式一:catch (异常类型 | 异常类型 标识符)
例:catch (ArrayIndexOutOfBoundsException | InputMismatchException e) - 方式二:多重catch()
catch(异常类型1 标识符1){
}catch(异常类型2 标识符2){
}
发生了什么异常就会进入对应的catch中
- 方式一:catch (异常类型 | 异常类型 标识符)
- 如果采用多重catch那么可以省略为一个Exception,必须放到多重catch的末尾,否则报错(子类异常在前面,父类异常在后面)
- 变量的作用域
使用try{}catch(){}finally{}处理异常
- 语法结构
方式一:
try{
可能发生异常的代码
}catch (异常类型 标识符){//此位置已经创建了一个异常对象
对异常进行处理
}finally{
//无论发生还是没有发生异常不管异常有还是没有捕获都会执行
最终会执行的代码
}
方式二:
try{
可能发生异常的代码
}finally{
//无论发生还是没有发生异常不管异常有还是没有捕获都会执行
最终会执行的代码
}
- 注意
- 在程序没有发生异常时,有return语句,要先执行finally,再执行返回操作
- 在catch语句块内,进行return,也要先执行finally,在执行返回操作
- 如果在finally中存在return,无论前面那个位置有return,都会返回finally中return的值
throw和throws
通过throw抛
- 语法结构
throw new 异常的类型(自定义异常的输出信息);
System.err.println();//红颜色输出信息,位置有可能会颠倒
- 注意
- 如果是运行时异常,则直接使用throw即可
- 如果是编译时异常,那么必须在throw后,在方法的声明处,通过throws表明由调用此方法的方法处理异常
- throws在方法的声明处告诉调用我方法的方法随便掉﹑但是需要处理我声明的异常
- throw一次只能抛出一个异常
- throw下面不能存在其他的内容,否则报错
自定义异常
- 新建一个类
- 继承一个异常类
想要自定义运行时异常,那么继承运行时异常,反之继承编译时异常 - 添加构造器