DAY08
复习:
1. 构造方法:
特点:与类同名而没有返回值类型
作用:用于创建对象
当类中没有手动指定构造方法的时候在编译的时候自动添加一个无参构造
2. this关键字:代表本类的在活动的对象,用于在本类中调用本类的方法和属性 --- this语句,表示调用本类中其他的对应形式的构造方法,必须放在首行
3. 代码块:
构造代码块:在创建对象的时候先于构造方法执行一次 --- 用于完成一些初始化操作
局部代码块:提高栈内存的利用率
4. 封装:
体现形式:方法、类(属性的私有化 -> 将属性设置为private,对外提供对应的get/set的方法,在方法中可以进行限定使数据更加符合场景要求)
优势:提高复用性,保证数据的合法性
5. 继承 :用extends关键字来完成继承关系 --- 支持的类与类之间的单继承 --- 单继承和多继承的优劣性 --- 提高复用性,避免方法调用产生歧义--- 子类可以继承父类全部的数据域,但是只有一部分可见
6. 多态:
编译时多态:方法的重载
运行时多态:
向上造型:用父类来声明用子类来创建--- 对象能干什么看的是父类,对象如何执行方法看的是子类。
方法的重写(Override):父子类中存在了方法签名完全相同的非静态方法。--- 两等两小一大
7. 权限修饰符:public
protected 默认 private --- protected在子类中使用的时候指的是在对应的子类中使用,不能跨子类使用
8. super关键字:在子类中表示父类对象的引用,用于调用父类中的方法和属性 --- super语句,表示在子类的构造方法中调用父类对应形式的构造方法。子类构造方法中如果没有手动指定super语句,那么默认调用父类无参构造(super());如果父类只提供了含参构造,那么子类的构造方法中必须手动提供对应形式的super语句
static - 静态
修饰符 - 用于修饰数据、方法、代码块以及内部类
静态变量
用static修饰变量,称之为静态变量,也叫类变量。在类加载的时候加载到了方法区,并且在方法区中被赋予了默认值。静态变量是先于对象出现的,所以习惯上是通过类名来调用静态变量。每一个对象存储的是这个静态变量在方法区中的地址,所以静态变量是被这个类的所有对象所共享的
静态变量能否定义到构造方法中?---不能。静态变量是在类加载的时候出现,先于对象出现。构造方法在创建对象的时候执行。
注意:
1. 类是加载到方法区中的
2. 类是在第一次使用的时候才加载,加载之后就不会移除
[if !vml]
[endif]
练习:定义一个类,统计这个类创建对象的个数
静态方法
用static修饰的方法,称之为静态方法。静态方法随着类的加载而加载到方法区中,但是在方法区中不执行只存储,在方法被调用的时候到栈内存执行。静态方法先于对象存在,所以习惯上是通过类名来调用静态方法。
main Arrays.sort() System.arraycopy()
静态方法中可以定义静态变量吗?--- 不能 --- 静态方法在调用的时候执行,静态方法执行的时候里面的变量才能初始化;静态变量是在类加载的时候初始化
静态方法中能否使用this/super?--- 不行 --- this代表当前在活动的对象,静态方法先于对象存在
能否在静态方法中直接使用本类中的非静态方法/非静态属性?--- 不行
public class A {
int i = 5;
public static void m(){
int j = (this.)i;
}
}
静态方法可以重载吗?---可以
静态方法可以被继承吗?---可以
静态方法可以重写吗?---不可以
静态方法虽然不能被重写,但是父子类中可以存在方法签名一致的静态方法 --- 静态方法的隐藏(hide)
注意:父子类中可以存在方法签名一致的方法,要么都是非静态(重写)要么都是静态(隐藏)
静态代码块
用static{}包起来的代码 --- 在类加载的时候执行一次
执行顺序:父类静态 -> 子类静态 -> 父类非静态 -> 父类的构造方法 -> 子类非静态 -> 子类的构造方法
[if !vml]
[endif]
DAY09
复习:
1. static:
静态变量:在类加载的时候加载到方法区,在方法区中被赋予默认值。静态变量比对象先出来,所以习惯上通过类名来调用。所有对象存的是这个静态变量的地址,所以所有对象共享同一个静态变量。
静态方法:随着类的加载而加载到方法区,在方法区中只存储不执行,在被调用的时候到栈内存中执行。静态方法先于对象出现,所以习惯上也是通过类名来调用。静态方法中不能使用this/super,也就意味着在静态方法中不能直接使用本类中的非静态。静态方法可以重载,可以被继承,不能重写,可以隐藏。
静态代码块:用static{}定义,在类加载的时候到栈内存中执行。--- 执行顺序:父类静态 - 子类静态- 父类非静态 - 父类构造方法 - 子类非静态 - 子类构造方法
注意:能够执行Java程序的内存块只有栈内存。
2. final:
常量:定义好之后值不可变
最终方法:可以被重载可以被继承但是不能被重写/隐藏
最终类:不能被继承
abstract
如果一个类的所有子类都对这个类中的某个方法做了重写,那么这个时候这个类中的对应的方法可以不定义方法体,需要用abstract修饰方法,从而成为了一个抽象方法。抽象方法所在的类必须是抽象类。--- 抽象类中不一定有抽象方法
抽象类不能创建对象,可以声明对象;接口也可以声明对象。
抽象类一定不是最终类
注意:任何一个类都有构造方法
抽象方法没有方法体,一定要被重写。
抽象方法可以定义被static/final/private修饰吗?---不行
抽象方法一定不能定义在最终类中。
如果一个类中的抽象方法用的是默认权限,对子类有什么要求?--- 要求父子类要同包
练习:定义一个类表示形状,提供获取周长和面积的方法,然后给这个类提供子类:矩形 - 正方形,椭圆 - 圆形
interface --- 接口
接口中定义都是抽象方法(JDK1.8以前)。类和接口之间用的是implements关键字来产生关联 --- 实现。类在实现接口之后需要重写接口中所有的抽象方法
接口不允许被实例化,也没有构造方法
在Java中,支持的是类和接口之间的多实现 --- 一个类可以实现多个接口
在Java中,支持接口之间的继承,而且接口之间是多继承
从JDK1.8开始,接口中允许定义实体方法 -- 这个是实体方法必须用default修饰
如果一个接口中只定义了一个抽象方法,那么把这个接口声明为函数式接口,用@FunctionalInterface定义 --- 也是JDK1.8的特性之一
内部类
方法内部类
定义在方法中的类 --- 方法/局部内部类 --- 为了重复使用某段逻辑,并且使这段逻辑只从属于某一个方法使用
成员内部类
定义在类中类
Outer2.Inner2 oi2 = new Outer2().new Inner2();
静态内部类
用static修饰的内部类
Outer3.Inner3 oi3 = new Outer3.Inner3();
匿名内部类
匿名内部类本质上是实现了对应的接口或者是继承了对应的类
任何一个接口都可以存在匿名内部类形式
一个类只要可以被继承,那么就可以存在匿名内部类形式 --- 最终类不存在匿名内部类形式
扩展:类中可以定义类,类中也可以定义接口,接口中可以定义类,接口中也可以定义接口 --- 如果类中定义了接口或者是接口中定义了接口,那么称之为内部接口 --- 类中定义的接口,以及接口中定义的类和接口默认都是静态的
class A {
static interface A1 {}
}
interface B {
static class B1 {}
static interface B2{}
}
包
声明包用的是package --- 区分同名类,进行功能的划分
导入包用的是import --- 导包的作用是用于提示代码从哪儿去找这个类
* 表示导入当前包下的所有的类但是不包括子包下的类
java --- 原生包
javax --- 扩展包
org --- 第三方厂商提供的一些常用的包
java.lang - 核心/基本包,包含了Java程序运行需要的基本类。在Java程序启动的时候,包下的类就已经自动加载到内存中,所以使用的时候可以不用导包
java.util - 工具包
java.math - 数学运算
java.io - 数据传输
java.net - 网络通信
java.nio - 高并发
java.text - 格式化
总结:java.lang包下的类以及同包类在使用的时候可以不用导包
垃圾分代回收机制
针对的是堆内存。
Java中的每种数据类型大小都是确定的,所以所有的内存是由Java自己进行分配,意味着内存的管理和回收也是由JVM自己进行---在Java中一旦产生内存问题导致程序员无法处理。理论上在正常情况下Java中的堆内存是足够使用的 --- 当堆内存使用的负荷量(一般情况下70%)超过一定限度的时候,会启动垃圾回收器(Garbage Collector ---
GC)进行堆内存的回收释放
Heap space
YoungGeneration
eden
survivor
fromspace
tospace
Old Generation
扩展:eden:from:to = 8:1:1
对象刚创建的时候是先放入新生代中的伊甸园区;如果在伊甸园区经过一次回收依然存在,那么将这个对象挪到幸存区,在幸存区中经过多次回收这个对象依然存在则挪到老生代。在回收的时候先回收新生代,如果新生代回收之后的内存足够使用则不扫描老生代;如果不够则扫描老生代。老生代的扫描频率要低于新生代
发生在新生代的回收 --- 初代回收minor gc
发生在老生代的回收 --- 完全回收full gc
扩展:对象创建完成之后会先试图放入新生代;如果新生代经过回收之后也放不开,则直接试图将该对象放入老生代。老生代如果也放不开,则会出现错误--- OutOfMemoryError
API --- Application Programming Interface --- 应用程序接口 --- 接口以及实现类
DAY10
.
复习:
1. abstract:
抽象类:不能实例化,但是类中有构造方法。子类继承了抽象类之后必须重写其中的抽象方法。抽象类不能用final修饰
抽象方法:没有方法体。必须在子类中被重写。可以重载。不能用static/final/private修饰
2. interface:
类和接口之间用implements关键字来完成实现关系。类在实现接口自后需要重写接口中所有的抽象方法。在JDK1.8以前,接口中只能定义抽象方法 --- 默认用public abstract修饰。接口中可以定义属性但是默认使用public
static final修饰。从JDK1.8开始,接口中允许定义实体方法,必须用default修饰,也可以定义静态方法。
接口与类之间是多实现,接口之间是多继承
作用:作为模板或者是协议、约束等来使用。
3. 内部类:
方法内部类、成员内部类、静态内部类、匿名内部类
除了静态内部类以外,其余的内部类中都不允许定义静态变量和静态方法
除了静态内部类以外,其余的内部类可以外部类中的非静态属性和非静态方法
方法内部类使用当前方法中的数据的时候,要求这个数据得是一个常量。
匿名内部类本质上是实现了对应的接口或者是继承了对应的类。所以任何一个接口都可以产生匿名内部类,任何一个可以被继承的类都可以产生匿名内部类。
4. 包:
声明包用的是package,作用:区分同名类,进行功能/模块的划分
导入包用的是import,给要使用的类指定查询路径的。 --- * 表示导入当前包下的所有的类但是不包括子包下的类
在使用java.lang包以及同包下的类可以不用导包
5. 垃圾分代回收机制:
针对堆内存。
对象一开始是先放到新生代的伊甸园区,在伊甸园区经过依次回收如果依然存在则挪到幸存区,在幸存区如果经过多次回收依然存在则挪到老生代。在回收时先扫描新生代,如果释放的空间足够则不扫描老生代。
初代回收 完全回收
如果一个对象在新生代存放不开,则会试图进行一次回收,如果经过回收依然在新生代存不开,则直接试图放入老生代。
Object
顶级父类。任何一个类都将Object作为父类,也就意味着任何一个对象都可以赋值给Object对象。Object类也是Java中唯一的一个没有父类的类。
重要方法
clone() --- 如果一个对象要想被克隆,那么这个对象所对应的 类必须实现接口--- Cloneable --- 这个接口中没有任何的方法和属性仅仅起标志性的作用
finalize() --- 通知GC回收垃圾,GC不一定启动
练习:定义一个类表示用户,重写其中的equals方法
class User {
private Stringusername;
private Stringpassword;
}
String
最终类。代表字符串的类,所有的字符串都是String的对象。
字符串是一个常量,定义好之后不可改变。
因为字符串是一个常量,所以它是被共享的 --- 只要值相同,用的都是同一个字符串
字符串本质上是一个不可变的字符数组
[if !vml]
[endif]
[if !vml]
[endif]
String str = “abc”; --- 1
String str = new String(“abc”); --- 2
String str = “a”; --- 1
str = str + “b”; ->
str = new StringBuilder(str).append(“b”).toString(); - 4
String[] strs = {/* 100个元素*/};
// 将字符串数组中的所有元素进行拼接
// 使用+进行拼接 --- 整个过程要产生301个对象
String str = “”; // 1
for(String s : strs)
str += s; // 每拼接1次要额外产生3个对象,拼接100次要额外产生300个对象
// 使用StringBuilder进行拼接 --- 整个过程中要额外产生102个对象
StringBuilder sb = new StringBuilder(); // 1
for(String s : strs)
sb.append(s); // 每拼接1次要额外产生1个对象,拼接100次要额外产生100个对象
String str = sb.toString(); // 1
如果拼接的字符串个数比较多,建议使用StringBuilder;如果个数比较少的话可以使用+
练习:
1. 输入字符串,然后再输入2个数字(一个表示起始位置,一个表示结束位置),按照指定的数字截取一个子字符串
gahodnlasfho 2 5 -> hod
2. 输入一个字符串,统计字符串中字母、数字和其他符号的个数
3. 输入一个字符串,将其中的数字提取出来并求和
dsho353sdhiha89dnso4 -> 3+5+3+8+9+4 = 32
4. 输入一个字符串,将其中的数字提取出来并进行升序排序
dsho353sdhiha89dnso4 -> 353894 -> 334589
5. 输入一个字符串,统计其中每一个字符出现的次数
sdhaofnaadsg -> s:2 d:2 h:1 a:3 o:1 f:1 n:1 g:1
DAY11
复习:
1. Object:顶级父类。任何一个类都将Object作为父类使用,也因此所有的对象都可以赋值给Object对象 --- Lambda表达式不能直接赋值给Object --- getClass:获取对象的实际类型;equals:比较两个对象是否相等。比较的时候默认是比较的两个对象的地址,但是实际中往往要重写(地址、参数、类型、属性);toString:当打印对象的时候最底层往往是调用对象的toString
String
最终类。代表字符串的类。
底层是依靠字符数组来存储数据并且该字符数组定义好之后不可变 --- 只要是值一致的字符串在方法区中用的一定是同一个
当进行字符串的拼接的时候如果个数比较少可以使用+;如果个数比较多建议使用StringBuilder
注意:在String中提供了一系列操作而不改变原字符串的方法,大部分都是产生了一个新的字符串
instanceof --- 判断对象和类的关系的
只要前边的对象是后边的类/子类/接口/子接口产生的实例,就返回一个true
“abc”instanceof String --- true
new Person() instanceof Object --- true
“abc”instanceof Serializable ---true
练习:输入一个字符串和一个数字,数字表示字节个数,根据指定的字节个数切割字符串(GBK)
接口interface 4->接口 7->接口int 3->接
练习:输入2个字符串,打印第二个字符串在第一个字符串中出现的所有的位置
vagaophgao a -> 1 3 8
expression-正则表达式- REGEX
Pattern --- 适用于完成筛选和过滤的操作
练习:
1. 输入一个字符串,然后判断字符串是否是一个小数字符串
10.28 0.56 3.00 13.85 15. 00.65
2. 校验密码:8-20位,小写字母/大写字母/数字中的至少两种
DAY 12
复习:
1. String:最终类,常量,以字符数组形式来存储数据 ---操作不改变原字符串
Pattern
指定规则进行范围性/模糊匹配
在正则中用()将某一块作为一个整体来操作 --- 捕获组
Java中的正则会对其中的捕获组进行编号,从1开始 --- 从( 开始计算
练习:
1. 邮箱格式的校验:
2607509766@qq.com langang@163.com
langang@tedu.cn langang@sina.com.cn
2. 输入一个字符串,统计其中每一个字符出现的次数
3. 对于任意的字符串可以认为是由多组叠字或者是单字来拼成的,这每一组叠字/单字都是字符串的碎片,计算一个字符串平均的碎片长度
aaabbbbbcddaaacc -> aaa bbbbb c dd aaa cc -> (3+ 5 + 1 + 2 + 3 + 2) / 6 = 2.67
包装类
byteshortintlongfloatdoublecharbooleanvoid
ByteShortIntegerLongFloatDoubleCharacterBooleanVoid
基本类型身上没有属性和方法让便捷的操作数据,因此针对每一种基本类型提供了对应的类形式 --- 包装类
Void是最终类,不能被实例化
当把基本类型的变量直接赋值给对应的引用类型的对象 --- 自动封箱,底层是调用了对应类身上的valueOf方法
当把引用类型的对象直接赋值给对应的基本类型的变量 --- 自动拆箱,底层是调用了对应对象身上的**Value方法
四种整数型都有范围判断(-128~127)
注意:凡是Number的子类都会提供将字符串转化为对应类型的构造方法
包装类产生的对象的哈希码是固定的,不随环境改变
注意:字面量的哈希码是不随环境不随系统而改变
数学类
Math --- 最终类,针对基本类型提供了基本的数学运算
BigDecimal --- 能够精确运算小数,要求参数以字符串形式传递
DecimalFormat --- 进行数字的格式化的类
BigInteger --- 能够计算任意大的整数,要求参数以字符串形式传入
日期类
Date --- 重点掌握字符串和日期之间的转换---SimpleDateFormat
Calendar --- 抽象类
DAY 13
复习:
1. 包装类:针对每一个基本类型都提供了对应的类形式 int -
Integer, char - Character;自动封箱 --- 指的是将基本类型的变量直接赋值给对应的引用类型的对象。自动封箱底层是调用了对应类身上的valueOf方法,对于整数在自动封箱过程中会有范围(-128~127)判断。自动拆箱是指将引用类型的对象直接赋值给对应的基本类型的变量。自动拆箱在底层是调用了对应对象身上的***Value方法。自动封箱/拆箱都是JDK1.5的特性之一。包装类的对象的实际值只要相同则它的哈希码就一定是相同的。
2. 数学类:
Math:最终类。针对基本类型提供了初等数学运算。
BigDecimal:用于精确运算小数的类,但是要求参数以字符串形式传递。
BigInteger:用于运算任意大的整数,要求整数以字符串或者是对应的补码的字节数组形式来传递。
DecimalFormat:用于对数字进行格式化的类。
3. 日期类
Date:表示日期的类。重点掌握字符串和日期之间的转换 ---
SimpleDateFormat:parse将字符串转化为日期,format将日期转化为字符串。
Calendar:表示日历的类。从JDK1.2开始,Java推荐使用Calendar
时间包
在JDK1.8中对时间体系进行了全新的详细的划分,划分出来一个详细的时间体系的包--- java.time
异常
[if !vml]
[endif]
异常是Java中一套用于问题的反馈和处理的机制
Throwable --- 异常的顶级父类
Error --- 错误表示合理(语法上还是逻辑上都是成立的)的应用程序中出现了严重的问题,而且这个问题不应该试图捕获 --- 意味着在程序中,错误一旦出现不能处理---StackOverflowError,OutOfMemoryError
Exception --- 表示合理的应用程序想要捕获的问题,也因此可以处理。处理方式:要么继续抛出,要么进行捕获处理。
编译时异常:在编译时期就已经出现要求必须处理。
CloneNotSupportedException
UnsupportedEncodingException
ParseException
运行时异常:在编译时期不出现到运行的时候才出现。可以处理可以不处理--- RuntimeException
ArithmeticException
ArrayIndexOutOfBoundsException
NullPointerException
ClassCastException
StringIndexOutOfBoundsException
NumberFormatException
自定义异常:写一个类继承Exception或者是其子类。如果是继承了RuntimeException及其子类,那么这个时候定义的是一个运行时异常;如果继承的是其他的Exception,那么定义的就是编译时异常
异常的捕获方式
A. 如果多个异常的处理方式各不一样,可以使用多个catch分别捕获分别处理
B. 如果所有异常的处理方式都一样,可以捕获这些异常的父类进行统一的处理
C. 如果多个异常进行了分组,那么同一组的异常之间用 | 隔开进行分组处理 --- 从JDK1.7开始
总结:方法的重载和方法的重写
方法的重载和重写都是行为多态。
方法的重载指在同一个类中存在方法名一致而参数列表不同的方法,和修饰符、返回值类型以及异常没有关系。重载本身是一种编译时多态。
方法的重写指在父子类中存在方法签名一致的非静态方法。子类在重写父类方法的时候,子类权限修饰符的范围要大于等于父类权限修饰符的范围。如果父类中的方法的返回值类型是基本类型/void,那么子类重写的方法的返回值类型要与父类一致。如果父类的方法的返回值类型是引用类型,那么子类重写的方法的返回值类型要么和父类一致,要么是父类方法返回值类型的子类。另外,子类重写的方法抛出的编译时异常不能超过父类方法的编译时异常的范围。方法的重写是一种运行时多态。
注意:异常从抛出的地方开始,后续代码停止执行。
finally --- 无论出现异常与否都需要执行一次。
如果在项目的开发期间遇到异常,记录栈轨迹,找异常来源进行改正;如果项目已经上线,记录错误日志,往往跳转错误页面
集合- Collection
存储多个同一类型的数据的容器 --- 大小不固定
- 泛型 - 在集合中的作用是用于表示元素类型。- 由于泛型的限制,集合中只能存储对象。
String[] arr; arr的数据类型是数组,元素类型是String
Collection c; c的数据类型是集合,元素类型是String
5,7, 2 --- Collection
Collection c; --- 表示集合中存储的元素是数组
List - 列表
有序(保证元素的存入顺序)的集合 --- 存在了下标,因此能够通过下标来操作列表中的元素
ArrayList - 顺序表
底层是依靠的数组来存储的数据。默认初始容量是10,每次扩容是在原来的基础上增加一半,基于右移。