100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 黑马程序员——Java基础---继承 抽象 多态 接口 包 内部类

黑马程序员——Java基础---继承 抽象 多态 接口 包 内部类

时间:2021-08-17 16:43:05

相关推荐

黑马程序员——Java基础---继承 抽象 多态 接口 包 内部类

-----------android培训、java培训、java学习型技术博客、期待与您交流!------------

一、继承

(一)继承概述

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

通过extends关键字可以实现类与类的继承

class子类名extends父类名{}

单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。

有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。

(二)继承的好处与弊端

1.继承的好处:

(1)提高了代码的复用性

多个类相同的成员可以放到同一个类中

(2)提高了代码的维护性

如果功能的代码需要修改,修改一处即可

(3)让类与类之间产生了关系,是多态的前提

其实这也是继承的一个弊端:类的耦合性很强

2.继承的弊端

(1)耦合性增强,违背了我们的开发原则(高内聚,低耦合)

(2)高内聚:能自己干的事儿从来不求别人

(3)低耦合:类与类直接不要产生太多依赖

(三)Java中继承的特点

1.一个类只能有一个父类,不可以有多个父类。

理解:一个儿子只有一个亲爹

举例:

classSubDemoextendsDemo{}//true

classSubDemoextendsDemo1,Demo2...//error

2.Java支持多层继承(继承体系)

理解:类似家谱

举例:

classA{}

classBextendsA{}

classCextendsB{}

(四)注意事项

1.子类只能继承父类所有非私有的成员(成员方法和成员变量),父类的私有成员,子类不能继承,其实这也体现了继承的另一个弊端:打破了封装性

2.子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。

3.不要为了部分功能而去继承

4.我们到底在什么时候使用继承呢?

继承中类之间体现的是:”isa”的关系。

(五)super关键字

1.super的用法和this很像

this代表本类对应的引用。

super代表父类存储空间的标识(可以理解为父类引用)

2.用法(this和super均可如下使用)

访问成员变量

this.成员变量 super.成员变量

访问构造方法(子父类的构造方法问题讲)

this(…) super(…)

访问成员方法(子父类的成员方法问题讲)

this.成员方法() super.成员方法()

案例演示:

classPersonTest{

publicstaticvoidmain(String[]args){

Students=newStudent("子明",18,"czbk001");

System.out.println(s.name+"--"+s.age+"--"+s.studyNum);

s.eat();//继承来的

s.sleep();//继承来的

s.study();

Teachert=newTeacher("凌子峰",48,"czbk008");

System.out.println(t.name+"--"+t.age+"--"+t.workNum);

t.eat();

t.sleep();

t.work();

}

}

classPerson{

Stringname;//姓名

intage;//年龄

intmoney;

publicvoideat(){

System.out.println("下雨天,吃点热乎的");

}

publicvoidsleep(){

System.out.println("下雨天,特别适合补一觉,但是我还有事需要做。。。");

}

}

classStudentextendsPerson{

StringstudyNum;//学号

Student(){}

Student(Stringname,intage,StringstudyNum){

this.name=name;

this.age=age;

this.studyNum=studyNum;

}

publicvoidstudy(){

System.out.println("下雨天,好好学习");

}

}

classTeacherextendsPerson{

StringworkNum;//工号

Teacher(){}

Teacher(Stringname,intage,StringworkNum){

this.name=name;

this.age=age;

this.workNum=workNum;

}

publicvoidwork(){

System.out.println("下雨天,好好讲课");

}

}

运行结果:

(六)继承中成员变量的关系

成员变量的关系

不同名字:该用谁的就用谁的

相同名字:

1.子类使用的是子类自己的

2.子类想使用父类的变量,使用super关键字

理解:super代表了父类引用

this:你创建了当前对象,this是当前对象的引用

super:你没有创建父类对象,super可以理解为父类的引用,真正代表的是,父类存储空间的标识。

案列演示:

classVarDemo{

publicstaticvoidmain(String[]args){

//创建子类对象

Ziz=newZi();

z.show2();

System.out.println();

}

}

classFu{

intnum1=10;

publicvoidshow(){

System.out.println(num1);

}

}

classZiextendsFu{

intnum1=20;

publicvoidshow2(){

intnum1=30;

System.out.println("num1="+num1);

System.out.println("num1="+this.num1);

System.out.println("num1="+super.num1);

}

}

