一、包
包的本质就是不同的文件夹
说明:
- package: 关键字,表示打包
- com.hspedu : 表示表名
命名规则:
- 只能包含字母、数字、下划线、小圆点
- 一般是小写字母+小圆点
- com.公司名.项目名.业务模块名
- 如:com.sina.crm.user
常用的包:
- java.lang
- java.util
- java.net
- java.awt
1 2 3
| import java.util.Scanner;
import java.util.*
|
注意事项:
- package 的作用是声明当前类所在的包,需要写在类的最上边,一个类中最多只能写一个 package
- import 指令放在 package 的下面,在类定义的前面,可以有多句且没有顺序要求
二、访问修饰符
修饰符 | 访问级别 | 本类 | 同包 | 子类 | 不同包 |
---|
public | 公开的 | √ | √ | √ | √ |
protected | 受保护的 | √ | √ | √ | × |
没有修饰符 | 默认 | √ | √ | × | × |
private | 私有的 | √ | × | × | × |
注意事项:
- 修饰符可以用来修饰类中的属性、方法以及类;
- 只有默认和 public 才能修饰类
- 成员方法的访问规则和属性完全一样
三、封装
封装: 把抽象的数据(属性)和对数据的操作(方法)封装在一起,程序的其他部分只能通过被授权的操作(方法)才能对数据操作
封装方法:
- 将属性私有化 (private)
- 提供 公共的 set 方法,用于对属性进行判断并赋值
- public void setxxx(参数){数据验证; 属性 = 参数}
- 提供 公共的 get 方法,用于获取属性值
- public 数据类型 getXxxx(){return xxx};
快速设置 get 及 set 方法的快捷键: control + inter(⌃ + 回车键)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class Encap01 { public static void main(String[] args) { Person person = new Person(); person.setName("老王"); person.setAge(10); System.out.println(person.info()); } }
class Person{ public String name; private int age; private double money;
public void setAge(int age) { if (age >=1 && age <= 120){ this.age = age; }else{ System.out.println("年龄需要在 1 ~ 120 之间"); this.age = 18; } }
public int getAge() { return age; }
public void setName(String name) { if (name.length() >= 2 && name.length() <= 6){ this.name = name; }else { System.out.println("名字程度需要在 2~6 之间"); } }
public String getName() { return name; }
public String info(){ return "姓名:" + name + "\t年龄:" + age + "\t薪资:" + money; } }
|
四、继承
继承: 可以解决代码复用,通过 extends 来声明继承父类,获取父类的属性和方法;、
父类 也叫 基类
子类 也叫 派生类
注意事项:
- 子类继承了父类的所有属性和方法,但是私有属性不能在子类直接访问,要通过公共方法去访问
- 子类必须调用父类的构造器,完成父类的初始化
- 当创建子类对象时,不管使用子类的那个构造器,默认情况下都会调用父类的无参构造器
- 如果父类没有无参构造器,则必须在子类的构造器中用 super 指定使用父类的那个构造器完成对父类的初始化工作,否则编译不通过
- super() 和 this() 都只能在构造器中使用,并且只能放在第一行,所以两个方法不能在同一个构造器中
- 父类构造器的调用不限于直接父类,可以一直往上追溯到 object 类
super 关键字:
- super 代表父类的引用,用于访问父类的属性、方法、构造器
- 访问属性: super.属性名
- 访问方法: super.方法名(参数列表)
- 访问构造器: super(参数列表) 1. 只能放在构造器的第一句,同一构造器只能出现一句
子类默认调用父类的 无参构造器
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Father { public int age;
public Father() { System.out.println("父类无参构造器:Father()"); }
public Father(int age) { this.age = age; System.out.println("父类有参构造器:Father(int age)"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.study;
class Son extends Father { public String name;
public Son(){ System.out.println("子类无参构造器:Son()"); }
public Son(String name){ this.name = name; System.out.println("子类有参构造器:Son(String name)"); } }
|
1 2 3 4 5 6 7 8 9
| public class Test { public static void main(String[] args) { Son son = new Son("老王"); } }
|
子类 通过 super 指定 调用父类的构造器
1 2 3 4 5 6 7
| public class Father { public int age;
public Father(int age) { this.age = age; System.out.println("父类有参构造器:Father(int age)");
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Son extends Father { public String name;
public Son(){ super(10); System.out.println("子类无参构造器:Son()"); }
public Son(String name){ super(10); this.name = name; System.out.println("子类有参构造器:Son(String name)"); } }
|
1 2 3 4 5 6 7 8 9
| public class Test { public static void main(String[] args) { Son son = new Son("老王"); } }
|
super 和 this 的比较
区别点 | this | super |
---|
访问属性 | 如果本类没有此属性,则从父类中继续查找 | 从父类开始查找属性 |
调用方法 | 如果本类没有此方法,则从父类继续查找 | 从父类开始查找方法 |
调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
特殊 | 表示当前对象 | 子类中访问父类对象 |
super : 从他的父类开始,可以调用它所有父类的方法和属性
this : 从他自己开始, 可以调用包括他所有父类的方法和属性,根据就近原则,相同的属性或方法只能调用离他最近的
方法重写
- 子类方法的 参数、方法名 要和父类的方法一致
- 子类方法的返回值类型 和父类方法返回值类型一样,或者父类返回类型的子类
- 父类:public object getInfo()
- 子类:public String getInfo()
- 子类方法不能缩小父类方法的访问权限
- 父类: public void sayOk()
- 子类: void sayOk()
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
---|
重载 | 本类 | 必须一样 | 类型、个数或顺序至少有一个不同 | 无要求 | 无要求 |
重写 | 父子类 | 必须一样 | 相同 | 子类和父类的返回类型一致或使其子类 | 子类方法不能缩小父类方法的访问方位 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Person { private String name; private int age;
public Person(String name, int age) { this.name = name; this.age = age; }
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 String say(){ return String.format("我叫 %s,今年 %d 岁",name,age); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Student extends Person{ private int id; private double score;
public Student(String name, int age, int id, double score) { super(name, age); this.id = id; this.score = score; }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public double getScore() { return score; }
public void setScore(double score) { this.score = score; }
public String say(){ return super.say() + String.format("我的学号是 %d,我考了 %f",id, score); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class Test { public static void main(String[] args) { Person person = new Person("老王", 20); String a = person.say(); System.out.println(a); Student student = new Student("张三",21,22,12); String b = student.say(); System.out.println(b); } }
|
五、多态
多态: 方法或对象具有多种形态,是建立在封装和继承基础之上的
重点:
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以改变的
- 编译类型看定义时 = 号 的左边,运行类型看 = 号的 右边
注意事项:
- 多态的前提: 两个对象存在继承关系
- 多态向上转型
- 本质: 服务类的引用指向了子类的对象
- 语法: 父类类型 引用名 = new 子类类型()
- 特点: 编译类型看左边, 运行类型看右边
- 多态向下转型
- 语法: 子类类型 引用名 = (子类类型)父类类型;
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向当前目标类型的对象
- 当讲下转型后,可以对用子类类型的所有成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class PolyDetail01 { public static void main(String[] args) { Base base = new Sub(); System.out.println(base.count);
Sub sub = (Sub)base; System.out.println(sub.count); } }
class Base{ int count = 10; }
class Sub extends Base{ int count = 20; }
|
instanceOf : 比较符,用于判断对象的运行类型是否为 xx 类型或者 xx 类型的子类型
1 2 3 4 5 6 7 8 9 10 11
| public class PolyDetail02 { public static void main(String[] args) { BB bb = new BB(); System.out.println(bb instanceof BB); } }
class AA{}
class BB extends AA{}
|
动态绑定机制
- 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
- 当调用对象属性时,没有动态绑定机制,那是声明使用哪里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class DynamicBinding { public static void main(String[] args) { A a = new B(); System.out.println(a.sum()); System.out.println(a.sum1()); } }
class A{ public int i=10; public int sum(){ return getI() + 10; } public int sum1(){ return i+10; }
public int getI() { return i; } }
class B extends A{ public int i=20;
public int getI() { return i; } }
|
多态数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class Person { public String name; public int age;
public Person(String name, int age) { this.name = name; this.age = age; }
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 String say() { return String.format("姓名= %s,年龄=%d", name, age); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class Student extends Person { private double score;
public Student(String name, int age, double score) { super(name, age); this.score = score; }
public double getScore() { return score; }
public void setScore(double score) { this.score = score; }
@Override public String say() { return super.say() + String.format("分数=%f", score); }
public String study() { return String.format("学生:%s 正在学习", getName()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Teacher extends Person { private double salary;
public Teacher(String name, int age, double salary) { super(name, age); this.salary = salary; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
@Override public String say() { return super.say() + String.format("薪水= %f", salary); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class Test { public static void main(String[] args) { Person[] person = new Person[5]; person[0] = new Person("jack", 20); person[1] = new Student("Tom", 20, 99); person[2] = new Student("smith", 18, 60); person[3] = new Teacher("scott", 50, 2000); person[4] = new Teacher("king", 60, 10000);
for (int i = 0; i < person.length; i++) { System.out.println(person[i].say()); if (person[i] instanceof Student) { System.out.println(((Student) person[i]).study());
} else if (person[i] instanceof Teacher) { Teacher teacher = (Teacher) person[i]; System.out.println(teacher.teach()); } } } }
|
六、object 类
1.equals
== 和 equals 的区别:
- ==:
- 既可以判断两个引用类型是否相等(地址是否相等),又可以判断两个值是否相等
- equals:
- 只能判断引用类型(默认判断地址是否相等,子类中会对其重写,用于判断内容是否相等)
1 2 3 4 5 6 7 8 9 10 11 12
| public class Equals { public static void main(String[] args) { String str1 = new String("你好"); String str2 = new String("你好");
System.out.println(str1 == str2); System.out.println(str1.equals(str2)); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class Person{ private String name; private int age;
public Person(String name, int age) { this.name = name; this.age = age; } public boolean equals(Object obj){ if (this == obj){ return true; } if (obj instanceof Person){ Person person = (Person)obj; return this.name.equals(person.name) && this.age == person.age; } return false; }
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; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| public class Doctor { private String name; private int age; private String job; private char gender; private double sal;
public Doctor(String name, int age, String job, char gender, double sal) { this.name = name; this.age = age; this.job = job; this.gender = gender; this.sal = sal; }
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 String getJob() { return job; }
public void setJob(String job) { this.job = job; }
public char getGender() { return gender; }
public void setGender(char gender) { this.gender = gender; }
public double getSal() { return sal; }
public void setSal(double sal) { this.sal = sal; }
@Override public boolean equals(Object obj) { if (this == obj){ return true; } if (obj instanceof Doctor){ Doctor doctor = (Doctor) obj; return this.name.equals(doctor.name) && this.age == doctor.age && this.job.equals(doctor.job) && this.gender == doctor.gender && this.sal == doctor.sal; } return false; }
public static void main(String[] args) { Doctor doctor1 = new Doctor("老王", 50, "程序员", '男', 50000); Doctor doctor2 = new Doctor("老王", 50, "程序员", '男', 50000); System.out.println(doctor1.equals(doctor2)); } }
|
2.hashCode
- 提高具有哈希结构的容器的效率
- 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的
- 两个引用, 如果指向的是不同对象,则哈希值是不一样的
- 哈希值主要是根据地址来的, 但是哈希值不等价于地址.
3.toString
- 默认返回 : 全类名 + @ + 哈希值的十六进制
- 子类往往会重写 toString 方法, 用于返回对象的属性信息
- 重写 toString 方法, 打印对象或拼接对象时,都会自动调用该对象的 toString 形式
- 当直接输出一个对象时, toString 方法会被默认调用
4.finalize
- 当对象被回收时,系统自动调用该对象的 finalize 方法
- 当某个对象没有任何引用时, 就是使用回收机制来销毁对象, 在销毁前会先调用 finalize 方法
- 垃圾回收机制是由系统来决定的, 也可以通过 System.gc() 主动触发垃圾回收机制
七.案例
1.创建 3 个 person 对象数组,并根据年龄排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class Person { private String name; private int age; private String job;
public Person(String name, int age, String job) { this.name = name; this.age = age; this.job = job; }
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 String getJob() { return job; }
public void setJob(String job) { this.job = job; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", job='" + job + '\'' + '}'; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Test { public static void main(String[] args) { Person[] person = new Person[3]; person[0] = new Person("张三", 30, "盗墓"); person[1] = new Person("李四", 28, "摸金校尉"); person[2] = new Person("王五", 50, "古董贩子");
Person temp = null;
for (int i = 0; i < person.length-1; i++) { for (int j = 0; j < person.length-i-1; j++) { if (person[j].getAge() < person[j+1].getAge()){ temp = person[j]; person[j] = person[j+1]; person[j+1] = temp; } } }
for (int i = 0; i < person.length; i++) { System.out.println(person[i]); } } }
|