1.封装
public class Encap01 {
public static void main(String[] args) {
Account account = new Account("李代胜",1000000,"6933784");
System.out.println(account.info());
}
}
class Account {
private String name;//名字公开
private double balance;//姓名私有
private String password;//工资私有
public Account() {
}
public Account(String name, double balance, String password) {
setName(name);
setBalance(balance);
setPassword(password);
}
public void setName(String name) {
if (name.length() >=2 && name.length() <=4) {
this.name = name;
}else {
System.out.println("姓名长度有误");
this.name = "无名";
}
}
public void getName(String name) {
this.name = name;
}
public void setBalance(double balance) {
if (balance>20) {
this.balance = balance;
}else {
System.out.println("余额有误");
this.balance = 0.0;
}
}
public void getBalance(double balance) {
this.balance = balance;
}
public void setPassword(String password) {
if (password.length() == 6){
this.password = password;
}else {
System.out.println("密码长度有误");
this.password = "693784";
}
}
public void getPassword(String password) {
this.password = password;
}
public String info() {
return "name为:" + name + ",balance为:" + balance + ",password为:" + password;
}
}
2.继承
2.1.继承的细节
2.2.继承本质分析
过程:子类创建的过程中在方法区会先加载类。类就会找继承关系,先加载父类,直到加载到超级父类Object。然后在堆里面分配空间,先从父类分配(堆中存地址,常量池存具体的值和地址)
2.3.练习
3.super关键字