运行结果:

结论:在子类方法中访问一个变量的过程

1.首先在子类局部范围找

2.然后在子类成员范围找

3.最后在父类成员范围找(肯定不能访问到父类局部范围)

4.如果还是没有就报错。(不考虑父亲的父亲…)

(七)继承中构造方法的关系

明确:子类不能继承父类的构造方法,但是我们可以调用父类的构造方法

1.子类中所有的构造方法默认都会访问父类中空参数的构造方法

2.为什么呢?

因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。

3.每一个构造方法的第一条语句默认都是:super()

4.如果父类中没有构造方法,该怎么办呢?

子类通过super去显示调用父类其他的带参的构造方法

子类通过this去调用本类的其他构造方法

本类其他构造也必须首先访问了父类构造

一定要注意:

super(…)或者this(….)必须出现在第一条语句上,并且只能有一个。

否则,就会有父类数据的多次初始化

演示案列:

classTest{

publicstaticvoidmain(String[]args){

Ziz=newZi(20);

z.show();

}

}

classFu{

publicintnum=10;

privateintnum2;

publicFu(intnum2){

this.num2=num2;

}

publicvoidshow(){

System.out.println("num2="+num2);

}

}

classZiextendsFu{

publicintnum;

publicZi(){

this(0);

System.out.println("zi");

}

publicZi(intnum){

super(num);

this.num=num;

System.out.println("zi");

}

publicvoidshow(){

intnum=30;

System.out.println("num="+num);

System.out.println("num="+this.num);

System.out.println("num="+super.num);

super.show();

}

}

运行结果:

(八)继承中成员方法的关系

1.成员方法的关系:

当方法名不同时,子类可以直接调用父类的方法

相同名字:

(1)子类调用成员方法走的子类的

(2)子类和父类出现了一模一样的方法声明,包括方法名,返回值类型,参数列表,这里,父类的方法被子类的方法重写了

2.演示案例:

classAnimalTest{

publicstaticvoidmain(String[]args){

Catc=newCat();

c.sleep();

c.eat();

Dogd=newDog();

d.sleep();

d.eat();

}

}

classAnimal{

Stringname;

intleg;

publicvoidsleep(){

System.out.println("晚上睡觉");

}

publicvoideat(){

System.out.println("吃东西,倍儿香");

}

}

classCatextendsAnimal{

publicvoidsleep(){

System.out.println("白天睡觉");

}

publicvoideat(){

System.out.println("吃鱼,倍儿香...");

}

}

classDogextendsAnimal{

publicvoideat(){

System.out.println("吃骨头,倍儿香...");

}

}

运行结果:

3.结论:

通过子类对象去访问一个方法

首先在子类中找

然后在父类中找

如果还是没有就报错。(不考虑父亲的父亲…)

4.方法重写

(1)方法重写概述:子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。

(2)使用特点:

如果方法名不同,就调用对应的方法

如果方法名相同,最终使用的是子类自己的

(3)方法重写的应用:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

(4)方法重写的注意事项

父类中私有方法不能被重写

子类重写父类方法时,访问权限不能低于父类的

父类静态方法,子类也必须通过静态方法进行重写。

5.Override和Overload的区别?

Override:重写,子父类中,方法名一样,参数列表不同,返回值类型一样

Overload:重载,同类中,方法名一样,参数列表不同的方法,与返回值类型无关

(九)final关键字

final关键字是最终的意思,当描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这个值起个名字,以便于阅读。而这个值不需要改变,所以加上final修饰。

final可以修饰类,成员变量,成员方法。

修饰类,类不能被继承

修饰变量,变量就变成了常量,只能被赋值一次

修饰方法,方法不能被重写

final修饰变量的初始化时机

在对象构造完毕前即可(显示初始化)

基本类型被修饰后,是其值不能被改变

引用类型被修饰后,是其地址值不能被改变

简单案例演示:

classFinalDemo{

publicstaticvoidmain(String[]args){

finalStrings="192.168.36.72";

System.out.println(s);

finalintx=10;//值不能被改变

System.out.println(x);

finalint[]arr={123,4455};//地址值不能被改变

System.out.println(arr);

}

}

二、抽象类

没有办法具体描述的类,比如:水果,工具,蔬菜,情感……

