7 第七天 魔乐java基础视频学习笔记.docx
《7 第七天 魔乐java基础视频学习笔记.docx》由会员分享,可在线阅读,更多相关《7 第七天 魔乐java基础视频学习笔记.docx(22页珍藏版)》请在冰豆网上搜索。
7第七天魔乐java基础视频学习笔记
1、课程名称:
面向对象
2、知识点
2.1、上次课程的主要知识点
1、继承性:
扩充类的已有功能;
·如果要想实现继承,可以通过extends关键字来完成,继承的子类也称为派生类,而父类也称为超类;
·在Java之中一个子类只允许继承一个父类,即:
不允许多重继承,但是允许多层继承;
·在子类对象实例化之前,会默认调用父类之中的无参构造方法,之后再调用子类自己的构造方法,也可以通过super()改变指定构造方法的调用;
·子类继承父类的时候会将父类之中的全部操作都继承下来,但是对于所有的私有属性隐式继承,而所有的非私有操作属于显示继承。
2、方法的覆写:
override;
·子类继承父类的时候,如果定义了和父类方法名称相同,参数的类型及个数相同,返回值相同的方法时,称为方法的覆写;
·在进行方法覆写的时候,被覆写的方法,不能拥有比父类更严格的访问控制权限,只要是方法首先想到定义就是public。
3、final关键字:
定义不能被继承的类,不能被覆写的方法、常量,使用publicstaticfinal定义的全局常量;
4、单例设计模式(Singleton):
构造方法私有化,之后通过类的static方法取得本类的实例化对象,单例设计的最大特点:
不管如何操作只会有本类的一个实例化对象;
5、多态性:
在某一个范围内的任意改变:
·方法的多态性:
方法的重载(同一个方法名称,根据参数的类型及个数不同,可以完成不同的操作)。
方法的覆写(不同的子类,针对于同一个方法可以有不同的实现)。
·对象的多态性:
父子类对象之间的转换操作:
|.对象的向上转型:
父类对象=子类实例,自动完成,80%;
|.对象的向下转型:
子类对象=(子类)父类实例,强制完成,在发生对象向下转型之前,一定要首先发生对象的向上转型,以建立联系,10%,除非要使用到子类一些特殊功能的时候;
|.可以通过instanceof来判断一个对象是否是指定类的实例。
6、抽象类:
是一个半成品,规定了子类必须覆写的操作;
·如果一个类之中包含了抽象方法,那么久称为抽象类,抽象方法使用abstract关键字进行定义,而抽象类也使用abstract关键字定义;
·抽象类就是比普通类多了抽象方法,其他的所有定义和普通类一样,但是对于抽象类的构造方法,不能直接使用,只能够通过实例化子类对象时,由子类对象;
·抽象类在使用的时候必须有子类,而且子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法;
·抽象类的对象实例化可以靠子类的向上转型完成,这个时候所调用的抽象方法一定是被子类所覆写过的方法;
7、接口:
接口属于一个特殊的类
·如果一个类之中全部由抽象方法和全局常量所组成的话,那么这个特殊的类就称为接口,接口使用interface关键字进行定义;
·接口也必须有子类,子类通过implements关键字实现接口,并且一个子类可以同时实现多个接口,每一个接口的子类都要求覆写接口之中的所有抽象方法;
·如果一个子类既要继承抽象类又要实现接口的话,则应该先继承后实现;
·接口可以通过子类采用对象的向上转型操作进行接口对象的实例化操作;
·一个接口可以同时继承多个父接口(接口的多继承);
·接口之中的全部方法定义永远都是public;
·接口的最大优点:
避免了抽象类的单继承局限,所有设计的时候优先考虑接口,而不是抽象类。
2.2、本次预计讲解的知识点
1、匿名内部类,以后才用的;
2、Object类以及组成方法;
3、基本数据类型的包装类;
4、结合接口、链表、实现第五个代码模型。
3、具体内容
今天的所有内容是围绕着实际的应用来讲,概念不多,但是代码重要。
3.1、匿名内部类(重点)
内部类:
在一个类的内部定义了另外的类,称为内部类,匿名内部类指的是没有名字的内部类,为了清楚内部类的主要作用,下面首先来观察如下的程序:
范例:
思考程序的问题
interfaceMessage{//定义了一个接口
publicvoidprint();//抽象方法
}
classMessageImplimplementsMessage{//定义接口的实现类
publicvoidprint(){
System.out.println("HelloWorld!
");
}
}
classDemo{
publicstaticvoidget(Messagemsg){//接收接口对象
msg.print();
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Messagemsg=newMessageImpl();//子类为接口实例化
Demo.get(msg);//传递msg对象
}
}
以上的代码属于正常的开发范畴,但是如果说现在MessageImpl这个子类只使用那么唯一的一次,有必要按照以上的方式进行定义吗?
这个时候那么MessageImpl就没有什么意义了,但是可以利用匿名内部类的概念来解决此问题。
匿名内部类是在抽象类和接口的基础之上所发展起来的一种应用。
interfaceMessage{//定义了一个接口
publicvoidprint();//抽象方法
}
classDemo{
publicstaticvoidget(Messagemsg){//接收接口对象
msg.print();
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Demo.get(newMessage(){//匿名内部类
publicvoidprint(){
System.out.println("HelloWorld!
");
}
});
}
}
对于匿名内部类的使用,暂时只需要记住它的语法即可,因为如果要想真正的去使用它,还需要一段时间的课程。
3.2、Object类(重点)
在Java的定义之中,除了Object类之外,所有的类实际上都存在继承关系,即:
如果现在定义了一个类,没有默认继承任何一个父类的话,则默认将继承Object类,以下两种类的最终定义效果是完全一样的。
classPerson{}
classPersonextendsObject{}
那么按照这样的方式理解,即:
Object类可以接收所有类的实例化对象。
classPerson{}
classTestDemo64{
publicstaticvoidmain(String[]args){
Objectobj=newPerson();//向上转型
Personper=(Person)obj;//向下转型
}
}
如果在日后的开发之中,一个操作可能接收所有类的对象,那么使用Object作为参数最合适。
除此之外,对于任意的一个简单Java类而言,理论上讲应该覆写Object类之中的三个方法:
·取得对象信息:
publicStringtoString();
·对象比较:
publicbooleanequals(Objectobj);
·取得哈希码:
publicinthashCode()。
3.2.1、取得对象信息:
toString()
在之前提示过,如果说现在一个对象直接输出,那么默认情况下输出的是一个对象的地址。
classPerson{}
classTestDemo64{
publicstaticvoidmain(String[]args){
Personper=newPerson();
System.out.println(per);//Person@757aef
System.out.println(per.toString());//Person@757aef
}
}
现在可以清楚地发现,如果直接输出一个类的对象,那么和这个对象调用toString()方法的结果是完全一样的,那么就可以得出一个结论:
对象直接输出默认调用了Object类之中的toString()方法,但是默认的toString()方法有一个特点:
为了适用于所有的子类,那么在toString()默认情况下就是输出了对象地址),当然,每一个子类也可以自己进行修改。
classPerson{
privateStringname;
privateintage;
publicPerson(Stringname,ageint){
this.name=name;
this.age=age;
}
publicStringtoString(){//方法覆写
return"姓名:
"+this.name+",年龄:
"+this.age;
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Personper=newPerson();
System.out.println(per);//Person@757aef
}
}
3.2.2、对象比较:
equals()
实际上对于equals()方法应该并不陌生了,这个方法在String类中见过,String是Object类的子类,所以String类的equals()方法就是覆写了Object类中的equals()方法,在Object类之中,默认的equals()方法实现比较的是两个对象的内存地址数值,但是并不符合于真正的对象比较需要。
对象比较之前也写过,但是之前是自己定义了一个新的方法名称,今天可以给出标准的方法名称:
equals()。
classPerson{
privateStringname;
privateintage;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringtoString(){//方法覆写
return"姓名:
"+this.name+",年龄:
"+this.age;
}
publicbooleanequals(Objectobj){
if(this==obj)
{
returntrue;
}
if(obj==null)
{
returnfalse;
}
if(!
(objinstanceofPerson))
{//不是本类对象
returnfalse;
}
//因为name和age属性是在Person类中定义,而Object类没有
Personper=(Person)obj;
if(this.name.equals(per.name)&&this.age==per.age)
{
returntrue;
}
returnfalse;
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Personper1=newPerson("张三",20);
Personper2=newPerson("张三",20);
System.out.println(per1.equals(per2));
System.out.println(per1.equals(per1));//true
}
}
3.2.3、使用Object接收所有的引用数据类型
Object是所有类的父类,那么Object类可以接收所有类的对象,但是在Java设计的时候,考虑到引用数据类型的特殊性,所以Object类实际上是可以接收所有引用数据类型的数据,这就包括了数组、接口、类。
范例:
使用Object类接收数组,数组和Object没有任何明确的定义关系
classTestDemo64{
publicstaticvoidmain(String[]args){
Objectobj=newint[]{1,2,3};//接收数组
if(objinstanceofint[])
{
int[]data=(int[])obj;//向下转型
for(intx=0;x{
System.out.println(data[x]);
}
}
}
}
范例:
接收接口对象,从接口定义而言,它是不能去继承一个父类的,但是由于接口依然属于引用类型,所以即使没有继承类,也可以使用Object接收。
interfaceMessage{
}
classMessageImplimplementsMessage{//定义接口子类
publicStringtoString(){
return"NewMessage:
HelloWorld.";
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Messagemsg=newMessageImpl();//向上转型
Objectobj=msg;//使用Object接收接口对象,向上转型
Messagetemp=(Message)obj;//向下转型
System.out.println(temp);//toString()
}
}
从代码上讲,以上只能算是一个固定的操作概念,不过从实际来讲,因为有了Object类的出现,所有的操作的数据就可以达到统一,那么之前的链表程序,就应该变得很方便了,所有的数据都使用Object接收,所有的对象比较(删除和查找)都可以使用equals()。
3.3、包装类(重点)
在Java的设计之中,一直提倡一个原则:
一切皆对象,这个原则本身有一个漏洞——基本数据类型不是对象(一般而言,引用数据类型才是对象),所以这个原则就出现了问题,那么如果说现在这个问题由我们来解决,那么该如何解决?
classInt{//类
privateintnum;//基本型
publicInt(intnum){
this.num=num;
}
publicintintValue(){
returnthis.num;
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Inttemp=newInt(10);//把基本类型变为类
intresult=temp.intValue();
System.out.println(result*result);
}
}
以上的操作是将基本类型变为了一个对象的形式进行操作了,但是这里面有一个问题:
基本数值型数据是可以进行数学运算的,可是以上变为了类的形式,那么肯定无法直接计算了。
而且以上的问题既然我们都可以想到方法去解决,那么java也一定早已解决,为此它专门提供了八种包装类:
byte(Byte)、short(Short)、int(Integer)、long(Long)、float(Float)、double(Double)、boolean(Boolean)、char(Character),而这八种包装类又分为两大阵营:
·数值型(Number子类):
Byte、Short、Interger、Float、Double、Long;
·对象型(Object子类):
Boolean、Character。
可是对于Number子类,就必须观察出Number类之中定义的方法:
byteValue()、intValue()、floatValue()、doubleValue()、shortValue()、longValue(),就是从包装的类之中取得所包装的数值。
3.3.1、装箱与拆箱
在基本数据类型和包装类之间的转换操作之中分为两个重要概念:
·装箱操作:
将基本数据类型变为包装类,称为装箱,包装类的构造方法;
·拆箱操作:
将包装类变为基本数据类型,称为拆箱,各个类的xxValue()。
范例:
以int和Integer为例
classTestDemo64{
publicstaticvoidmain(String[]args){
Integervar=newInteger(15);//装箱
intresult=var.intValue();//拆箱
System.out.println(result*result);
}
}
范例:
以double和Double为例
classTestDemo64{
publicstaticvoidmain(String[]args){
Doublevar=newDouble(15.5);//装箱
doubleresult=var.doubleValue();//拆箱
System.out.println(result*result);
}
}
范例:
以boolean和Boolean为例
classTestDemo64{
publicstaticvoidmain(String[]args){
Booleanvar=newBoolean(true);//装箱
booleanresult=var.booleanValue();//拆箱
if(result)
{
System.out.println("Hello");
}
}
}
以上的操作是在JDK1.5之前所进行的必须的操作,但是到了JDK1.5之后,Java提供了自动的装箱和拆箱机制,并且包装类的对象可以自动的进行数学计算了。
classTestDemo64{
publicstaticvoidmain(String[]args){
Integervar=15;//自动装箱
intresult=var;//自动拆箱
System.out.println(++var*result);
}
}
classTestDemo64{
publicstaticvoidmain(String[]args){
Booleanvar=true;//自动装箱
if(var)//自动拆箱后操作
{
System.out.println("Hello");
}
}
}
那么正是因为有了这样的自动装箱和拆箱的机制,所以Object也可以接收基本数据类型数据。
classTestDemo64{
publicstaticvoidmain(String[]args){
Objectobj=15;//int-->自动装箱-->Object
intresult=(Integer)obj;//Object-->包装类-->自动拆箱
System.out.println(result*result);
}
}
但是到此处还有一个小问题,实际上这一问题之前见过的。
classTestDemo64{
publicstaticvoidmain(String[]args){
Integerx=newInteger(10);//新空间
Integery=10;//入池
Integerz=10;
System.out.println(x==y);//false
System.out.println(x==z);//false
System.out.println(z==y);//true
System.out.println(x.equals(y));//true
}
}
以后使用包装类的时候还需要考虑equals()和==的区别。
3.3.2、数据转型
包装类之中所提供的最大优点还在于可以将字符串变为指定的基本数据类型,下面列出几个操作:
·Integer类:
publicstaticintparseInt(Strings);
·Double类:
publicstaticdoubleparseDouble(Strings);
·Boolean类:
publicstaticBooleanparseBoolean(Strings)。
但是Character这个包装类之中,并没有提供一个类似的parseCharacter()方法,因为字符串String类之中提供了一个charAt()方法,可以取得指定索引的字符,而且一个字符的长度就是一位。
范例:
将字符串变为int
classTestDemo64{
publicstaticvoidmain(String[]args){
Stringstr="16";
intresult=Integer.parseInt(str);//String-->int
System.out.println(result*result);
}
}
但是需要提醒的是,在执行这种转换的操作过程之中,字符串中的全部内容必须由数字所组成,如果有一位内容不是数字,则在转换的过程之中将出现如下的错误提示:
NumberFormatException。
范例:
将字符串变为double数据
classTestDemo64{
publicstaticvoidmain(String[]args){
Stringstr="36.";
doubleresult=Double.parseDouble(str);
System.out.println(result*result);
}
}
范例:
将字符串变为boolean数据
classTestDemo64{
publicstaticvoidmain(String[]args){
Stringstr="true";
booleanresult=Boolean.parseBoolean(str);
if(result)
{
System.out.println("Hello");
}