------- android培训、java培训、java学习型技术博客、期待与您交流! ----------
面向对象(继承-概述)
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
多个类可以称为子类,单独这个类称为父类或者超类。
子类可以直接访问父类中的非私有的属性和行为。
继承的出现提高了代码的复用性。
继承的出现让类与类之间产生了关系,提供了多态的前提。
注意:千万不要为了获取其他类的功能,简化代码而继承,必须是类与类之间有所属关系才可以继承.
java只支持单继承,不支持多继承,但是java有另外一种体现形式--多实现.
java支持多层继承,也就是一个继承体系.
如何使用一个继承体系中的功能呢?
想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系*性功能。
通过了解共性功能,就可以知道该体系的基本功能。
那么这个体系已经可以基本使用了。
那么在具体调用时,要创建最子类的对象,为什么呢?
1.因为有可能父类不能创建对象,
2.创建子类对象可以使用更多的功能,包括基本的也包括特有的。
简单一句话:查阅父类功能,创建子类对象使用功能。
类与类,事物与事物之间除了继承关系,还有聚合关系和组合关系.
面向对象(子父类中变量的特点)
如果子类中出现非私有的同名成员变量时,
子类要访问本类中的变量,用this,
子类要访问父类中的同名变量,用super。
super的使用和this的使用几乎一致。
this代表的是本类对象的引用。
super代表的是父类对象的引用。
加载子类class文件的时候先加载父类class文件.
面向对象(子父类中函数的特点-覆盖)
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖)。
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,
这时,没有必要定义新功能,而是使用覆盖,保留父类的功能定义,并重写功能内容。
覆盖:
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2,静态只能覆盖静态。
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。
面向对象(子父类中构造函数的特点-子类实例化过程)
在对子类对象进行初始化时,父类的构造函数也会运行,
那是因为子类的构造函数默认第一行有一条隐式的语句 super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函数
因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。
所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
注意:super语句一定定义在子类构造函数的第一行。
子类的实例化过程。
结论:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。
子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
面向对象(final关键字)
final: 最终。是一个修饰符,
1,可以修饰类,函数,变量.
2,被final修饰的类不可以被继承.
3,被final修饰的方法不可以被复写.
4,被final修饰的变量是一个常量只能赋值一次,即可以修饰成员变量又可以修饰局部变量.
当在描述事物时,一些数据的值是固定的,为了增强阅读性,都给这些值起个名字。方便于阅读。
而这个值不需要改变,所以加上final修饰。常量的书写规范所有字母都大写,
如果由多个单词组成。单词间通过_连接。
面向对象(抽象类)
当多个类中出现相同功能,但是功能主体不同,这时可以向上抽取.只抽取功能定义,不抽取功能主体.
1,抽象方法一定定义在抽象类中.
2,抽象方法和抽象类都必须被abstract关键字修饰.
3,抽象类不可以用new创建对象,因为调用抽象方法没意义,会编译失败.
4,抽象类中的方法要被使用,必须由子类复写所有的抽象方法,然后建立子类对象调用.
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类.
抽象类和一般类没有太大不同,该怎么描述事物还怎么描述,只不过类里面出现了抽象方法.
抽象类中也可以有非抽象方法,这些方法可以直接被使用.
注意:抽象类中也可以不定义抽象方法,这样做仅仅是不让该类建立对象.
classEmployee
{
privateString name;
privateString id;
privatedouble pay;
Employee(Stringname,String id,double pay)
{
this.name= name;
this.id= id;
this.pay= pay;
}
publicvoid work();
}
classpro extends Employee
{
Pro(Stringname,String id,double pay)
{
super(name,id,pay);
}
publicvoid work()
{
System.out.println("prowork");
}
}
classManager extends Employee
{
privateint bonus;
Manager(Stringname,String id,double pay,int bonus)
{
super(name,id,pay);
this.bonus= bonus;
}
publicvoid work()
{
System.out.println("managerwork");
}
}
面向对象(模版方法模式)
模版方法设计模式:在定义功能时,功能的一部分是确定的,但是一部分是不确定的.
而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由该类的子类去完成.
abstract class GetTime
{
publicfinal void getTime()
{
longstart = System.currentTimeMillis();
runcode();
longend = System.currentTimeMillis();
System.out.println("毫秒:"+(end-start));
}
publicabstract void runcode();
}
class SubTime extends GetTime
{
publicvoid runcode()
{
for(intx=0; x<4000; x++)
{
System.out.print(x);
}
}
}
class TemplateDemo
{
publicstatic void main(String[] args)
{
//GetTimegt = new GetTime();
SubTimegt = new SubTime();
gt.getTime();
}
}
面向对象(接口)
接口:初期可以理解为是一个特殊的抽象类.当类中的方法都是抽象的就可以通过接口的形式来表示.
interface:用于定义接口. class:用于定义类.
接口定义时,格式特点:
1,接口中常见定义:常量,抽象方法.
2,接口中的成员都有固定修饰符.
常量:public static final 方法:public abstract
接口中的成员都是public的.
接口是不可以创建对象的,因为有抽象方法.
需要被子类实现,子类对接口的抽象方法全都覆盖后,子类才可以实例化,否则子类是一个抽象类.
接口可以被类多实现,java不支持类与类的多继承但是支持类与接口的多实现.
接口与接口之间可以继承,而且支持多继承.
面向对象(接口的特点)
1,接口是对外暴露的规则.
2,接口是程序的功能扩展.
3,接口的出现降低耦合性。
4,接口可以用来多实现。
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
接口与接口之间可以有继承关系。
例如:电脑主板和不同厂家的元件可以通过统一的插槽进行连接,符合规则就可以用.
抽象类和接口异同:
相同:
1,都可以在内部定义抽象方法。
2,通常都在顶层。
3,都不可以实例化,都需要子类来实现。
不同点:
1,抽象类中可以定义抽象方法和非抽象方法,而接口中只能定义抽象方法。
2,接口的出现可以多实现。抽象类只能单继承。也就是说:接口的出现避免了单继承的局限性。
3,继承和实现的关系不一致。继承:is a,实现:like a
面向对象(多态-概念)
多态:某一类事物的多种存在形态。
例如:动物中有猫和狗。
猫这个对象对应的类型是猫类型
猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物。
动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向了子类对象。
1,多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象。
2,多态的前提
必须是类与类之间有关系。要么继承,要么实现。
通常还有一个前提:存在覆盖。
3,多态的好处
多态的出现大大的提高程序的扩展性。
4,多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
面向对象(多态-转型)
instanceof: 用于判断对象的类型。 对象 intanceof 类型(类类型接口类型)
Animala = new Cat();//类型提升。 向上转型。
a.eat();
如果想要调用猫的特有方法时,如何操作?
Catc = (Cat)a;//强制将父类的引用。转成子类类型。向下转型。
c.catchMouse();
多态自始至终都是子类对象在做着变化
千万不要出现这样的操作,就是将父类对象转成子类类型。
面向对象(多态中成员的特点)
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。
面向对象(多态的主板示例)
interface PCI
{
publicvoid open();
publicvoid close();
}
class MainBoard
{
publicvoid run()
{
System.out.println("mainboardrun ");
}
publicvoid usePCI(PCI p)//PCI p = new NetCard();接口型引用指向自己的子类对象。
{
if(p!=null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI
{
publicvoid open()
{
System.out.println("netcardopen");
}
publicvoid close()
{
System.out.println("netcardclose");
method();
}
}
class SoundCard implements PCI
{
publicvoid open()
{
System.out.println("SoundCardopen");
}
publicvoid close()
{
System.out.println("SoundCardclose");
}
}
class DuoTaiDemo5
{
publicstatic void main(String[] args)
{
MainBoardmb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(newNetCard());
mb.usePCI(newSoundCard());
}
}
面向对象(多态的扩展示例)
/*
需求:数据库的操作。
数据是:用户信息。
1,连接数据库。JDBC Hibernate
2,操作数据库。c create r read u update d delete
3,关闭数据库连接。
*/
interface UserInfoDao
{
publicvoid add(User user);
publicvoid delete(User user);
}
class UserInfoByJDBC implements UserInofDao
{
publicvoid add(User user)
{
1,JDBC连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
publicvoid delete(User user)
{
1,JDBC连接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class UserInfoByHibernate implementsUserInfoDao
{
publicvoid add(User user)
{
1,Hibernate连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
publicvoid delete(User user)
{
1,Hibernate连接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class DBOperate
{
publicstatic void main(String[] args)
{
//UserInfoByJDBCui = new UserInfoByJDBC();
//UserInfoByHibernateui = new UserInfoByHibernate();
UserInfoDaoui = new UserInfoByHibernate();
ui.add(user);
ui.delete(user);
}
}
面向对象(Object类)
Object:是所有对象的直接后者间接父类,传说中的上帝。
它里面的方法是所有对象都具备的。
常见方法:
booleanequals(Object obj):用于比较两个对象是否相同。
StringtoString(): 获取对象的字符串表现形式 类名@哈希值。
ClassgetClass():获取正在运行的对象所属的字节码文件的对象。
Object类中已经提供了对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。
class Demo
{
privateint num;
Demo(intnum)
{
this.num= num;
}
//复写equals方法
publicboolean equals(Object obj)
{
if(!(objinstanceof Demo))
returnfalse;
Demod = (Demo)obj;
returnthis.num == d.num;
}
/*
publicboolean compare(Demo d)
{
returnthis.num==d.num;
}
*/
//复写toString方法
publicString toString()
{
return"demo:"+num;
}
}
面向对象(内部类)
内部类的访问规则:
1,内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2,外部类要访问内部类,必须建立内部类对象。
访问格式:
1,当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。
外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Innerin = new Outer().new Inner();
2,当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装。
static:内部类就具备static的特性。
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
newOuter.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
内部类定义在局部时,
不可以被成员修饰符修饰
可以直接访问外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
匿名内部类:
1,匿名内部类其实就是内部类的简写格式。
2,定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
3,匿名内部类的格式:new 父类或者接口(){定义子类的内容}
4,其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。 可以理解为带内容的对象。
5,匿名内部类中定义的方法最好不要超过3个。
/*分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。
这时就是还有的事物定义成内部类来描述。*/
class Outer
{
privatestatic int num = 31;
classInner// 内部类。
{
voidshow()
{
System.out.println("showrun..."+num);
}
/*staticvoid function()//如果内部类中定义了静态成员,该内部类也必须是静态的。
{
System.out.println("functionrun ...."+num);
}
*/
}
publicvoid method()
{
Innerin = new Inner();
in.show();
}
}
class InnerClassDemo
{
publicstatic void main(String[] args)
{
Outerout = new Outer();
out.method();
//直接访问外部类中的内部类中的成员。
Outer.Innerin = new Outer().new Inner();
in.show();
//如果内部类是静态的。 相当于一个外部类
Outer.Innerin = new Outer.Inner();
in.show();
//如果内部类是静态的,成员是静态的。
Outer.Inner.function();
}
}