(一)格式:

类:abstractclass类名{}

方法:publicabstractvoideat();

注意:抽象方法是没有方法体

抽象类中可以没有抽象方法,但是如果有抽象方法,那么此类必然为抽象类

(一)抽象类特点

1.抽象类和抽象方法必须用abstract关键字修饰

格式:

类:abstractclass类名{}

方法:publicabstractvoideat();

2.抽象类不一定有抽象方法,可以有非抽象方法,但有抽象方法的类一定是抽象类

3.抽象类中,有构造方法,但是抽象类不能直接new,也就是不能实例化

4.那么,抽象类如何实例化呢?

按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。

5.抽象类的子类

要么是抽象类

要么重写抽象类中的所有抽象方法

(三)抽象类的成员特点

成员变量

可以是变量

也可以是常量

构造方法

有构造方法,但是不能实例化

那么,构造方法的作用是什么呢?

用于子类访问父类数据的初始化

成员方法

可以有抽象方法,限定子类必须完成某些动作

也可以有非抽象方法,提高代码服用性

(四)abstract不能和哪些关键字共存

private 冲突--对子类隐藏,无法被复写,而abstract必须让子类重写

final 冲突-- 被final修饰后,不能被重写,矛盾

static 无意义–类名调用,没有方法体,无意义

(五)老师案例

具体事物:基础班老师,就业班老师

共性:姓名,年龄,讲课。

classTeacherAbstract{

publicstaticvoidmain(String[]args){

BaseTeacherbt=newBaseTeacher("小李广",28);

System.out.println("我叫"+bt.getName()+",今年"+bt.getAge());

bt.teach();

System.out.println("----------------------------------------");

EmploymentTeacheret=newEmploymentTeacher("凌子峰",29);

System.out.println("我叫"+et.getName()+",今年"+et.getAge());

et.teach();

}

}

abstractclassTeacher{

//成员变量

privateStringname;

privateintage;

//构造函数

Teacher(){}

Teacher(Stringname,intage){

this.name=name;

this.age=age;

}

//get/set

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

//抽象方法

publicabstractvoidteach();

}

classBaseTeacherextendsTeacher{

BaseTeacher(){}

BaseTeacher(Stringname,intage){

super(name,age);

}

publicvoidteach(){

System.out.println("我主讲Java_SEcourse,打好基础好上就业班");

}

}

classEmploymentTeacherextendsTeacher{

EmploymentTeacher(){}

EmploymentTeacher(Stringname,intage){

super(name,age);

}

publicvoidteach(){

System.out.println("我主讲Java_EEcourse,学好EE好就业");

}

}

运行结果:

三、多态

(一)多态的概述:某一个事物,在不同时刻表现出来的不同状态。

(二)多态前提和体现

有继承关系

有方法重写

有父类引用指向子类对象

(三)成员访问特点

成员变量:编译看左边,运行看左边

成员方法:编译看左边,运行看右边

静态方法:编译看左边,运行看左边

(四)多态的好处和弊端

1.好处多态的好处

提高了程序的维护性(由继承保证)

提高了程序的扩展性(由多态保证)

2.多态的弊端

不能访问子类特有功能

那么我们如何才能访问子类的特有功能呢?

多态中的转型

3.向上转型

从子到父

父类引用指向子类对象

4.向下转型

强制:从父到子

父类引用转为子类对象

格式:子类变量名=(子类类型)父类变量名;

好处:

转型之前,父类p并不能使用子类的特有功能

转型之后,父类就可以使用子类的功能.

(五)案例演示:钢铁侠变身过程

classIronManDuoTai{

publicstaticvoidmain(String[]args){

//向上转型,从子类-->父类,父类引用指向子类对象

//使用多态创建对象

Personp=newIronMan();

System.out.println("这是谁?");

//输出属性,是父类的

System.out.println("我啊,不认识了吗?"+p.name+"啊!");

System.out.println("怎么做起这个了?");

System.out.print("没办法,只能靠");

//调用方法,是子类的

p.business();

System.out.println("赚点外快了");

//变身过程,向下转型,强制转换,从父类-->子类

System.out.println("前方有情况,救命啊~~~~~~~");

IronManim=(IronMan)p;

im.fly();

System.out.print("我是"+im.name+",");

im.savePeople();

}

}

//定衣父类Person

classPerson{

Stringname="托尼.斯塔克";

publicvoidbusiness(){

System.out.println("开厂子,很赚钱");

}

}

//定义子类IronMan

classIronManextendsPerson{

Stringname="钢铁侠";

publicvoidbusiness(){

System.out.print("合影5块");

}

publicvoidfly(){

System.out.println("飞。。。");

}

publicvoidsavePeople(){

System.out.println("我来救人");

}

}

运行结果:

四、接口

(一)接口概述:本质就是一种规则

(二)作用:就是扩展类功能

(三)特点:

1.接口用关键字interface表示

格式:interface接口名{}

2.类实现接口用implements表示

格式:class类名implements接口名{}

3.接口不能实例化

4.那么,接口如何实例化呢?

按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。

5.接口的子类

要么是抽象类

要么重写接口中的所有抽象方法

6.接口中可以写方法,但是必须是抽象的.

(四)接口成员特点

成员变量

只能是常量:默认修饰符publicstaticfinal

构造方法

没有,因为接口主要是扩展功能的,而没有具体存在

成员方法

只能是抽象方法:默认修饰符publicabstract

(五)类与类,类与接口以及接口与接口的关系

类与类

继承关系,只能单继承,但是可以多层继承

类与接口

实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口

接口与接口

继承关系,可以单继承,也可以多继承

(六)抽象类和接口的区别

成员区别

抽象类:变量,常量;有抽象方法;抽象方法,非抽象方法

接口:常量;抽象方法

关系区别

类与类:继承,单继承

类与接口:实现,单实现,多实现

接口与接口:继承,单继承,多继承

设计理念区别

抽象类:被继承体现的是:”isa”的关系。共性功能

接口:被实现体现的是:”likea”的关系。扩展功能

(七)教练和运动员案例

乒乓球运动员和篮球运动员。

乒乓球教练和篮球教练。

为了出国交流,跟乒乓球相关的人员都需要学习英语。

classCoachAndPlayer{

publicstaticvoidmain(String[]args){

PPCoachppc=newPPCoach("刘国梁","棕色",42);

System.out.println("我叫"+ppc.getName()+",今年"+ppc.getAge()+"岁"+",有一双"+ppc.getEyes()+"的眼睛");

ppc.teach();

ppc.eat();

ppc.sleep();

ppc.studyEnglish();

System.out.println("----------------------------");

PPPlayerppp=newPPPlayer("凌子峰","黑色",20);

System.out.println("我叫"+ppp.getName()+",今年"+ppp.getAge()+"岁"+",有一双"+ppp.getEyes()+"的眼睛");

ppp.play();

ppp.eat();

ppp.sleep();

ppp.studyEnglish();

System.out.println("----------------------------");

BBCoachbbc=newBBCoach("贺子皓","黑色",40);

System.out.println("我叫"+bbc.getName()+",今年"+bbc.getAge()+"岁"+",有一双"+bbc.getEyes()+"的眼睛");

bbc.teach();

bbc.eat();

bbc.sleep();

System.out.println("----------------------------");

BBPlayerbbp=newBBPlayer("韩以风","棕色",21);

System.out.println("我叫"+bbp.getName()+",今年"+bbp.getAge()+"岁"+",有一双"+bbp.getEyes()+"的眼睛");

bbp.play();

bbp.eat();

bbp.sleep();

}

}

abstractclassPerson{

privateStringname;

privateintage;

privateStringeyes;

//构造方法

Person(){}

Person(Stringname,Stringeyes,intage){

this.name=name;

this.eyes=eyes;

this.age=age;

}

//get/set

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetEyes(){

returneyes;

}

publicvoidsetEyes(Stringeyes){

this.eyes=eyes;

}

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

//成员方法

publicvoideat(){

System.out.println("吃东西");

}

publicabstractvoidsleep();

}

//教练

