Java学习周记week03
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习周记week03相关的知识,希望对你有一定的参考价值。
一.继承
1.什么叫继承?
继承是面向对象的三大特征之一。
在程序中,继承描述的是类与类之间的关系,通过继承多个类之间形成一种关系体系。
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出的类被称作子类,现有的类被称作父类。
继承后子类的特点: 子类自动拥有父类所有可继承的属性和方法。
在程序中,如果想声明一个类继承另一个类,需要使用extends关键字。
2.继承的注意事项
(1)继承必须合理(子类必须属于父类的一种时,符合is a 法则时,才会继承)
(2)父类中成员是共性的内容(父类抽取出了共性的内容,子类可以在父类基础上扩展新的属性和行为)
(3)子类自动拥有父类的成员并且可以直接使用非私有的父类成员
3.子类中访问父类成员变量特点
如果父类中的成员变量是非私有的,那么子类可以直接访问。
如果出现了成员变量同名的情况,在程序中使用子类对象会自动调用子类的成员变量,如果想调用父类的成员变量,需要使用super关键字。
4.子类中访问父类成员方法特点
当程序通过对象调用方法时,会先在子类中查找是否有对应方法,如果有的话就执行子类中的方法,如果没有的话就会执行父类中的对应方法。
在子类中,访问父类中的成员方法格式:
super.父类中的成员方法();
5.继承特点
1.Java只支持单继承:就一个子类 只能最多直接继承一个父类。(Java不支持多继承)
2.Java支持多层继承。
3.父类定义了继承树中共性内容,子类定义了该类个性内容。
6.继承中方法的重写与应用
子父类成员方法特殊情况——覆盖
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖。
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
7.方法重写的注意事项
-
子类方法覆盖/重写/覆写(override)父类方法,必须要保证权限大于等于父类权限。
-
如果父类的方法是private的修饰的,那么在子类中没法重写(其他修饰符都可以重写)。
-
写法上稍微注意:必须一模一样:方法的返回值类型 方法名 参数列表都要一样。
总结:当一个类是另一个类中的一种时,可以通过继承,来继承属性与功能。如果父类具备的功能内容需要子类特殊定义时,进行方法重写。
二. 抽象类
1.抽象方法的产生与定义
分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是方法功能声明相同,但方法功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。
当定义了抽象函数的类也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。
1 抽象方法定义的格式: 2 public abstract 返回值类型 方法名(参数); 3 4 抽象类定义的格式: 5 abstract class 类名 { 6 }
2.抽象方法的使用
抽象类无法直接创建对象,只能被子类继承后,创建子类对象。
三.接口
1.接口的概念
类:具有相同属性和功能的事物集合
接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。
一切事物均有功能,即一切事物均有接口。
2.接口的定义
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
1 public interface 接口名 { 2 抽象方法1; 3 抽象方法2; 4 抽象方法3; 5 }
3.实现类接口
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
class 实现类 implements 接口 { 重写接口中所有方法 }
在类实现接口后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
4.接口中成员的特点
1、接口中可以定义成员变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量,其值不能改变。后面我们会讲解static与final关键字
2、接口中可以定义方法,方法也有固定的修饰符,public abstract
3、接口不可以创建对象。
4、实现类必须覆盖掉接口中所有的抽象方法后,实现类才可以实例化。否则实现类是一个抽象类。
5.接口特点
接口可以继承接口。
如同类继承类后便拥有了父类的成员,可以使用父类的非私有成员。A接口继承B接口后,A接口便拥有了A、B两个接口中所有的抽象方法。
Java支持一个类同时实现多个接口,或一个接口同时继承多个接口。
类可以在继承一个类的同时,实现多个接口。
接口与父类的功能可以重复,均代表要具备某种功能,并不冲突。
6.抽象类与接口的比较
相同点:
都位于继承的顶端,用于被其他类实现或继承;
都不能直接实例化对象;
都可以包含抽象方法,其子类都必须覆写这些抽象方法;
区别:
抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;
接口只能包含抽象方法;
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
抽象类为继承体系中的共性内容,接口为继承体系外的扩展功能
二者的选用:
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
四.多态
1.多态的概念
多态是继封装、继承之后,面向对象的第三大特性。
父类引用变量可以指向子类对象。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
2.多态的代码体现
父类类型 变量名 = new 子类类型();
此时,虽然该变量指向的是子类对象,但表现为一个父类的形态,可以调用一切父类的方法,子类特有的方法将不能调用。
3.多态调用注意事项
成员变量编译看父类中是否存在,不存在编译失败
成员变量运行父类中的变量
成员方法编译看父类中是否存在,不存在编译失败
成员方法运行子类重写的方法
4.多态的好处和弊端
多态的存在意义(优点)为:配合继承与方法重写提高了代码的复用性与扩展性,如果没有方法重写,则多态同样没有意义。
多态的弊端: 不能调用子类的特有方法。
5.向上转型与向下转型
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
向上转型的使用格式
1 父类类型 变量名 = new 子类类型(); 2 如:Animal p = new Cat();
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!
向下转型的使用格式
1 子类类型 变量名 = (子类类型) 父类类型的变量; 2 如:Cat c = (Cat) a; //变量p 实际上指向Cat对象
instanceof关键字
判断对象是否可以向下转型 返回值为boolean
1 boolean b = 引用变量 instanceof 类; 2 if(a instanceof Dog){ 3 Dog d = (Dog)a; 4 }
五.static关键字
1.static概念
static它是静态修饰符,一般用来修饰类中的成员。
2.static 的特点
static是静态修饰符,一般修饰成员。被static修饰的成员属于类,不属于单个对象。
static修饰的成员被多个对象共享。
static修饰的成员属于类,但是会影响每一个对象。
被static修饰的成员又叫类成员,不叫对象的成员。
3.static修饰成员的使用
被static修饰的成员可以并且建议通过类名直接访问。也可以通过某个对象访到属于类的静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员。
格式:
类名.静态成员变量名
类名.静态成员方法名(参数)
对象名.静态成员变量名 ------不建议,出现警告
对象名.静态成员方法名(参数) ------不建议,出现警告
1 class Demo { 2 //非静态成员变量 3 public int num1 = 100; 4 //静态成员变量 5 public static int num2 = 100; 6 7 //非静态方法 8 public void method(){ 9 System.out.println("静态方法"); 10 } 11 //静态方法 12 public static void method(){ 13 System.out.println("静态方法"); 14 } 15 16 } 17 class Test { 18 public static void main(String[] args) { 19 System.out.println(Demo.num); 20 Demo.method(); 21 } 22 }
4.静态代码快
静态代码块是定义在成员位置,使用static修饰的代码块。
特点:
在同一个类中,它优先于主方法执行、优先于构造代码块执行,当以任意形式第一次使用到该类时执行。
该类不管创建多少对象,静态代码块只执行一次。
可用于给静态变量赋值,用来给类进行初始化。//数据库JDBC
1 public class Person { 2 private String name; 3 private int age; 4 //静态代码块 5 static{ 6 System.out.println("静态代码块执行了"); 7 }
六.final关键字
1.final关键字的概念
继承的出现提高了代码的复用性,并方便开发。但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写。这个时候就要使用到final关键字。
2.final关键字的特点
-
final修饰类不可以被继承,但是可以继承其他类。
-
final修饰的方法不可以被覆盖,但父类中没有被final修饰方法,子类覆盖后可以加final。
-
final修饰的变量称为常量,这些变量只能赋值一次。
-
引用类型的变量值为对象地址值,地址值不能更改,但是地址内的对象属性值可以修改。
-
修饰成员变量,需要在创建对象前赋值,否则报错。
-
也可以成员变量不赋值,但是构造方法必须赋值
七.四种访问权限修饰符
public | protected | default | private | |
同一类中 | 可调用 | 可调用 | 可调用 | 可调用 |
同一包中 | 可调用 | 可调用 | 可调用 | |
不同包中 | 可调用 | 可调用 | ||
不同包中的无关类 | 可调用 |
-
要想仅能在本类中访问使用private修饰;
-
要想本包中的类都可以访问不加修饰符即可;
-
要想本包中的类与其他包中的子类可以访问使用protected修饰
-
要想所有包中的所有类都可以访问使用public修饰。
- 如果类用public修饰,则类名必须与文件名相同。一个文件中只能有一个public修饰的类
八.内部类
1.内部类的概念
将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类。其他类也称为外部类。
访问方式
外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
2.匿名内部类
内部类是为了应对更为复杂的类间关系。
最常用到的内部类就是匿名内部类,它是局部内部类的一种。
定义的匿名内部类有两个含义:
- 临时定义某一指定类型的子类。
- 定义后即刻创建刚刚定义的这个子类的对象。
格式
1 new 父类或接口(){ 2 //进行方法重写 3 };
九.Object类
Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。所有类在创建对象的时候,最终找的父类就是Object。
两个常用方法1.equals 2.toString
开发中经常重写这两个方法,让这两个方法更符合开发时的使用。
1. equals(Object);方法,用于比较两个对象是否相同,它其实就是比较两个对象的地址值是否相同。
2.toString();方法,就是返回该对象的字符串表示,其字符串内容是对象的类型[email protected]+内存地址值。
十.异常
1.异常的概念
在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。
2.异常的分类
异常和错误的根类是Throwable,异常类皆继承java.lang.Throwable;
旗下有两个子类,Error与Exception。
- 严重错误Error:无法通过处理的错误。
- 编译时异常Exception,编译时无法通过。
- 运行时异常RuntimeException,是Excption的子类,运行时可能会报错,可以不处理。
3.异常的基本操作
- 创建异常对象
- 对异常的基本操作有两种
- 抛出异常
- 捕获异常(使用try/catch做分支处理)
声明抛出处理,出现异常后不处理,声明抛出给调用者处理。
方法声明上加throws 异常类名
注意:异常处理,指处理的一种可能性,即有了异常处理的代码,不一定会产生异常。如果没有产生异常,则代码正常执行,如果产生了异常,则中断当前执行代码,执行异常处理代码。
抛出异常 throw(动词,表示抛出异常的动作)
使用格式:
throw new 异常类名(参数);
声明异常 throws(将异常标识出来,报告给调用者我这个方法可能会出现这种异常)
声明异常格式:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2… { }
4.捕获异常 try…catch…finally
捕获:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理
捕获异常格式:
1 try { 2 3 //需要被检测的语句。 4 5 } 6 7 catch(异常类 变量) { //参数。 8 9 //异常的处理语句。 10 11 } 12 13 finally { 14 15 //一定会被执行的语句。 16 17 }
try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
5.异常的注意事项
- 多异常处理
捕获处理:
- 多个异常分别处理
- 多个异常一次捕获多次处理
- 多个异常一次捕获一次处理
声明抛出异常:
声明上使用,一次声明多个异常
- 运行时异常被抛出可以不处理。即不捕获也不声明抛出
- 如果父类方法抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集
- 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出[多线程会用到这个]
- 当多异常处理时,捕获处理,前边的类不能是后边类的父类
- 在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。
十一.常用API
1.Date类
类 Date 表示特定的瞬间,精确到毫秒。
继续查阅Date类的描述,发现Date拥有多个构造函数,只是部分已经过时,但是其中有未过时的构造函数可以把毫秒值转成日期对象。
- Date(); 获取一个当前日期对象
- Date(long date); 获取一个距离标准基准时间 date毫秒数的日期对象。
- Date方法默认调用了toString对象
- long getTime(返回一个自标准基准时间以来的此Date对象表示的毫秒数);
2.DateFormat
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat类)允许进行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和标准化。
我们通过这个类可以帮我们完成日期和文本之间的转换。
DateFormat类的作用:即可以将一个Date对象转换为一个符合指定格式的字符串,也可以将一个符合指定格式的字符串转为一个Date对象。
1 代码演示: 2 //创建日期格式化对象,在获取格式化对象时可以指定风格 3 DateFormat df= new SimpleDateFormat("yyyy-MM-dd");//对日期进行格式化 4 Date date = new Date(1607616000000L); 5 String str_time = df.format(date); 6 System.out.println(str_time);//2020年12月11日
指定格式的具体规则我们可参照SimpleDateFormat类的说明,这里做简单介绍,规则是在一个字符串中,会将以下字母替换成对应时间组成部分,剩余内容原样输出:
- 当出现
y
时,会将y替换成年
- 当出现
M
时,会将M替换成月
- 当出现
d
时,会将d替换成日
- 当出现
H
时,会将H替换成时
- 当出现
m
时,会将m替换成分
- 当出现
s
时,会将s替换成秒
DateFormat的两个常用方法
1.format(Date date);将一个Date格式化为日期/时间字符串。
2.parse(String source); 从给定字符串的开始解析文本,以生成一个日期。
format方法,用来将Date对象转换成String
parse方法,用来将String转换成Date(转换时,该String要符合指定格式,否则不能转换)。
2.calendar类
Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。
Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,将语言敏感内容处理好,再返回子类对象。
Calendar类静态方法
getInstance(); 使用一个默认时区和语言环境获得一个日历
Calendar c = Calendar.getInstance(); //返回当前日历对象
Calendar类常用方法
- add(int field , int mount); 为给定的日历字段添加或减去指定的时间量
- get(int field); 返回给定日历字段的值
- getInstance(); 使用默认时区和语言环境获得一个日历
- getTime(); 返回一个表示此Calendar时间值的Date对象
- set(int field, int mount);将给定的日历字段设置为给定值
YEAR 年
MONTH 月,从0开始算起,最大11;0代表1月,11代表12月。
DATE 天
HOUR 时
MINUTE分
SECOND秒
注意事项
西方星期的开始为周日,中国为周一。
在Calendar类中,月份的表示是以0-11代表1-12月。
日期是有大小关系的,时间靠后,时间越大。
3.System类
在API中System类介绍的比较简单,我们给出定义,System中代表程序所在系统,提供了对应的一些系统属性信息,和系统操作。
查看文档System类不能手动创建对象,因为构造方法被private修饰,阻止外界创建对象。System类中的都是static方法,类名访问即可。在JDK中,有许多这样的类。
常用方法
static long currentTimeMillis(); 返回以毫秒值为单位的当前时间。
static void exit(int status); 终止当前正在运行的Java虚拟机(0记为正常状态,其他为异常状态)
static void gc(); 运行垃圾回收(并没有什么卵用)
static String getProperty(String key); 获取指定键的系统属性
4.Math类
Math
类是包含用于执行基本数学运算的方法的数学工具类,如初等指数、对数、平方根和三角函数。
类似这样的工具类,其所有方法均为静态方法,并且一般不会创建对象。如System类
static double abs(double a); 返回double值的绝对值
static double ceil(double a); 向上取整
static double floor(double a);向下取整
static double max(double a , double b); 返回较大值
static double min(double a ,double b); 返回较小值
static double pow(double a , double b); 返回 a的b次幂的值
static double random(); 返回一个随机的大于等于0.0且小于1.0的double 值
static long round(double a ); 四舍五入
5.基本类型包装类
java将基本数据类型值封装成了对象。
其中需要注意int对应的是Integer,char对应的Character,其他6个都是基本类型首字母大写即可。
parseXXX(String s);其中XXX表示基本类型,参数为可以转成基本类型的字符串,如果字符串无法转成基本类型,将会发生数字转换的问题NumberFormatException
在需要的情况下,基本类型与包装类型可以通用。有些时候我们必须使用引用数据类型时,可以传入基本数据类型。
自动拆箱:对象转成基本数值
自动装箱:基本数值转成对象
6.正则表达式
正则表达式(英语:Regular Expression,在代码中常简写为regex)。
正则表达式是一个字符串,使用单个字符串来描述、用来定义匹配规则,匹配一系列符合某个句法规则的字符串。在开发中,正则表达式通常被用来检索、替换那些符合某个规则的文本。
常用方法
1.matches(String regex); 判断字符串是否匹配给定的规则
2.split(String regex);根据给定正则表达式的匹配规则,拆分此字符串
十一.集合
数组的长度是固定的。集合的长度是可变的。
数组中存储的是同一类型的元素,可以存储基本数据类型值。
集合存储的都是对象。而且对象的类型可以不一致。
Collection接口是集合中的顶层接口,它中定义的所有功能子类都可以使用。查阅API中描述的Collection接口。Collection 层次结构 中的根接口。Collection 用来存储一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。
1.Collection接口的基本方法
boolean add(E e); 添加对象,并判断是否删除成功 (増)
void clear(); 删除集合中的所有成员 (删)
boolean contains(Object o); 判断集合中是否包含o(查)
boolean remove(Object o); 删除对象,并判断是否删除成功 (删)
int size(); 返回collection的元素数(查)
Object[] toArray(); 返回包含此collection中所有元素的数组
2.Iterator 迭代器
java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。
Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
常用方法
boolean hasNext(); 如果仍有元素可以迭代,则返回true,说明可以迭代。
E next(); 返回迭代的下一个元素,并把指针向后移动一位。
1 //1,创建集合对象。 2 Collection<String> coll = new ArrayList<String>(); 3 coll.add("abc1"); 4 coll.add("abc2"); 5 coll.add("abc3"); 6 coll.add("abc4"); 7 8 //2.获取容器的迭代器对象。通过iterator方法。 9 Iterator it = coll.iterator(); 10 11 //3,使用具体的迭代器对象获取集合中的元素。参阅迭代器的方法 12 while(it.hasNext()){ 13 System.out.println(it.next()); 14 } 15 16 /* 17 迭代器for循环的形式的使用 18 for (Iterator it = coll.iterator(); it.hasNext(); ) { 19 System.out.println(it.next()); 20 } 21 */
迭代的常规用法中我们要尽量避免在迭代过程中为集合添加/删除数据。否则会报错,原因是Java抛出了并发修改异常。
迭代过程中并发修改异常的原因为:
迭代器中”记忆”的集合长度与集合中实际长度不同,而导致出现索引与实际元素不符甚至无限循环的情况发生。
3.增强for循环
增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
for(元素的数据类型 变量 : Collection集合or数组){
}
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
增强for循环和老式的for循环有什么区别?
注意:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。
建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过角标操作。
十二.泛型
泛型:就是一种不确定的类型(JDK1.5的一个新特性)
基本体现: <E>这就是泛型 可以是任意类型
- 泛型用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数传递。
- 泛型是数据类型的一部分,将类名与泛型合并一起看做数据类型。
- 泛型的定义:定义泛型可以在类中预支地使用未知的类型。
- 泛型的使用:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
1.使用泛型的好处
- 将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
- 避免了类型强转的麻烦。
2.含有泛型的类:泛型类
定义格式:修饰符 class 类名<代表泛型的变量> { }
使用格式:创建对象时,确定泛型的类型
3.含有泛型的方法
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
使用格式:调用方法时,确定泛型的类型
4.含有泛型的接口
定义格式:修饰符 interface接口名<代表泛型的变量> { }
使用格式:
1、实现接口时,确定泛型的类型
2、实现接口,不指定泛型的类型,直到创建对象时,确定泛型的类型
5.泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
定义:(查看ArrayList的构造方法或者addAll方法)无法在类中使用
使用:调用方法时可以给予任意类型。参照Arraylist的构造方法或者addAll方法
? extends E代表只要是E类型的子类即可
? super E代表只要是E类型的父类即可
以上是关于Java学习周记week03的主要内容,如果未能解决你的问题,请参考以下文章