1.1继承
概念: 面向对象的三大特征之一, 用来描述类和类的关系用的
- 好处:可以抽取子类共性的内容, 提高代码的复用性, 提高代码维护性,父类中定义非私有有的东西, "子类"可以直接使用的!!!!
- 弊端:子类和父类的耦合度增强, 父类一旦发生变化, 子类不得不一起跟着改变!!!!!
格式:
public class Fu{}public class Zi extends Fu{}
注意:
- 不能瞎用继承, 满足is a才可以!!!!是谁的一种的情况才能使用!!!!!
- java只支持单继承, 不支持多继承, 支持多层继承
因为子类可以使用父类的也可以使用自己的:
- 1.当子类的成员变量和父类的成员变量一样的时候, 使用的是子类的, 因为遵循了就近原则!!!!!!如果非要访问父类的成员变量,需要使用super关键字
- 不重要!!!!!因为以后父类的成员变量都会私有化, 是不能直接访问的!!!!!
- 2.当子类的成员方法和父类的成员方法一样的时候, 使用的是子类的, 因为遵循了就近原则!!!!!!如果非要访问父类的成员方法,需要使用super关键字
- 这个现象我们称为子类重写了父类的方法
- 为啥要重写????子类不是可以直接使用父类的非私有的方法吗???
- 使用场景:一般用于迭代更新!!!!保留原来的技术, 产出新技术, 不影响原来的使用, 也推出了新的使用!!!!
- 注意:我们可以通过@Override来校验是否正确重写, 就算没有这个注解, 如果满足重写的要求也算重写!!!!
- 3.子类一定要走父类的构造!!!!!!!为啥???如果你不走, 系统会默认帮你调用父类的无参构造, 系统为啥这样做???
- 子类随时都要使用父类的东西, 所以必须保证父类的数据在堆内存中初始化好才能使用, 所有一定要走父类的构造函数, 而且父类的构造要先走!!!!!!
- 如果父类没有无参构造, 则子类一定要手动调用父类的有参数构造, 总而言之, 言而总之, 子类是一定要走父类的构造!!!!!!!!!!!!!!!
- 使用场景:一般我们习惯, 子类的无参调用父类的无参, 子类的满参调用父类的满参!!!!!
- this用来调用本类的成员或者构造, 而super是用来调用父类的成员以及构造
1.2多态
概念: 面向对象的三大特征之一
特点
- 父类引用指向子类对象
- 父类 对象名 = new 子类();
- 动物 对象名 = new 猫();
前提:
- 1.必须有继承或者实现关系
- 2.必须有方法重写
- 因为多态只能看到父类的东西, 也只能使用父类中定义有的东西, 如果子类对方法没有重写的话, 干脆创建父类对象得了, 多态将毫无意义!!!!!
- 3.必须有父类引用指向子类对象
由于多态格式中即出现了父类也出现子类, 我们需要搞清楚访问的到底是谁
- 1.如果直接访问属性,我们看到的父类的属性,不能访问子类特有属性, 因为看不到!!!!
- 2.如果访问的功能, 我们走的是子类的功能, 不能访问子类特有功能
好处:
- 经常用来提高方法的扩展性, 将父类定义成方法的参数, 可以接受其所有的子类
弊端:
- 多态不能使用子类特有内容!!!!!!
- 方法定义者在定义的时候使用父类类型来接受, 他也不知道调用传入的到底是哪个子类,所有只能使用父类中的共性内容不能使用特有内容!!!!!
- 如何解决(一般不用):
- 向下转型
- 子类类型 对象名 = (子类类型)父类引用;
- Fu fu = new Zi();
Zi zi = (Zi)fu;
2.权限修饰符
- public:本类, 本包, 不同包的子类, 不同包的无关类
- protected:本类, 本包, 不同包的子类
- 什么都不写:本类, 本包
- private:本类
2.1final
修饰符, 可以修饰类, 变量, 方法
- 1,修饰类:这个类是最终类, 不能在有子类,所有的内容都不能被重写!!!!
- 2.修饰方法:这个方法不能重写了!!!!!
- 3.修饰变量
- 修饰局部变量
- 变量有且只能被赋值一次!!!!!
- 命名规范一般和普通变量命名规范一致!!!!!!
- 修饰成员变量
- 变量有且只能被赋值一次!!!!!
- 直接赋值(推荐的)
- 通过构造赋值(极其不推荐!!!!)必须保证每一个构造都要对final修饰的成员变量赋值才可以!!!!!!
- 命名规范需要大家每个单词每个字母都要大写, 多个单词之间用_隔开!!!
- 例如:int NUMBER = 10; int MAX_AGE = 100;
- 被final修饰的变量就是常量!!!!!!
- 使用场景:可以让普通的常量更具备可读性!!!!!!!
2.2static
修饰符:修饰成员变量成员方法
修饰成员变量
- 被这个类所有的对象所共享!!!!!
- 可以使用类名.方式访问
- 可以使用类名.方式访问
特点:
- 1.随着类的字节码的加载而初始化
- 2.被所有对象所共享,属于整个类共享的数据
- 3.可以直接拿类名去使用, 不需要依附对象, 而且也建议大家通过类名的方式来访问!!!!
- 4.随着类的加载而加载, 随着类而消失, 驻留内存中时间比较长, 用慎用!!!!!!
- 5.静态的只能访问静态
2.3abstract
抽象的, 是一个修饰符:可以修饰类和方法
修饰类:
- 成为抽象类
- 特点:抽象类无法直接创建对象使用!!!!因为抽象类中可能含有抽象方法, 因为抽象方法是没有方法体的, 是一个残缺的方法,残缺的方法不能用!!!!!
- 如何使用抽象类????
- 1.定义抽象类的子类
- 2.让子类完成(重写)残缺的方法(抽象方法)
- 3.创建子类对象来去使用!!!!
- 和普通类对比, 仅仅只是可以多定义一个东西,就是抽象方法, 剩下的和普通类一模一样!!!!!!
修饰方法:抽象方法
- 特点:没有方法体!!!
- 有抽象方法的类必须是抽象类!!!!!
abstract和那些关键字是冲突的
- private
- private abstract void method();
- 典型错误, 因为private关键字不能被子类直接看到, abstract是强制子类重写, 子类不能重写父类的私有方法!!!!!
- final
- public final abstract void method();
- 典型错误, final不让子类重写, 而abstract必须要子类重写!!!!!冲突!!!!!
3.接口
1.如果定义接口
public interface 接口名{
//自定义常量
//抽象方法(重要的!!!!!!!)
//默认方法
//私有方法
//静态方法
}
2.定义接口内容:可以定义抽象方法
3.接口的特点
- 1.由于里面可能含有抽象方法, 所以不能直接使用!!!!
- 1.定义一个类去实现接口 implements
- 2.重写他所有的抽象方法
- 3.使用接口的实现类
- 2.接口中的成员变量默认被public static final修饰
- 3.接口中没有构造函数的概念(构造函数的作用的在堆中对成员变量进行初始化用的!!!!)
- 4.接口中的方法默认被public abstract修饰
- 在JDK1.8以及之后可以定义默认方法
- 作用:
- "接口升级比较难受", 于是在jdk1.8的时候可以这样定义默认解决接口升级的问题
- 使用场景:只有当接口中的升级的方法都一样的话, 才会使用默认方法!!!!!
- 在JDK1.8以后可以定义静态方法
- 在JDK1.9的时候可以定义私有方法
3.1类和接口的关系
- 类和类
- 类和接口
- 接口和接口
- 多继承
- 为啥没有冲突?因为接口当初设计的时候只有抽象方法, 抽象方法是没有方法体, 所有没有冲突!!!!!
3.2接口和抽象类
- 抽象类的定义规则和规范的范围是强制所有的"子类" 必须实现(重写)抽象方法
- 接口的定义规则和规范的范围, 所有的实现该接口的实现类,灵活比较高,可以让类选择性的实现!!!!!!
4.内部类
概念:定义在类中的类我们成为内部类!!!!!
特点:内部类可以直接访问外部类的成员甚至私有, 但是外部类不能直接访问内容的东西!!!!!
分类:
4.1成员内部类
位置:在类中方法外
格式:
public class Outer{
class Inner{
}
}
直接使用
- Outer.Inner 对象名 = new Outer().new Inner();
- 对象名.使用其内容
间接使用
好处:可以直接使用外部类的成员甚至私有!!!!!
4.2局部内部类
位置:定义在方法中的类
格式:
public class Outer{
public void method(){
class Inner{
}
Inner i = new Inner();
i.内容
}
}
总结:没有什么卵用!!!!!
4.3匿名内部类
本质: 创建一个已知类或者已知接口的子类或者实现类对象
作用:简化子类或者实现类的创建的
格式:
new 已知类|已知接口(){
方法重写!!!!!
}
注意事项:
- 如果要重写的方法操作4个, 就不太建议使用匿名内部类, 否则看起来很臃肿不利于阅读
- 如果要重写方法代码比较多, 不推荐大家使用匿名内部类
5.lambda
他是jdk1.8以及之后才能使用的技术
完整格式:
(抽象方法参数列表)->{
对抽象方法的重写
}
省略格式:
- 1.参数列表的数据类型可以省略, 要省都省!!!!!
- 2.参数只有一个的时候,()可以省略!!!!
- 3.方法体只有一句的时候, {}可以省略, 但是如果{}省略return和;都要跟着一起省略
使用前提:面向接口, 而且要求接口中有且只有一个抽象方法的时候才能使用lambda!!!!!
原则:可推导可省略
记住一个快捷键:alt + enter可以直接将匿名内部类转换成lambda
6.代码块
概念: 可以写代码的区域我们成为代码块!!!!!!
分类:
- 局部代码块
- 构造代码块
- 静态代码块
- 格式:static {
代码
} - 位置:类中方法外
- 特点:随着类的加载而加载, 只会执行一次!!!!!!!
- 作用:后期一般用于加载配置文件 , 或者执行一次性的操作
6.1同步代码块
7.包装类
概念: 其实就是基本数据类型对应的引用数据类型
在jdk1.5的时候, 出现了自动拆装箱, 我们完全可以把int看成Integer, 把Integer看成int
注意:
- 包装类毕竟是引用数据类型, 可以被赋值为null,所以在使用的要避免空指针异常!!!!!
包装类现在唯一的作用:
- 可以实现字符串和基本数据类型的互转
- 基本类型 ----> String:基本类型+"" 搞定
- String ----> 基本类型
- int Integer.parseInt(String number);
- double Double.parseDouble(String number);
- Long.parseLong(String number);
7.1StringBuilder
前提:
- 字符串是不可改变的字符序列, 他一旦创建不能更改, 也并不具备拼接的能力, 我们采用+, 或者+= 拼接字符串其实底层使用的StringBuilder的append拼接的功能完成!!!!
String +或者+=为什么慢????
- 因为String没有拼接的能力, 底层每次拼接都需要创建StringBuilder对象来完成, 拼完后还得转回为String才可以, 每次拼接都需要大量的对象需要创建比较浪费时间!!!!!
StringBuilder:可以改变的字符序列,作用用来提高字符串的拼接效率!!!!!
构造
- StringBuilder()
- 创建StringBuilder里面没有字符
- 相当于: String s = ""
- StringBuilder(String str)
- 创建StringBuilder里面维护初始化字符串内容
- String s = "abc";
功能
- StringBuilder append(任何类型)
- 将内容拼接到StringBuilder里面!!!!!!,返回的依然本类对象
- String toString()
- 将StringBuilder的内容转回成String类型
如何将StringBuilder转回String
8.数组的高级操作
二分查找(折半查找)
冒泡排序
Arrays的工具类:
- static int binarySearch(double[] a, double key) 二分查找!!!
- static void sort(byte[] a) 对数组进行排序
- static String toString(数组)
9.递归
现象: 方法调用自己的现象我们成为递归
作用: 类似于循环!!!!!!
注意实现:递归有出口, 否则会报StackOverFlowError ----> 栈内存溢出
建议:能用循环就用循环解决, 不能循环在考虑递归!!!!!!
主要解决不确定循环层数的这种需求!!!!!!
求阶乘:
- 如何求1000的阶乘
-
9.1BigInteger(大整数)
- 构造:BigInteger(String val)
- 作用:用来计算超级大的整数, 原理是底层基于字符串, 么有长度限制!!!!!
- 功能:
- BigInteger add(BigInteger augend)
- 一个BigDecimal和另外一个BigDecimal的对象进行相加, 返回新的BigDecimal,老的不变!!!!
- BigInteger subtract(BigInteger subtrahend)
- 一个BigDecimal和另外一个BigDecimal的对象进行相减, 返回新的BigDecimal,老的不变!!!!
- BigInteger multiply(BigInteger multiplicand)
- 一个BigDecimal和另外一个BigDecimal的对象进行相乘, 返回新的BigDecimal,老的不变!!!!
- BigInteger pide(BigInteger pisor)
- 一个BigDecimal和另外一个BigDecimal的对象进行相除, 返回新的BigDecimal,老的不变!!!!
- 必须能够被除尽才能使用该方法!!!!!
10.异常
概念: 用来描述程序的不正常的情况, 异常不是语法错误!!!!!
体系:Throwable
- Error(错误)
- 一般情况我们程序员式没有办法通过代码修改, 一般是硬件问题!!!!!
- Exception(异常)
- 编译时异常
- 特点: 在编译期间就会报错, 必须手动处理的异常
- 分类:除了运行时异常都是编译时异常
- 运行时异常
- 特点: 在运行期间才会报错, 编译期间不用处理!!!!
- 分类:RuntimeExcption以及其子类都是运行时异常
自己处理异常
- 将异常抛给调用者处理!!!
- 通过 throws关键字见异常声明到方法的声明上面, 告知调用者你可能产生的异常, 起到警示的作用!!!!!!!!!
- 格式
- throws 异常类名1,异常类名2 ......
- 捕获异常
-
try{
//可能会出现问题的代码
//以及出现问题后不需要执行的代码
}catch(异常类型 异常名){
//出现问题后的提示
}....
catch(异常类型 异常名){
//出现问题后的提示
}
-
作用:不让程序终止!!!!!!!!
-
流程:catch是中国好备胎, 当try里面出现问题后, 会根据异常类型从上往下匹配catch,一旦匹配成功执行对应的catch的语句, 然后try语句执行完毕
-
注意事项
-
1.一个try可以配很多catch
-
2.catch的异常类型如果有子父类关系, 父类的异常类型应该定义在下面, 否则会报错
-
3.如果catch都不匹配, jvm帮我们处理, 但是jvm只会处理运行时异常 ,如果编译时必须得处理
-
快捷键:ALT+CTRL + T
throw和throws的区别
throw
- 作用: 制造异常, 终止方法
- 位置:在方法里面用的
- 跟的异常对象, 只能跟一个
- 使用场景:一般用于校验参数的合法性
throws
- 作用:声明异常, 告诉调用者方法可能产生的异常
- 位置:方法的声明上
- 跟的异常类型, 可以跟多个!!!
异常的方法
- 观察发现所有的异常都是类名不一样而已, 功能都是从父类中继承下来,所有我们学习Throwable的功能即可
- void printStackTrace()
自定义异常
- 本质:就是让异常类名更具备见名知意的效果!!!!!
- 步骤
- 1.定义一个类去继承Exception或者RuntimeException, 然后起一个见名知意的名字即可
- 2.根据父类构造生成自己的构造即可
11.时间
基础知识:时间原点,1970-1-1 0点0分0秒,世界标准时间, 我们国家处于东八区, 1970-1-1 8点0分0秒
11.1Date
包:java.util
看构造:
- Date(); 代表当前系统时间
- Date(long 毫秒值) 代表指定时间, 从1970-1-1 8:0:0 距离的毫秒值
功能:
- long getTime(); 获取里面内置的毫秒值
- void setTime(long 毫秒值) 修改毫秒值
11.2SimpleDateFormat
作用: 用来实现 Date和String之间的互转
包:java.text
看构造:SimpleDateFormat(String format);
- "yyyy-MM-dd HH:mm:ss"
- "yyyy年MM月dd日 HH:mm:ss"
功能:
- Date ----> String
- String format(Date date)
- 将给定的Date转成 指定的字符串
- 底层算出各个时间, 然后通过字符串的replace方法替换成指定的位置的内容实现的
- 作用: 就是让时间让大众都能理解
- String ---> Date
- Date parse(String source)
- 要求你的字符串和模式需要匹配才行, 否则就会报ParseException
为啥要实现String ---> Date之间互转啊????????
- Date ---> String 让时间更具备阅读星
- String ---> Date 为了让操作时间更方便, 因为date有毫秒值
12.集合
对比数组:
- 1.集合的长度可以改变,动态扩容
- 2.只能存储"引用数据类型",不能存储"基本数据"类型
Collection(接口)
- List(接口)
- ArrayList 构造 ArrayList<填写集合存储的数据类型>();
- <>里面是泛型, 要求必须是引用数据类型
- Student[] ArrayList<Student>
- LinkedList
- Set(接口)
Collection的公共方法
- boolean add(E e); 添加元素
- boolean remove(Object obj);
- 根据元素删除, 删除满足条件的第一个元素!!!!
- 在使用迭代器遍历集合的时候, 不能使用集合的方法对集合进行增删操作否则会报java.util.ConcurrentModificationException
- void removeIf(Predicate<E> pre);
- 发现接口只有一个抽象方法, 可以匿名内部类, 使用lambda
- boolean contains(Object obj) 判断集合中是否包含某个元素
- void clear(); 清空集合,让集合的长度变为0
- boolean isEmpty(); 判断集合是否长度为0
- int size() 求集合中元素的个数
- Iterator<E> iterator()
- 获取迭代器 Iterator
- boolean hasNext(); 判断是否有元素
- E next(); 取出元素!!!!
- E remove();
- 删除迭代器指针对应的元素
- 使用迭代器遍历集合的时候, 只能使用迭代器的方法进行删除, 不能使用集合的方法
- 因为如果使用集合删除, 则可能会出现隔过的情况!!!!!!!, 这样的功能是有bug的!!!!
- 迭代器底层是记录了一个modCount的值, 记录增删的次数, 如果你采用集合的方法进行了增删会导致modCount++, 但是expectedModCount的值不变,这两个值一旦不一样, 就会产生异常!!!!!
- 为什么迭代器的remove方法就不会出现异常????
- 因为迭代器的删除有cursor指针回退, 而且会将modCount的值同步给expectedModCount,不会出现隔过的情况, 当然不会出现异常!!!!!
- 示例
- //2.借助迭代器遍历集合
Iterator<String> it = coll.iterator();
//3.借助迭代器的方法, 遍历集合
while (it.hasNext()){
String next = it.next();
System.out.println(next);
}
- 所有实现迭代器接口都可以使用增强for
- for(元素的数据类型 变量名: 集合|数组){
变量名
} - 注意事项
- 底层采用的迭代器, 不能使用集合的方法对集合进行增删, 只能查看!!!!!!!或者元素中的内容, 因为看不到迭代器对象
list
特点:
- 1.有序,存储的顺序和取出的顺序
- 2.可以存储重复元素
- 3.有索引
特有的方法
- void add(int index, E e);
- 在指定位置上添加元素, 原来的以及后面要顺延一位!!!!!
- 插入元素
- E remove(int index);
- 删除指定索引的元素, 删除完, 后面的索引的元素会往前顺延!!!!!
- E set(int index, E newE);
- E get(int index);
- 根据索引获取元素
- 可以用遍历集合
- for(int i = 0; i < 集合.size(); i++){
元素 = 集合.get(i);
}
- 注意: 一旦牵扯到索引就要注意索引越界
Set
特点:
- 1.大部分无序
- 2.不可以重复(去重)
- 3.没有索引
- 所有的功能都是从Collection中继承下来的, 没有任何特有的方法
TreeSet
可以对元素进行排序
结论: 如果存储的自定义类型, 必须指定排序的规则才可以!!!!!
- 自然排序
- 让自定义类实现Comparable接口,重写compareTo方法, 在里面定义排序规则, 其中this代表当前正在添加的元素, o代表是集合中元素
- 比较器排序
- 在创建TreeSet的时候传入比较器, Comparator, 重写里面的 compare(o1, o2), 其中o1代表正在添加的元素, o2代表集合中元素
- 在TheeSet中比较器的优先级更高一点, 因为底层优先判断是否有比较器, 如果有按照比较器的规则来排, 如果没有比较器, 才会走有类里面的compareTo方法比较!!!!
去重标准
- 只和比较的值是否为0有关系, 为0则认为重复!!!!!, 不为0认为不重复排序
- 缺点:相同内容的, 可能比较的值为0, 怎认为是重复就给去重了!!!!, 这样现实生活中可能跟这个需求有违背, set集合没有索引操作起来很不方便!!!!
原理:
- 特点:增删慢, 查询快!!!!!!
- 底层基于树形结构
Collections(Arrays)
- static void sort(List<T> list) 自然排序, 要求自定义类和Comparable有关系
- static <T> void sort(List<T> list, Comparator<T> c) 比较器排序规则
13.数据结构
作用: 规定了数据的存储的机构
类型
- 栈
- 先进后出 我们现实中使用较少!!!不是很常见
- 栈内存就是基于栈结构, 每当新的方法被调用, 新的方法执行完后, 老的才会执行
- 队列
- 数组
- 查询快, 增删慢
- 因为有索引,可以快速定位到想要查找的元素, 数组的长度不可以改变 , 一旦添加或者删除需要创建新的数组, 将老的数组的元素复制一份到新数组中,所以增删比较慢
- 连续的空间, 0索引旁边一定是1索引的元素
- ArrayList
- 链表
- 查询慢,增删块
- 查询慢, 因为已知都是头节点或者尾节点, 要么从头查, 要么从尾, 所以很慢
- 增删快 不用牵一发动全身, 只需要断开两个节点的关系即可
- 散列结构, 底层是通过记录地址的方式链接起来
- LinkedList 特有方法 一对操作首尾的操作!!!!!!
- 红黑树结构
- 哈希表结构