abstractclassCoachextendsPerson{

Coach(){}

Coach(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicabstractvoidteach();

publicvoidsleep(){

System.out.println("教练晚上睡觉");

}

}

//运动员

abstractclassPlayerextendsPerson{

Player(){}

Player(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicabstractvoidplay();

publicvoidsleep(){

System.out.println("运动员晚上睡觉");

}

}

//接口

interfaceStudy{

publicabstractvoidstudyEnglish();

}

//乒乓球教练

classPPCoachextendsCoachimplementsStudy{

PPCoach(){}

PPCoach(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicvoidteach(){

System.out.println("我教乒乓球");

}

publicvoidstudyEnglish(){

System.out.println("学英语");

}

}

//篮球教练

classBBCoachextendsCoach{

BBCoach(){}

BBCoach(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicvoidteach(){

System.out.println("我教篮球");

}

}

//乒乓球运动员

classPPPlayerextendsPlayerimplementsStudy{

PPPlayer(){}

PPPlayer(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicvoidplay(){

System.out.println("我会玩乒乓球");

}

publicvoidstudyEnglish(){

System.out.println("学英语");

}

}

//篮球运动员

classBBPlayerextendsPlayer{

BBPlayer(){}

BBPlayer(Stringname,Stringeyes,intage){

super(name,eyes,age);

}

publicvoidplay(){

System.out.println("我会玩篮球");

}

}

运行结果:

五、形式参数和返回值问题案例

抽象类作为形式参数,要的是抽象类的子类对象

牌有很多种--麻将,三国杀,多米诺骨牌

所有我们牌定义为抽象类

接口作为形式参数,要的是实现了接口的子类对象

牌还有扩展功能--变魔术

classPersonTest{

publicstaticvoidmain(String[]args){

//创建人的对象

Personp=newPerson();

//创建纸牌的对象

Cardc=newCard();

p.play(c);

//父类牌指向子类麻将

Paipai=newMaJiang();

p.play2(pai);

//变魔术

Magicm=newCard();

p.play3(m);

}

}

classPerson{

//人打纸牌的方法

publicvoidplay(Cardc){

c.bang();

c.shunzi();

}

//人玩牌

publicvoidplay2(Paip){

p.fun();

}

//人用纸牌变魔术

publicvoidplay3(Magicm){

m.moShu();

}

}

//定义接口

interfaceMagic{

publicabstractvoidmoShu();

}

//抽象的牌类

abstractclassPai{

publicabstractvoidfun();

}

//纸牌继承了牌类,实现了Magic接口

classCardextendsPaiimplementsMagic{

//牌有炸的方法

publicvoidbang(){

System.out.println("炸了,翻倍...");

}

//牌有顺子的方法

publicvoidshunzi(){

System.out.println("顺出去,没了.....");

}

//娱乐

publicvoidfun(){

System.out.println("打牌虽好,不要沉迷哦!!!");

}

//用牌可以变魔术

publicvoidmoShu(){

System.out.println("给女神,变魔术.....");

}

}

classMaJiangextendsPai{

//娱乐

publicvoidfun(){

System.out.println("打麻将虽好,四圈差不多了");

}

}

运行结果:

抽象类作为返回值类型,返回的是抽象类的子类对象

发牌机不光发纸牌,还能发别的牌(麻将)

classFaPaiJiTest{

publicstaticvoidmain(String[]args){

//创建人对象

Personp=newPerson();

//获取发牌机

FaPaiJifpj=p.getFaPaiJi();

Cardc=fpj.faPai();

c.tongHuaShun();

c.fun();

Magicm=newPerson().getFaPaiJi().faPai3();//链式编程

m.moShu();

//newPerson().getFaPaiJi().faPai3().moShu();

}

}

classPerson{

//人使用发牌机工作

publicCardwork(FaPaiJifpj){

Cardc=fpj.faPai();

returnc;//Card

}

//人拿到发牌机

publicFaPaiJigetFaPaiJi(){

returnnewFaPaiJi();

}

}

classFaPaiJi{

//发牌机发牌

publicCardfaPai(){

Cardc=newCard();

returnc;

}

publicPaifaPai2(){

//返回的是抽象类的子类对象

Paip=newCard();//多态

returnp;

}

publicMagicfaPai3(){

//返回的是接口的实现类的子类对象

Magicm=newCard();//多态

returnm;

}

}

//定义接口

interfaceMagic{

publicabstractvoidmoShu();

}

//定义牌类

abstractclassPai{

publicabstractvoidfun();

}

//card继承牌类,实现接口

classCardextendsPaiimplementsMagic{

publicvoidtongHuaShun(){

System.out.println("同花顺.....");

}

publicvoidfun(){

System.out.println("玩牌好好玩~~~");

}

publicvoidmoShu(){

System.out.println("给女神,变魔术.....");

}

}

运行结果:

六、包

(一)包的概述:其实就是文件夹,对类进行分类管理

(二)包的划分:

举例:

按类划分:

学生类

增加:create

删除:delete

修改:update

查询:query

老师类

增加:create

删除:delete

修改:update

查询:query

按功能分:

增加:

增加老师,增加学生

删除:

删除老师,删除学生

修改:

修改老师,修改学生

查询:

查询老师,查询学生

(三)定义包的格式

package包名;

多级包用.分开即可

注意事项:

package语句必须是程序的第一条可执行的代码

package语句在一个java文件中只能有一个

如果没有package,默认表示无包名

(四)带包的类的编译和运行

手动式

a:javac编译当前类文件。

b:手动建立包对应的文件夹。

c:把a步骤的class文件放到b步骤的最终文件夹下。

d:通过java命令执行。注意了:需要带包名称的执行

javacn.itcast.HelloWorld

自动式

a:javac编译的时候带上-d即可

javac-d.HelloWorld.java

b:通过java命令执行。和手动式一样

(五)包的作用

1.为避免多个类重名的情况,如果出现两个相同名字的类,可通过包将两者区分,从而避免冲突。

2.对类文件进行分类管理,可以将相关的一些类放在同一个包中。

3.给类提供多层命名空间,如a包中的Demo.class文件,如果要创建Demo对象,就要在使用上加上a.如:a.Demodemo=newa.Demo();

4.包的出现可以将java的类文件和源文件相分离。

(六)规则

1.包必须写在程序的第一行。因为要先有包,才知道类文件的存放地

2.package只有一句,如果不写package,那么默认在当前文件夹

3.类的全称:包名.类名

4.编译定义了包的程序文件,在编译时要指定包的存储目录。如:javac—dc:\mypack类名.java。

(七)导包

1.导包概述:不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候,java就提供了导包的功能。

2.导包的格式:

import包名;

注意:

这种方式导入是到类的名称。

虽然可以最后写*,但是不建议。

例如:

importjava.util.Scanner;

importjava.util.*;

3.package,import,class的顺序关系

package>import>class

4.包中的访问

(1)要访问其他包中的类,需要定义类的全称:包名.类名

(2)包如果不在当前路径,需要使用classpath设定环境变量,为JVM指明路径。

(3)被访问的包中的类的权限必须是public。

(4)类中的成员权限:public或者protected,protected是为其他包中的子类提高的一种权限。类共有后,被访问的成员也要共有才可以被访问。不同包中的子类可以直接访问父类中被protected权限修饰的成员。同一包中,protected只作为覆盖。

5.权限修饰符

注意:一个java文件里面,不能出现两个以上的共有类或者接口。因为被public修饰的类名必须与java文件名相同。

6.类及其组成可以用的修饰符

(1)类:

默认,public,final,abstract

我们自己定义:public居多

(2)成员变量:

四种权限修饰符均可,final,static

我们自己定义:private居多

(3)构造方法:

四种权限修饰符均可,其他不可

我们自己定义:public居多

(4)成员方法:

四种权限修饰符均可,fianl,static,abstract

我们自己定义:public居多

七、内部类

(一)内部类概述:把类定义在其他类的内部,这个类就被称为内部类。

举例:在类A中定义了一个类B,类B就是内部类。

(二)内部类的访问特点

1.内部类可以直接访问外部类的成员,包括私有。

之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this。

2.外部类要访问内部类的成员,必须创建对象。当内部类私有就不能再直接创建内部类对象。

(三)内部类位置

按照内部类在类中定义的位置不同,可以分为如下两种格式:

成员位置(成员内部类)

局部位置(局部内部类)

1.成员内部类

(1)外界如何创建对象

外部类名.内部类名对象名=外部类对象.内部类对象

(2)成员内部的常见修饰符

private为了保证数据的安全性

static为了让数据访问更方便

被静态修饰的成员内部类只能访问外部类的静态成员

内部类被静态修饰后的方法

静态方法:直接内部类名.成员方法

非静态方法:创建对象类访问

(3)案例演示

classInnerClass{

publicstaticvoidmain(String[]args){

Outero=newOuter();

o.display();

System.out.println("------------");

Outer.Inner.show1();

}

}

classOuter{

privateintn=1;

staticintnum=200;

staticclassInner{

intn=10;

publicvoidshow(){

intn=120;

System.out.println("n的值为:"+this.n);

System.out.println("n的值为:"+n);

System.out.println("n的值为:"+newOuter().n);

}

publicstaticvoidshow1(){

System.out.println("num的值为:"+num);

}

}

publicvoiddisplay(){

Inneri=newInner();

i.show();

}

}

运行结果:

2.局部内部类

(1)概述:局部内部类就是方法内部的类

可以直接访问外部类的成员,在方法内部创建内部类的对象,才能使用到内部类的功能。

在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能,

本质:实现了接口(继承类)的子类匿名对象。

(2)局部内部类访问局部变量的注意事项:

必须被final修饰,为什么呢?因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。通过反编译工具可以看一下。

(3)案例演示

classOuterTest{

publicstaticvoidmain(String[]args){

//创建外部类对象

Outero=newOuter();

o.method();

System.out.println();

}

}

classOuter{

privateintnum=2;

publicvoidmethod(){

finalintnum=6;//注:从内部类中访问本地变量num;需要被声明为最终类型

//局部内部类

classInner{

publicvoidshow(){

System.out.println("num="+num);

System.out.println("num="+newOuter().num);

}

}

//创建内部类对象

Inneri=newInner();

i.show();

}

}

运行结果:

(四)匿名内部类

1.就是内部类的简化写法。

2.前提:存在一个类或者接口

这里的类可以是具体类也可以是抽象类。

3.格式:

new类名或者接口名(){重写方法;}

4.本质:

是一个继承了类或者实现了接口的子类匿名对象

5.匿名内部类中定义的方法最好不要超过3个。

6.匿名内部类的利与弊

好处:简化书写

弊端:

①不能直接调用自己的特有方法。

②不能做强转动作

③如果继承的父类或接口中有很多方法时,使用匿名内部类,阅读性会非常差,而且调用会很麻烦。所以匿名内部类中定义的方法一般不超过3个。

案例演示

classAnonymityTest{

publicstaticvoidmain(String[]args){

Anonymitya=newAnonymity();

a.method();

}

}

//存在一个接口Inter

interfaceInter{

publicabstractvoidshow();

}

classAnonymity{

publicvoidmethod(){

newInter(){

//重写方法

publicvoidshow(){

System.out.println("HelloWorld...");

}

}.show();

}

}

运行结果:

7.加入方法有多个,如何调用呢?

方式1:每一种格式调用一个,太麻烦

方式2:用类或者接口接收该子类对象,多态思想

案例演示:

classAnonymityTest{

publicstaticvoidmain(String[]args){

Anonymitya=newAnonymity();

a.method();

}

}

//存在一个接口Inter

interfaceInter{

publicabstractvoidshow();

publicabstractvoidshow1();

}

classAnonymity{

publicvoidmethod(){

Interi=newInter(){//接口指向子类对象,多态思想

//重写方法

publicvoidshow(){

System.out.println("HelloWorld...");

}

publicvoidshow1(){

System.out.println("What?");

}

};

i.show();

i.show1();

}

}

运行结果:

8.接口作为形式参数的案例演示

classPersonTest{

publicstaticvoidmain(String[]args){

PersonStudyps=newPersonStudy();

ps.show(newPerson(){

publicvoidstudy(){

System.out.println("一起好好学Java~~~~~~");

}

});

System.out.println();

}

}

classPersonStudy{

//接口作为形式参数

publicvoidshow(Personp){

p.study();

}

}

interfacePerson{

publicabstractvoidstudy();

}

9.练习题:按照要求,补齐代码

interfaceInter{voidshow();}

classOuter{//补齐代码}

classOuterDemo{

publicstaticvoidmain(String[]args){

Outer.method().show();

}

}

要求在控制台输出”HelloWorld”

分析:

(1)Outer.method(),类名.方法名,说明method是静态方法

(2)method().show(),说明method返回值类型为对象

返回的是Inter的实现类的子类匿名对象

实现代码:

classOuter{

publicstaticIntermethod(){

returnnewInter(){

publicvoidshow(){

System.out.println("HelloWorld");

}

};

}

}

-----------android培训、java培训、java学习型技术博客、期待与您交流!------------

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。