4.super和this的比较
5.方法重写
6.多态
6.2.多态细节
6.3.动态绑定机制
上述代码,当把子类的sum()方法注释掉,getI()方法调用的是子类的,属性没有动态绑定机制,所以i还是取的父类的i
6.4.多态数组
6.5.多态参数
7.Object详解
7.1.==和equals的区别
7.1.1==
7.1.2.equals
7.1.3.重写equals方法(对象)
public class poly01 {
public static void main(String[] args) {
Person person1 = new Person("jack", 20, '男');
Person person2 = new Person("jack", 20, '男');
System.out.println(person1.equals(person2));//在未重写equals的情况下,使用的是Object的equals方法,比较的是地址值,所以返回false
}
}
@Data
class Person{
private String name;
private int age;
private char gender;
//重写object的equals方法
public boolean equals(Object obj){
//this 当前对象Person,如果当前对象和传进来的对象是同一个对象,直接返回trur
if (this == obj){
return true;
}
if (obj instanceof Person){//当前对象是Person,才做比较
//向下转型,需要得到各个obj的属性
Person p = (Person) obj;
return this.name.equals(p.name) && this.age==p.age && this.gender == p.gender;
}
//不是Person对象返回false
return false;
}
}
8.hashCode
9.toString
10.finalize
11.类变量
内存图
12.类方法
13.理解main方法
14.代码块
15.单例模式
public class HouseRentApp {
public static void main(String[] args) {
GirlFriend xh = new GirlFriend("小红");
GirlFriend xb = new GirlFriend("小白");
}
}
//女朋友类,只能有一个女朋友
class GirlFriend{
private String name;
public GirlFriend(String name){
this.name = name;
}
}
上述代码出现了两个对象,不符合单例规则
单例改造
15.1.饿汉式
有可能还没用这个对象,对象就已经创建好了,所以叫饿汉式
public class HouseRentApp {
public static void main(String[] args) {
// GirlFriend xh = new GirlFriend("小红");
// GirlFriend xb = new GirlFriend("小白");
GirlFriend instance = GirlFriend.getInstance();
}
}
//女朋友类,只能有一个女朋友
class GirlFriend{
//单例改造
//1.私有构造方法
//2.在类的内部直接创建
//3.提供一个公用的static方法,返回gf对象
private String name;
//2
//为了能够在静态方法中返回gf对象,需要用static修饰
//有可能还没用这个对象,对象就已经创建好了,所以叫饿汉式
private static GirlFriend gf= new GirlFriend("小红红");
//1
private GirlFriend(String name){
this.name = name;
}
public static GirlFriend getInstance(){
return gf;
}
}
15.2.懒汉式
需要使用对象时,才会创建对象
简单懒汉式
public class HouseRentApp {
public static void main(String[] args) {
GirlFriend instance = GirlFriend.getInstance();
}
}
//简单懒汉式
class GirlFriend{
//步骤:
//1.私有化构造器
//2.定义一个static静态属性对象
//3.定义一个public static方法,可以返回一个cat对象
private String name;
private static GirlFriend gf;
private GirlFriend(String name){
this.name = name;
}
public static GirlFriend getInstance(){
if (gf == null){
gf = new GirlFriend("小可爱");
}
return gf;
}
}
15.3.饿汉式和懒汉式区别
16.final
17.抽象类
class Animal{
private String name;
public Animal(String name){
this.name = name;
}
/**
* 思考:这里eat()方法无意义
* 即:父类方法不确定性的问题
* 考虑将方法设计为抽象(abstract)方法:所谓抽象方法就是没有实现的方法(没有方法体)
*/
public void eat(){
System.out.println("这是一个动物,但是不知道吃什么!");
}
}
abstract class Animal{
private String name;
public Animal(String name){
this.name = name;
}
/**
* 当一个类中存在抽象方法,这个类也必须声明为抽象类
* 一般来说,抽象类会被继承,由子类来实现抽象方法
*/
public abstract void eat();
}
public class HouseRentApp {
public static void main(String[] args) {
Manager manager = new Manager("李代胜",30000,1);
manager.setBonus(20000);
manager.work();
Employee commonEmployee = new CommonEmployee("黄",10000,2);
commonEmployee.work();
}
}
@Data
abstract class Employee{
private String name;
private double salary;
private int id;
public abstract void work();
}
@Data
class Manager extends Employee{
private double bonus;
@Override
public void work() {
System.out.println("经理 " + getName()+ " 在工作");
}
}
class CommonEmployee extends Employee{
@Override
public void work() {
System.out.println("工人 " + getName() + " 在工作");
}
}
普通解决
package com.cn.houserent;
public class HouseRentApp {
public static void main(String[] args) {
JobNum job = new JobNum();
job.getJobTime();
JobNumB jobNumB = new JobNumB();
jobNumB.getJobTime();
}
}
class JobNum{
public void getJobTime(){
long star = System.currentTimeMillis();
int l = 0;
for (int i = 0; i < 1000000000; i++) {
l += i;
}
long end = System.currentTimeMillis();
System.out.println("执行时长:" + (end - star));
}
}
class JobNumB{
public void getJobTime(){
long star = System.currentTimeMillis();
int l = 0;
for (int i = 0; i < 1000000000; i++) {
l += i;
}
long end = System.currentTimeMillis();
System.out.println("执行时长:" + (end - star));
}
}
模板设计模式解决
public class HouseRentApp {
public static void main(String[] args) {
AA aa = new AA();
aa.CalculateTime("AA");
BB bb = new BB();
bb.CalculateTime("BB");
}
}
abstract class Template{
public abstract void job();
public void CalculateTime(String lei){
long star = System.currentTimeMillis();
job();//动态绑定(很重要),aa调用的时候就动态绑定到AA类的job()方法
long end = System.currentTimeMillis();
System.out.println(lei + "执行时长:" + (end - star));
}
}
class AA extends Template{
public void job(){
int l = 0;
for (int i = 0; i < 1000000000; i++) {
l += i;
}
}
}
class BB extends Template{
public void job(){
int l = 0;
for (int i = 0; i < 1000000000; i++) {
l += i;
}
}
}
18.接口
19.接口和继承
当子类继承了父类就自动有了父类的功能。如果子类需要扩展功能,可以通过实现接口的方法扩展
可以理解为,接口是对java单继承的一种补充
20.接口的多态性
21.内部类
21.1.内部类的分类
21.2.局部内部类
(1)
class Outer{//外部类
private int n1 = 100;
private void m2(){}//私有方法
public void m1(){//方法
//局部内部类是定义在外部类的局部位置,通常在方法中
class Inner{//局部内部类(本质还是一个类)
public void f1(){
System.out.println(n1);//可以直接访问私有属性
m2();//可以直接访问私有方法
}
}
}
}
(2)
(5)
12.3.匿名内部类
12.4.基于接口的匿名内部类
传统方式
public class LocalInnerClass {
public static void main(String[] args) {
//基于接口的匿名内部类
Tiger tiger = new Tiger();
tiger.cry();
}
}
interface A{
void cry();
}
class Tiger implements A{
@Override
public void cry() {
System.out.println("老虎~~~");
}
}
需求:Tiger类只使用一次,后面再不使用了
public static void main(String[] args) {
//需求:Tiger类只使用一次,后面再不使用了,使用匿名内部类解决
A a = new A() {
@Override
public void cry() {
System.out.println("老虎叫~~");
}
};
a.cry();
}
}
interface A{
void cry();
}
public class LocalInnerClass {
public static void main(String[] args) {
//基于接口的匿名内部类
Tiger tiger = new Tiger();
tiger.cry();
//需求:Tiger类只使用一次,后面再不使用了,使用匿名内部类解决
//编译类型是什么?A
//运行类型是什么?就是匿名内部类
//底层
/*
//jdk底层在创建匿名内部类LocalInnerClass$1,立即就会创建LocalInnerClass$1实例,
// 并把地址返回给a
class xxx implements A() {
@Override
public void cry() {
System.out.println("老虎叫~~");
}
};
*/
A a = new A() {
@Override
public void cry() {
System.out.println("老虎叫~~");
}
};
a.cry();
//获取运行内存名称
System.out.println(a.getClass());
}
}
interface A{
void cry();
}
12.5.基于类的匿名内部类
public class LocalInnerClass {
public static void main(String[] args) {
//1.编译类型是father
//2.带{}运行类型是匿名内部类(LocalInnerClass$2)
//3.不带{}运行内存是father
//源码
/*
class LocalInnerClass$2 extends Father{}
*/
Father father = new Father("jack") {
@Override
public void test() {
System.out.println("重写test");
}
};
father.test();
}
}
class Father{
public Father(String name){
super();
}
public void test(){
}
}
12.6.匿名内部类使用
12.7.匿名内部类实战
1.
public class LocalInnerClass {
public static void main(String[] args) {
//当做实参直接传递,简洁高效
II(new A() {
@Override
public void show() {
System.out.println("匿名内部类~~");
}
});
}
//静态方法,形参是接口类型
public static void II(A a) {
a.show();
}
}
interface A {
void show();
}
12.8.成员内部类
public class LocalInnerClass {
public static void main(String[] args) {
CallPhone callPhone = new CallPhone();
callPhone.say();
}
}
class CallPhone{
private int n1 = 10;
private String name = "张三";
class Inner{
public void show(){
System.out.println("n1= " + n1 + "name= " + name);
}
}
//写方法使用
public void say(){
//使用成员内部类
Inner inner = new Inner();
inner.show();
}
}
12.9.静态内部类
22.枚举
22.1.普通枚举
package com.cn.houserent;
public class Enum {
public static void main(String[] args) {
}
}
class Season {
private String name;
private String desc;
//定义了四个固定对象
public static final Season SPRING = new Season("春天","温暖");
public static final Season WINTER = new Season("冬天","寒冷");
public static final Season AUTUMN = new Season("秋天","凉爽");
public static final Season SUMMER = new Season("夏天","炎热");
//1.将构造器私有化
//2.去掉set方法,防止属性被修改
//3.在Season创建固定的对象
//4.优化:可以加入final修饰
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
// public void setName(String name) {
// this.name = name;
// }
// public void setDesc(String desc) {
// this.desc = desc;
// }
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
22.2.关键字枚举
package com.cn.houserent;
public class Enum {
public static void main(String[] args) {
}
}
enum Season {
//定义了四个固定对象
// public static final Season SPRING = new Season("春天","温暖");
// public static final Season WINTER = new Season("冬天","寒冷");
// public static final Season AUTUMN = new Season("秋天","凉爽");
// public static final Season SUMMER = new Season("夏天","炎热");
//如果使用了enum关键字来实现枚举类
//1.使用enum代替class
//2.public static final Season SPRING = new Season("春天","温暖")
//直接使用SPRING("春天","温暖") 解读 对象名/常亮名(实参列表)
//3.如果有多个常量,使用,间隔
//4.如果使用enum,要求将定义的对象写在最前面
SPRING("春天","温暖"),
WINTER("冬天","寒冷"),
AUTUMN("秋天","凉爽"),
SUMMER("夏天","炎热");
private String name;
private String desc;
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
javap:反编译
javac:编译
22.3.常用方法
23.注解
23.1.@Override

23.2.@Deprecated
23.3.@SuppressWarnings
23.4.四种元注解
24.作业
注:静态变量只会初始化一次
package com.cn.houserent;
public class TestVehicles {
public static void main(String[] args) {
Person person = new Person("唐僧", new Horse());
person.passRiver();
person.common();
}
}
interface Vehicles{
void work();
}
class Horse implements Vehicles{
@Override
public void work() {
System.out.println("一般情况用马");
}
}
class Boat implements Vehicles{
@Override
public void work() {
System.out.println("过河用船");
}
}
class Person{
private String name;
private Vehicles vehicles;
public Person(String name, Vehicles vehicles) {
this.name = name;
this.vehicles = vehicles;
}
public void passRiver(){
//得到船
if (!(vehicles instanceof Boat)){
vehicles = VehiclesFactory.getBoat();
}
vehicles.work();
}
public void common(){
//得到马
if (!(vehicles instanceof Horse)){
vehicles = VehiclesFactory.getHorse();
}
vehicles.work();
}
}
class VehiclesFactory{
private static Horse horse = new Horse();
public static Horse getHorse(){
return horse;
}
public static Boat getBoat(){
return new Boat();
}
}
25.异常
25.1.概念
25.2.异常体系图
注:
所有的运行时异常都在RuntimeException下面
所有的编译时异常都在FileNotFoundException下面
25.3.常见运行时异常
25.4.编译异常
25.5.异常处理
25.5.1.try~catch~finally
25.5.1.1final、finally、finalize之间有什么区别
25.1.1.2try~catch使用细节
25.5.2.throws处理异常
25.6.自定义异常
25.6.1.自定义异常步骤
25.7.throw和throws的区别
26.包装类
26.1.基本和包装类相互转换
26.2.练习
26.3.包装类方法
26.4.面试题
27.string
27.1.两张创建string对象的区别
27.2.测试题
27.3.string常用方法
28.stringbuffer
28.1.string和stringbuffer的对比
28.2.stringbuff的常用构造器
28.3.string、stringbuffer转换
28.4.测试题
29.stringbuilder
29.1.string、stringbuffer、stringbuilder对比
30.math类
30.1.常用方法
31.Arrays类
1.按照价格降序排序
Book[] books = new Book[4];
books[0] = new Book("红楼梦", 100);
books[1] = new Book("金瓶梅", 90);
books[2] = new Book("青年文摘", 5);
books[3] = new Book("西游记", 300);
Arrays.sort(books, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
return (int) (o1.getPrice() - o2.getPrice());
}
});
System.out.println(Arrays.toString(books));
2.按照书名的长度按照从大到小排序
public static void main(String[] args) {
Book[] books = new Book[4];
books[0] = new Book("红楼梦", 100);
books[1] = new Book("金瓶梅02", 90);
books[2] = new Book("青年文摘", 5);
books[3] = new Book("西游记111", 300);
Arrays.sort(books, new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
return o2.getName().length() - o1.getName().length();
}
});
System.out.println(Arrays.toString(books));
}
}
32.System类
33.BigIntger和BigDecimal
34.日期类
34.1.第一代日期类Date
34.2.第二代日期Calendar
34.3.第三代日期类
35.集合(Collection)
35.1.集合框架体系
Collection(单列集合)
Map(双列集合)
35.2.Collection接口和常用方法
遍历方式一:Iterator
36.List
36.1.ArrayList注意事项
36.2.ArrayList底层源码
//todo 集合要补
37.Collections工具类
38.泛型
38.1.泛型说明
38.2.泛型语法
38.3.泛型使用细节
38.4.泛型练习
public class TestVehicles {
public static void main(String[] args) {
MyDate myDate1 = new MyDate(1992, 9, 23);
MyDate myDate2 = new MyDate(1992, 9, 28);
MyDate myDate3 = new MyDate(1992, 9, 3);
Employee employee1 = new Employee("李代胜",50000,myDate1);
Employee employee2 = new Employee("李代利",50000,myDate2);
Employee employee3 = new Employee("李科",50000,myDate3);
List<Employee> employees = new ArrayList<>();
employees.add(employee1);
employees.add(employee2);
employees.add(employee3);
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee emp1, Employee emp2) {
//先按照name排序,如果name相同,则按生日日期的先后排序
//1.对传入的参数进行校验(emp1和emp2的运行类型是不是Employee)
if (!(emp1 instanceof Employee && emp2 instanceof Employee)){
System.out.println("类型不正确");
return 0;
}
//2.比较name
int i = emp1.getName().compareTo(emp2.getName());
if (i!=0){
return i;
}
//3.比较年份
int y = emp1.getBirthday().getYear() - emp2.getBirthday().getYear();
if (y != 0){
return y;
}
//4.比较月份
int m = emp1.getBirthday().getMonth() - emp2.getBirthday().getMonth();
if (m != 0){
return m;
}
//5.比较日
return emp1.getBirthday().getDay() - emp2.getBirthday().getDay();
}
});
for (Employee employee : employees) {
System.out.println(employee);
}
}
}
class Employee {
private String name;
private int sal;
private MyDate birthday;
public Employee(String name, int sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
class MyDate {
private int year;
private int month;
private int day;
public MyDate(int year,int month, int day) {
this.month = month;
this.day = day;
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public String toString() {
return "MyDate{" +
"month=" + month +
", day=" + day +
", year=" + year +
'}';
}
}
改进:birthday的对比,最好放到MyDate类去比较,封装性更改好
public class TestVehicles {
public static void main(String[] args) {
MyDate myDate1 = new MyDate(1992, 9, 23);
MyDate myDate2 = new MyDate(1992, 9, 28);
MyDate myDate3 = new MyDate(1992, 9, 3);
Employee employee1 = new Employee("李代胜",50000,myDate1);
Employee employee2 = new Employee("李代胜",50000,myDate2);
Employee employee3 = new Employee("李代胜",50000,myDate3);
List<Employee> employees = new ArrayList<>();
employees.add(employee1);
employees.add(employee2);
employees.add(employee3);
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee emp1, Employee emp2) {
//先按照name排序,如果name相同,则按生日日期的先后排序
//1.对传入的参数进行校验(emp1和emp2的运行类型是不是Employee)
if (!(emp1 instanceof Employee && emp2 instanceof Employee)){
System.out.println("类型不正确");
return 0;
}
//2.比较name
int i = emp1.getName().compareTo(emp2.getName());
if (i!=0){
return i;
}
return emp1.getBirthday().compareTo(emp2.getBirthday());
}
});
for (Employee employee : employees) {
System.out.println(employee);
}
}
}
class Employee {
private String name;
private int sal;
private MyDate birthday;
public Employee(String name, int sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}';
}
}
class MyDate implements Comparable<MyDate>{
private int year;
private int month;
private int day;
public MyDate(int year,int month, int day) {
this.month = month;
this.day = day;
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public String toString() {
return "MyDate{" +
"month=" + month +
", day=" + day +
", year=" + year +
'}';
}
@Override
public int compareTo(MyDate o) {
//1.比较年份
int y = year - o.getYear();
if (y != 0){
return y;
}
//2.比较月份
int m = month - o.getMonth();
if (m != 0){
return m;
}
//3.比较日
return day - o.getDay();
}
39.自定义泛型类
练习
40.自定义泛型接口
使用说明
1.接口中,静态成员不能使用泛型(接口成员变量都默认是静态的)
2.泛型接口类型在继承接口或者实现接口时确定
3.没有指定泛型,默认是Object类型
41.自定义泛型方法
1.泛型方法可以定义在普通类中,也可以定义在泛型类中
2.当泛型方法被调用时,类型必须被确定
3.public void eat(E e){},修饰符(public)后面没有<E,R...> void eat,那么方法不是泛型方法,而是使用了泛型
42.泛型练习
43.泛型的继承和通配符
44.泛型练习(JUnit使用)
public class TestVehicles {
public static void main(String[] args) {
User user = new User(1,25,"张三");
DAO<User> dao = new DAO<>();
dao.save("1",user);
System.out.println(dao.map);
User user1 = dao.get("1");
System.out.println(user1);
dao.update("1",new User(2,30,"李四"));
System.out.println(dao.map);
List<User> list = dao.list();
System.out.println(list);
dao.delete("1");
System.out.println(dao.map);
}
}
class DAO<T>{
public Map<String,T> map = new HashMap<>();
public void save(String id,T entity){
map.put(id,entity);
}
public T get(String id){
return map.get(id);
}
public void update(String id,T entity){
map.put(id, entity);
}
public List<T> list(){
Collection<T> values = map.values();
return new ArrayList<>(values);
}
public void delete(String id){
map.remove(id);
}
}
class User{
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.name = name;
this.id = id;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
44.1.junit
45.坦克大战(1.0)
46.java绘图坐标体系
47.绘图案例
public class TestVehicles extends JFrame {//对应窗口,可以理解成一个画框
private MyPanel mp;
public static void main(String[] args) {
new TestVehicles();
}
public TestVehicles(){//构造器
//初始化面板
mp = new MyPanel();
//把面板(画板)放入到窗口(画框)里面
this.add(mp);
//设置窗口的大小
this.setSize(400,300);
//当点击窗口的小×,退出程序
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);//可以显示
}
}
//1.定义一个MyPanel 继承JPanel(java提供),画图形就在面板上画
class MyPanel extends JPanel{
/**
* 理解:
*1.MyPanel可以理解成一个画板
*2.Graphics g 可以把g理解成一支画笔
*3.Graphics 提供了很多绘图的方法
*/
@Override
public void paint(Graphics g) {//绘图方法
System.out.println("paint 方法被调用");
super.paint(g);//调用父类方法完成初始化
//画一个圆形
g.drawOval(10,10,100,100);
}
}