day 2021.4.28
面向对象的三大特征:多态性
extends继承或者implements实现,是多态性的前提。
多态的格式与使用规则
代码中多态性的体现:父类引用指向子类对象。
格式:
父类名称 对象名 = new 子类名称();
或者:
接口名称 对象名 = new 实现类名称();
访问成员变量的两种方法:
1.直接用过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找。
2.简介通过成员方法访问成员变量,看该方法访问谁,优先用谁,没有则向上找。
day 2021.4.29
多态中成员方法的使用特点
在多态的代码当中,成员方法的访问规则是,
看new的是谁,就优先用谁,没有则向上找。
对比:
成员变量:编译看左边,运行还是看左边。
成员方法:编译看左边,运行看右边。
使用多态的好处
对象的向上转型
对象的向上转型,其实就是多态写法。
格式:
父类名称 对象名 = new 子类名称();
含义:右侧创建一个子类对象,把他当作父类来看待使用。
注意:向上转型一定是安全的。从小范围转向大范围。
对象的向下转型
向上转型有一个弊端,对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。
解决方案:用对象的向下转型还原。
格式:
子类名称 对象名 = (子类名称)父类对象。
含义:将父类对象,还原成为本来的子类对象。
图解
instanceof关键字的使用
格式:
对象 instanceof 类型
这将会得到一个boolean值,也就是判断前面的对象能不能当作后面类型的实例。
final关键字的四种用法
final关键字代表最终的,不可改变的。
常见四种用法:
1.可以用来修饰一个类。
格式:
public final class 类名称{
方法体
}
含义:这个类不能有任何子类,但可以有父类。
注意:一个类如果是final的,那么其中所有成员方法都无法进行覆盖重写。(应为没有子类)
2.可以用来修饰一个方法。
含义:当final关键字用来修饰一个方法的时候,这个方法就是最终方法,不能被覆盖重写。
格式:
修饰符 final 返回值类型 方法名称 (参数列表){
方法体
}
注意事项:对于类,方法来说,abstract关键字和final关键字不能同时使用。因为矛盾。
3.还可以用来修饰一个局部变量。
含义:当final 用来修饰一个局部变量,那么这个变量就不能进行更改。
这是正确的修饰。
当final的引用类型变量,其中的地址值不可改变,但可以改变地址内的内容。
4.还可以用来修饰一个成员变量。
含义:对于成员变量来说,如果使用final关键字修饰,那么这个变量也是不可改变的。
a.由于成员变量具有默认值,所有用了final之后必须手动赋值。
b.对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。
直接赋值
通过构造方法赋值
注意,set方法必须去掉。>
c.必须保证类当中所有的重载的构造方法,都最终会对final的成员方法进行赋值。
四种权限修饰符
内部类的概念与分类
概念:一个类的内部可以定义其他类,这样的类叫内部类。
分类:
1.成员内部类。
定义格式:
修饰符 class 外部类名称 {
修饰符 class 内部类名称 {
、、、
}
、、、
}
注意:1.内部类使用外部可以随意访问。
2.需要借助内部类对象。
3.局部内部类(包含匿名内部类)
如何使用内部类
有两种方法:
1.间接方式:
在外部类的方法当中,使用内部类,然后main只是调用外部类方法
2.直接方式:公式:
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
内部类的同名变量访问
如果出现重名现象,那么格式是:
外部类名称…this.外部类成员变量名
局部内部类定义
含义:如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
局部:只有当前所属方法才能使用,出来这个方法就不能用。
定义格式:
修饰符 class 外部类方法名称{
修饰符 返回值类型 外部方法名称(){
class 局部内部类名称
、、。。。
}
}
小结:
具备内部类的final问题
局部内部类如果希望访问所在方法的局部变量,那么这个局部变量必须是有效final的
备注:从java 8开始,只要局部变量事实不变,那么final关键字可以省略。
匿名内部类
如果接口实现类(或者父类的子类)只需要使用唯一一次,那么这种情况下就可以省略该类的定义,而改为使用匿名内部类
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){
、、覆盖重写接口中所有抽象方法。
}
匿名内部类的注意事项
对格式new 接口名称(){。。。} a进行解析
1.new代表创建对象的动作。
2.接口名称是匿名内部类需要实现的哪个接口
3.{。。。}才是匿名内部类的内容。
注意:
1.匿名内部类在创建对象的时候,只能使用唯一一次。如果希望多次创建对象,那么就必须使用单独定义的实现类。
2.匿名对象在调用方法的时候,只能调用唯一一次,如果希望同一个对象调用多次方法,那么必须给对象起个名字
3.匿名内部类是省略了实现类或者子类的名称,但是匿名对象名称是可以省略的。
day 2021.4.30
类作为成员变量类型
文件:cn.itclass.day0430.demo01
接口作为成员变量类型
文件:cn.itclass.day0430.demo02
接口作为方法的参数和返回值
这是多态写法:左边是接口名称,右边是实现类名称。
Object类的toString方法
类Object是类层次接口的跟类,也就是说有类的父类,说有对象,都实现这个类的方法。
自定义的类默认继承了Object类,所以可以使用Object类中的toString方法。
如果没有覆盖重写toString,直接打印对象名是获取该对象的地址值。
如果直接打印对象名,出现的不是地址值,则说明该类重写了toString方法。
Object的equals方法
含义:指示某对象是否与此对象相等,(比较两个对象的地址值)
Person类默认继承了Object类,所以可以使用Object类的equals方法。返回boolean。
day 2021.5.1
覆盖重写equals方法
Object类的equals方法默认比较的是两个对象的地址值,没有意义,所以我们要重写equals方法,比较两个对象的属性。
存在问题:隐含着多态,多态无法使用子类特有内容。(属性和方法)
解决:可以使用向下转型。
问题:
使用equals方法比较两个对象时,两个对象都必须向下转型,否则代码异常。
解决:
增加一个instanceof判断,判断判断前面的对象能不能当作后面类型的实例。
增加效率,多写两个if语句。
1.if(obj == obj){return true}
2.if(obj == null){return false}
Objects类
**问题:**null不能调用方法,所以Object类的equals不能比较null和其他对象的属性。因此会出现NullPointerException(空指针异常)
**解决:**使用Objects类的equals方法。
Objects类的equals方法中,如果一个以上的对象为null,则比较连个对象的地址值。
Date类
API。
DateFormat类
是日期/时间格式化子类的抽象类毫秒值。
作用:格式化日期或文本。
Calendar类
是个抽象类,无法直接创建对象使用,得使用里面的一个静态方法,getInstance()。 改方法返回了Calendar子类对象。
提供了很多操控日历字段的方法。
day 2021.5.5
System类的常用方法
提供了大量的静态方法,可以湖片区与系统相关的信息或系统操作。
API
StringBuilder类
String:
字符串的底层是一个被final修饰的数组,不能改变。
要改变得进行字符串的相加,那么内穿中就会有多个字符串,占用空间多,效率低下。
StringBuilder类的作用:字符串缓冲区,可以提高字符串的操作效率。(可以堪称可以变化的字符串)
底层没有被final修饰。可以改变长度。
StringBuilder在内春中始终占用一个数组,占用控件少,效率高。
如果超出StringBuilder的内存,那么数组会自动扩容。
链式编程:方法返回值是一个对象,可以继续调用方法。
包装类
问题描述:基本数据类型,使用起来非常方便,但是没有对应的方法来操作这些基本类型的数据。
解决:可以使用一个类,把基本数据类型包装起来,在类中定义一些方法。这个类叫包装类。
可以使用类中的方法操作这些基本类型的数据。
装箱与拆箱
装箱概念:把基本类型的数据,包装到包装类。(基本数据类型 --> 包装类)
构造方法:
Integer(int value)构造一个新分配的Integer对象,他表示指定的int。
过时方法会出现横线。
Integer(String s)构造一个新分配的Integer对象,他表示参数所指示的int值。
**注意:**Integer(String s)传递的字符串,必须的基本类型的字符串,否则出现NumberFormatException(数字转换异常)。
"100"正确;"a"错误。<
拆箱:在包装中取出基本类型的数据(包装类 – > 基本类型的数据)
成员方法:
int intValue ()以 int 类型返回该Integer的值。
自动拆箱与自动装箱
概念:基本类型的数据和包装类之间可以自动互相转换。(JDK1.5开始)
基本类型与字符串之间的相互转换
基本类型–>字符串(String)
1.基本类型的值 + “ ” ;最简单的方法
2.包装类的静态方法toString(参数),不是Object的toString()。toString是重载
3.String类的静态方法valueOf(参数)
字符串 --> 基本类型
使用包装类的静态方法parsXXX(“数字符串”);
Integer类:static Int parsInt(String)
Double类:static double parsDouble(String)
day 2021.5.7
Collection集合
java.util.Clloection接口,是所有单列集合的最顶层,里边定义了所有单列集合的共性方法。任意单列集合都可以使用Collection接口中的方法。
集合与数组的区别:
数组的长度是固定的,集合的长度是可变的。
数组中存储的是同意类型的元素,可以存储基本数据类型值。集合存储的都是对象,而且对象的类型可以不一致 。
Collection集合的框架
Collection常用功能
API
Iterator接口
迭代器,用于遍历集合。
迭代:
先判断该集合有没有元素,如果有,再把这个元素取出,继续判断,再取出。一直把集合中去所有元素取出,这种取出方式专业术语成为迭代。
Iterator是一个接口,需要Iterator接口的实现类对象,获取实现类的方法比较特殊:
再Collection接口中有一个方法,叫iterator(),这个方法的返回的就是迭代器的实现类对象。
迭代器使用步骤:
1.先使用Collection集合中的iteator()方法获取迭代器的实现类对象,使用Iterator接口接收(多态)。
**注意事项:**Iterator<>接口也是又泛型的,迭代器跟着集合走。结合是什么泛型,迭代器就是什么泛型。
2.使用Iterator接口中的方法hasNext判断还有没有下一个元素。
3.使用Iterator接口中的方法next取出集合中的元素。
迭代器遍历的优化。加个while循环。
增强for循环
jdk1.5之后的高级for循环,专门用来遍历数组和集合。内部原理其实是一个Iterator迭代器,所以遍历过程中,不能对集合中的元素进行增删操作。底层使用的也是迭代器,使用for循环格式,优化了迭代器的书写。
格式:
for(集合/数组的数据类型 变量名:集合名/数组名){
sout(变量名);/
}
泛型
ArrayList集合在定义的时候,不知道集合中会存储什么类型的数据,所以类型使用泛型。
例子:
public class ArrayList<E>(){...};
//<E>代表数据类型为泛型。
ArrayList<String> list = new ArrayList<>();
ArrayList<Student> list = new AArrayList<Student>();
创建对象时确定泛型的类型。会把数据类型作为参数传递,赋值给泛型E。
使用泛型的好处
创建集合对象时,不使用泛型
好处:
集合不适用泛型,默认的类型就是Object类型,可以存储任意类型的数据。
弊端:
集合不安全,会引发异常。ClassCastException(calss类型转换异常)
创建集合对象,使用泛型
好处:
1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型。
2.把运行期异常(运行之后才抛出异常),提升到了编译器异常(写代码的时候就会报错)。
弊端:
泛型是什么类型,就只能存储什么类型的数据。
定义一个含有泛型的类
day 2021.5.11
定义和使用含有泛型的接口
含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口泛型。有两种方法:
1.定义接口的实现类,实现接口,指定接口的泛型。
2.接口使用说明泛型,实现类就使用说明泛型,类跟着接口走。
泛型通配符
?:代表任意数据类型
使用方式:
不能创建对象使用,只能作为方法的参数使用。
注意:定义时不能使用,只能当参数传递。
通配符高级使用–受限泛型
泛型的上线限定:?extends E :代表使用的泛型只能是E类型的子类或本身
泛型的下线限定:?super E :代表使用的泛型只能是E类型的父类或本身
List集合
三大特点:有序集合,有索引的,允许存储重复的元素。
特有方法:add,get,remove,set。
ArrayList 集合:查询快,增删慢。
LinkedList集合:查询慢,增删快
Vevtor集合: