java学习心得

更新时间:2024-06-28 21:44:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1、继承和重载

关于继承的理解就应从简单的父子关系理解吧,父与子是一种很特殊的关系,儿子继承了父亲的很多特征,但是儿子和父亲有所不同。问你一个简单的问题一个儿子 可能有两个亲生父亲吗?当然不可能!所以Java没有多继承!也许你会问这样讲Java不是胡诌吗?在这里你一定要知道Java的一条真理:万物皆对象。 理解一个Java的语法不可死记硬背,一定要和对象联系起来。相信现在你一定不会忘记Java不支持多继承了!

学习一门知识如果可以理解它而不是机械的记忆,会获得很多意想不到的收获,在学习的同时又加深的对万事万物的领悟这不是我们追求的一种逍遥吗? 在Java中引入继承的概念主要是为了方法的覆盖和重载打下一个坚实的基础。在这里我想先着重讲一下重载。很多人分不清什么是重载什么是覆盖,如果是这样我可以告诉你一个很简单你的办法,只要知道它是不是重载就好了。 想一想最原始的类的概念吧,就是把确实存在事物转变成计算机的一种数学模型罢了,比如说人类,Java中就叫Public class Person(关于命名规范的问题可以自己查一下Java的API

只要照着其中规范写就可以了)我们人类有很多的行为,在Java中把类的行为称为方法,我举一个例子吧,比如吃饭是一种行为,但是放入我们口中可能是各种 各样的食物,如果是苹果我们就咬着吃,如果是八宝粥我们就喝了它,如果喂我们吃草呢?当然要吐掉,还要大骂一声是谁这么缺德,给我吃草!好了不开玩笑了, 写一个程序!

package Blog; //Blog是包名

public class Apple//苹果 { }

package Blog;

public class Babao//八宝粥 { }

package Blog;

public class Weed//草 { }

package Blog;

public class Person//人类

{//定义了3个重载的方法,参数表不同 public void eat(Apple apple) {

System.out.println(\苹果来了,咬着吃\ }

public void eat(Babao babao) {

System.out.println(\好香的八宝粥,喝了它\ }

public void eat(Weed weed) {

System.out.println(\是谁这么缺德,给我吃草!\ } }

package Blog;

public class Test {

public static void main(String[] args) { Person person=new Person(); Apple apple=new Apple(); Babao babao=new Babao(); Weed weed=new Weed(); person.eat(apple); person.eat(babao); person.eat(weed); } }

测试程序中最后三行的都是吃的方法,但是参数表不同,结果也是完全不同的。

从这个例子我们可以看出这就是重载,记住它的本质就是方法名相同,参数表一定不同。

所以判断一个方法是不是另一个方法的重载只需要看这两点。当然还有一点你要知道如果子类一个方法和父类的一个方法满足这两个条件它也是一种重载!

关于继承的补充:一个父类拥有的方法子类是可以继承的,所以在编写子类的时候如果不需要改变某个父类方法那么字子类中可以不写这个方法,子类将自动持有这个方法!

同包的时候子类无条件继承除了父类的私有属性和方法之外的一切属性和方法 不同包的时候子类继承父类的public和protected级别的属性和方法

2、方法的覆盖

在讨论方法的覆盖时我还想拿父子做一个例子,为了把问题讲得更明白些,我决定把爷爷也加入其中,祖孙三代同堂帮我完成方法覆盖的任务。想一想在我们祖辈时 期写字用的是毛笔,现在呢,用计算机打字了,从面向对象的观点来看,祖孙三的代很多特性和行为都没有改变,只是很少的一部分改变了,如果我们在每个类中的 重写相同的方法想一想是不是很合理呢?当然不是的,所以对于没有改变的行为在子类中就不需要重复再写了,只有那些已经改变了的方法,我们才需要重写它。对 于这个在子类中被重新写入的方法我们把它叫做方法的覆盖。举一个例子 package blog;

public class Grandfather { public void write() {

System.out.println(\用毛笔写字!\

} }

package blog;

public class Father extends Grandfather{ }

package blog;

public class Son extends Father{ public void write() {

System.out.println(\我们是新一代,写字用电脑!\ } }

package blog;

public class Test {

public static void main(String[] args) {

Grandfather grandfather=new Grandfather();

Father father=new Father(); Son son=new Son(); grandfather.write(); father.write(); son.write(); } }

在这个测试程序中我建立了三个类,爷爷,父亲,儿子他们都具有写的行为,在面向对象中称为方法,如果父亲的写的行为和爷爷一样,我们就不需要重新定义它, 只要用关键字extends来表示它们之间的一种继承关系就行了,但是到了儿子这一代除了要声明他和父类的继承关系之外,由于写的方法发生了重大的变化, 所以我们必须重新定义它,在面向对象中我们称它为方法的覆盖。关于覆盖还有几点要声明一下

1、覆盖的方法必须存在父子类的继承关系,方法的名称,参数,返回值必须完全一致。

2、子类的覆盖方法的权限不能低于父类方法的权限,抛出的异常不能多余父类定义的异常

以上两点必须牢记!

除此以外就是静态方法只能被静态方法覆盖,父类的私有方法不能被子类覆盖

还有两点就是语法规定了,我觉得用处不大感兴趣的话可以了解一下。 父类的抽象方法被子类覆盖的方式有两种:一种是重新声明为抽象方法,另一种就是在子类中实现它。

父类的非抽象方法可以被覆盖为抽象方法。

Abstract是修饰符,代表抽象,这里还没有接触到抽象和异常所以我们暂时不管它,跳过去就好了。

之前我曾说过,方法的覆盖有点难,学过C++的朋友可能会说这有什么难的和我们学的语法一样吗!正如我之前所说Java的语法并不困难,困难的是一种思想的学习和思维的转变。

试想一下只要存在父子类关系就可以随便的覆盖非私有的方法是一件很方便的事情还是很可怕的事情?还是举一个生活中常见的例子看一下,如果把银行看成一个 类,那么储蓄所应该就是它的子类了,银行是为公众服务的,自然会有一个公开的取钱的方法,如果银行的子类储蓄所被人恶意覆盖了取钱的方法会怎么样?想想如 果是你会怎样改?假如银行类有这样的方法取钱public int withdraw(int i){return i}到了储蓄所这个方法会被恶意修改成public int withdraw(int i){return i*10}这样的方法可是一个快速致富的捷径呀! 所以说父子类中方法的覆盖会给编程带来重大隐患。也许你会问,Java已经是世界第一大编程语言了,为什么还会犯这种错误呀?其实这个问题很好回答,因为 面向对象的思想是在逐步深刻的,就是现在也没有被完全认识清楚,何况是在1995年,即使Java的创始者是一个计算机的天才,但他也是一个人,是人就会 发错误!这就是我们常说的认识有多远,就能走多远。在Java的语法中还会有很多这样的不足,解决的办法我会在模式设计中给出一些方案!

3、多态

这次我们聊一聊多态,多态应该是Java基础中非常重要的一部分,它的地位应该仅次于接口。为什么这么说呢?因为它使我们的编程更加灵活!如果你之前读过 一些Java的书籍,可能会经常看到这样的话:学习Java就像搭积木,或者是迷宫,走进去出不来,这句话恐怕就是对多态而言的。大部分的书中讲多态都是 从语法开始的,我想别出心裁换一种方法,从这种思想的诞生讲起,试想一下我们每个人都有手机,手机的供电方式有两种,一种是电池供电,另一种就是线充。这 是完全不同的两种供电方式,但是对手机供电的效果都是一样的。于是我们大胆设想一下,可不可以把这种生活中的例子引入面向对象的程序中,为我们服务呢?从 手机的观点来看无论是电池还是线充它们都是手机供电装置,唯一不同的只是供电的具体手段不同罢了。于是多态的观念就产生了。 我们先写一个供电类 package blog;

public class ElectricProvider {

public void provide()//供电方法 {} }

他有两个子类一个是电池类,一个是线充类 package blog;

public class Battery extends ElectricProvider{ public void provide() {

System.out.println(\电池供电\ } }

package blog;

public class Transformer extends ElectricProvider{

public void provide() {

System.out.println(\线充供电\ }

}

再写一个手机类 package blog;

public class Mobile {

public void work(ElectricProvider ep) {

ep.provide(); } }

以下是测试 package blog;

public class Test {

public static void main(String[] args) {

Mobile mobile=new Mobile(); ElectricProvider ep=new Battery();

mobile.work(ep);//根据实参的类型自动选择方法,这个实参是Battery类型,所以会运行电池供电的方法

ep=new Transformer();

mobile.work(ep);//根据实参的类型自动选择方法,这个实参是Transformer类型,所以运行线充供电的方法 } }

看到mobile.work(ep)这个方法了吗,它就是多态,第一次出现的时候被理解成电池,第二次出现的时候别理解成充电器,多种状态都出现了,多态故此得名!

它有两点好处:第一编程大大简单了,无论是电池还是线充只要用

mobile.work(ep)就搞定了,是不是很方便,还有就是实参的方法被隐藏了。从mobile.work(ep)看不出ep是如何调用方法的!

这种机制在机器内部是如何执行的?请慢慢听我道来。众所周知程序要先编译再运行,Java也不例外,在执行编译的时候mobile.work(ep)这条 语句是这样处理的:首先会判断ep的类型是什么?在编译时是按照声明的类型来判断的,所以ep是ElectricProvider类型,由于 ElectricProvider中有provide方法,所以编译顺利通过。在运行程序时ep的类型并非按照声明的类型来处理,而是它的实际类型,第一 次ep的实际类型是Battery所以会执行Battery的provide方法,第二次ep的实际类型是Transformer所以执行的方法是 Transformer的provide方法。这就是多态的运行机制!

多态对于Java是很重要的,它体现了一种思想,针对父类编程。看一看在程序中public void work(ElectricProvider ep)是不是真对父类,

ElectricProvider ep=new Battery();ep=new Transformer();是不是把子类对象都声明为父类的引用。它的好处还不止于此,以后我们还要接触到针对接口编程,那是Java的核心,如果你能对“针对父类编程”有深刻体会的话,那么针对接口编程你也会很快理解的。

PS:什么是对象的引用?

Java号称去掉了指针的语法,其实只是去掉了针对指针的操作,而且把指针改了一个名字叫引用,例如上面的程序ElectricProvider ep=new Battery(),我们声明了一个ElectricProvider类型的指针(引用),它指向计算机的内存中的一个地址,这个地址是存储 Battery对象的首地址,后面又执行了一句ep=new Transformer();此时计算机的内存中又存储了一个Transformer类型的对象,这时ep指针中指向的地址就变成了 Transformer类型的对象的首地址。这是我第一次也是最后一次说指针了,因为C++的程序员们对指针很熟悉,所以我把引用称为指针是为了让大家更 好的理解引用的实质,但是以后不会说了,毕竟我们要进军Java领域,以后要尝试着说Java的行话!

4、组合

接着上次的的例子谈谈组合,想想我们买手机的时候除了手机本身是不是已经包括电池了?

没有电池的手机是无法工作的,所以电池应该是手机的一部分,这样说来上面那个例子的手机类的写法就可以做一点小的修改 package blog;

package blog;

public class Mobile {

private Battery battery;

public Mobile(Battery battery) {

this.battery = battery; }

public void setBattery(Battery battery) { this.battery = battery; }

public void work() {

battery.provide(); } }

从这里可以看出,电池已经作为了手机的一部分,另外我又添加了一个public void setBattery(Battery battery)的方法,想一想这个方法是做什么用的呢?如果手机的电池坏了,可不可以换一块呢?这个方法就提供了更换电池的手段。 请看测试函数 package blog;

public class Test {

public static void main(String[] args) {

Battery battery=new Battery(); Mobile mobile=new Mobile(battery); mobile.work();

Battery second=new Battery();//新电池一块 mobile.setBattery(second);//和手机绑定 mobile.work();//手机工作 } }

从测试函数可以看出第一次用构造函数构造了一个手机,然后手机开始工作。之后又创建了一个新的电池对象second用set方法和手机进行了绑定,然后手机就可以继续工作了!

有没有朋友很好奇,你怎么知道电池已经换了呢?好,现在我就告诉你一个证明的小方法。

电池对象battery和second都是存在计算机的内存中,只要能证明它们的存储地址确实不同,就可以证明电池真的更换了。于是可以写一个方法放在手机类中 public void showme() {

System.out.println(\电池的编号是\ }

这个方法输出当前手机对象关联的电池对象的内存地址,我们假设电池的内存地址为电池的编号。通过这个方法就可以在这测试函数中看出结果 package blog;

public class Test {

public static void main(String[] args) {

Battery battery=new Battery(); Mobile mobile=new Mobile(battery); mobile.showme();//输出电池编号 mobile.work();

Battery second=new Battery();//新电池一块 mobile.setBattery(second);//和手机绑定 mobile.showme();//输出更换后的电池编号 mobile.work();//手机工作 } }

运行的结果是

电池的编号是blog.Battery@9cab16 电池供电!

电池的编号是blog.Battery@1a46e30 电池供电!

可以看出编号确实不同,证明电池确实更换过了!

通过这道小题目是不是可以很好的理解组合了?对于面向对象的思想有没有了一点自己的认知?对,面向对象就是这么好学!

如果你还有兴趣我看一给你介绍一个更复杂一点的例子 我们把手机类改成这样

package blog;

public class Mobile {

private ElectricProvider ep;

public Mobile(ElectricProvider ep) {

this.ep = ep; }

public void set(ElectricProvider ep) { this.ep = ep; }

public void work() {

ep.provide(); } }

手机类中不再持有电池类的引用而变成了它的父类ElectricProvider,其他的都没变就轻松的实现了多态,看看测试函数

public class Test {

public static void main(String[] args) {

Battery battery=new Battery(); Mobile mobile=new Mobile(battery);

mobile.work();

Transformer transformer=new Transformer();//改用线充供电 mobile.set(transformer);//和手机绑定 mobile.work(); } }

通过多态我们轻松的实现了电池供电和线充供电的一致性编程,还记得这叫什么吗?对,就是针对父类编程!

通过这几个例子你有没有发现面向对象编程既灵活又有趣,和搭积木很相象!只要你的思路足够清晰就不会走近Java的迷宫,相反会走进Java圣殿,身在其中,其乐融融!

5、修饰符之static

Static修饰符是Java中最常用的修饰符之一,可以用来修饰类中的成员变量,成员方法,除此以外还可以修饰程序的代码块,称为静态代码块。

具体用法如下

用static修饰的方法称为静态方法,静态方法不需要通过类的实例化就可以直接使用。 例如

package blog;

public class A {

public static void print() {

System.out.println(\静态的打印方法!\ }

public void print1() {

System.out.println(\实例方法的打印方法!\ } }

package blog;

public class Test {

public static void main(String[] args) { A.print();//静态方法可以直接使用类名加方法名

A a=new A();

a.print1();//实例方法必须用对象名加方法名 } }

特别需要注意的是静态方法不能用abstract修饰,因为静态方法必须在本类中提供实现,而abstract方法是在子类中实现,二者自相矛盾。

Static在Java语法中占有很重要的地位,它修饰方法时,表示该方法是类的方法不用依靠某个具体的类的实例,只要完成了类加载,就可以使用该方法。如上面的主方法public static void main(String[] args)就是通过类加载完成方法实现的。因为只要Test类被加载,就不用实例化一个对象,从而直接执行mian方法。

用static修饰的变量称为静态变量

在类加载的过程中完成静态变量的内存分配,可以直接通过类名加变量名直接访问该变量。

静态变量有点类似于C++中的全局变量。 比如

package blog;

public class A {

public static int num=5; public void setNum(int num)

{this.num=num;}

public static void print() {

System.out.println(\ } }

package blog;

public class Test {

public static void main(String[] args) { A.print();//打印num=5 A a1=new A(); a1.setNum(8);

A.print();//打印num=8 A a2=new A(); a2.setNum(3);

A.print();//打印num=3 } }

static变量的作用是用来在类中不同对象的数据共享

static代码块

静态代码块在类加载的时候只执行一次,如果把构造方法看成对象的初始化,则可以把静态代码块看成类的初始化,在代码块中可以初始化类中的静态变量,如 package blog;

public class A {

public static int num; static {num=7;}

@SuppressWarnings(\ public void setNum(int num) {this.num=num;}

public static void print() {

System.out.println(\ } }

在静态代码块中完成静态变量num的初始化,此时num值为7

静态代码块还可以完成一些其他的初始化。在JDBC(一种连接数据库的技术,用Java实现)的应用中可以经常看到!

PS:最后需要补充的一点的是实例方法和实例变量都不能在静态方法或者静态代码块中出现,this和super关键字也不能在静态方法和静态代码块中出 现,原因是static关键字是用来修饰属于类的变量和方法,而所有和具体对象相关的实例方法,实例变量及与实例相关的关键字(this,super)都 不能放入,不然会造成自相矛盾,编译也会报错!

6、修饰符之abstract

Abstract修饰符用来修饰类和方法

用abstract修饰类表示这是一个抽象类,有一点要切记抽象类是不能实例化的。 用abstract修饰方法就表示这是一个抽象的方法,抽象的方法不提供具体的实现。

关于abstract的语法规定如下

1、 抽象类有可以没有抽象方法,但是有抽象方法的类一定要定义为抽象类 2、 抽象类中的抽象方法在子类中实现。 3、 构造方法没有抽象方法。

什么样的类可以被声明为抽象类呢?比如小吃就可以看成一个抽象类,因为不管是那个地方的传统小吃都是小吃的一个子类,所以我们可以把小吃定义为一个抽象类。

现在用植物举一个例子,植物是一个抽象类,每一种具体的植物都是它的子类,植物有一个生长地带,但是不同的植物生长的地带是不同的,所以可以定义一个抽象类,抽象类中有一个抽象的获得生长地带的方法!程序如下 package blog;

public abstract class Plant {

public abstract void getGrowPlace();//定义一个抽象的方法,获取植物的生长地带 }

package blog;

public class Pine extends Plant {

public void getGrowPlace() {

System.out.println(\松树生长在北方!\ } }

package blog;

public class Bamboo extends Plant{

public void getGrowPlace() {

System.out.println(\竹子生长在南方!\ } }

package blog;

public class Test {

public static void main(String[] args) { Pine pine=new Pine(); Bamboo bamboo=new Bamboo(); pine.getGrowPlace(); bamboo.getGrowPlace(); } }

程序中定义了一个抽象类,由两个子类继承了这个抽象类,并且实现了抽象的方法!

Abstract修饰法的用法比较简单,还有一点需要注意的是,这个修饰符不能和final连用,原因是abstract中的方法由子类实现,而final修饰的方法必须在本类实现,所以连用这两个修饰法导致自相矛盾,编译无法通过

7、修饰符之final

Final修饰符用来修饰变量,表示它是一个常量,

Final用来修饰一个方法,表示这个方法是终极的只能被继承不能被子类覆盖了.

Final用来修饰一个类表示这个类没有子类,不能被继承 下边逐一说明它的用法

用final修饰变量最常见的就是在一些数学公式中,比如π我们就可以把它看成一个常量

程序如下 package blog;

public class Circle {

private final double PI=3.14;//声明一个常量PI private double radius;

public Circle(double radius) { this.radius = radius; }

public void area() {

System.out.println(\圆面积是:\ } }

package blog;

public class Test {

public static void main(String[] args) { Circle circle=new Circle(1.0); circle.area(); }

}

程序很简单,不多说了,功能就是计算圆面积!

Final用来修饰一个方法表示这个方法不希望被子类覆盖了,想想什么样的方法前面要加这个修饰符呢?还记得在覆盖中我举了一个public int withdraw(int i)银行取钱的例子吗?如果子类覆盖了父类的方法,那是很危险的,在这种情况下在父类中的public int withdraw(int i)方法要加final修饰符,这样子类就没法覆盖这个取钱的方法了

Final用来修饰一个类表示这个类出于安全原因不希望这个类被继承,以免其中的方法被子类覆盖就把这个类声明为final,在JDK中很多我们用到的常用类都是用final修饰的。

还有一点要强调的是final不能和abstract修饰符连用,理由已经说过了,这次加深一下印象,千万别忘记呀!

修饰符就聊到这里了,下次谈谈接口,这是JAVA中最有意思也是最有特色的一部分,一定要好好研究一下,你一定会受益匪浅的!

8、接口

经过前几次的铺垫现在终于进入了Java最有特色的一部分----接口。 什么是接口呢,就是用interface关键字定义的接口。它用于明确的描述对外界所提供的方法(服务)但是并不提供具体的实现,而是由实现它的类去定义 具体的实现。从接口的定义来看好像并不是很难理解,但是由接口派生而出的模式就有很多种了。可以说一句夸张一点的话,没有接口就没有今天的Java。 好了,现在把接口的语法规定详细的介绍一下:

接口中可以有成员变量和成员方法,成员变量的类型默认都是

public,static,final类型的,现在仔细想想由这三个关键字修饰的变量有什么特 点呢?首先它是对外公开的,然后呢它是属于整个类的并非属于某个具体实

例,最后它是一个常量,不能变的!具有这样特性的变量从感觉上看应该是对外公开的很 稳定常量,这是接口中成员变量的最大特点,这些特点都服从于接口的特点―稳定,不轻易改变!接口中可以定义方法,这些方法的类型都是

public,abstract的,也就是说它们都是对外公开的方法,但是却没有具体的实现。具体的实现由它的实现类去完成!

要想对接口有全面的理解,首先必须自上而下的理解,然后在自下而上的理解才能把它理解透彻。

现在举一个常用的例子从而自上而下的角度理解接口:

假设一家网络公司提供上网的套餐服务,那么首先要制定一个原则,上网套餐都包括什么?而具体的套餐实现不在该原则中体现,于是可以写一个接口 package blog;

public interface NetService {

public void adsl();//提供adsl上网服务 public void email();//提供电子邮件服务 }

接下来制定了两种套餐服务,A套餐B套餐,这是套餐服务的具体实现 package blog;

public class ServiceA implements NetService{

public void adsl() {

System.out.println(\提供1M带宽的上网服务\

}

public void email() {

System.out.println(\提供50M空间的电子邮件服务\ } }

package blog;

public class ServiceB implements NetService{

public void adsl() {

System.out.println(\提供2M带宽的上网服务\ }

public void email() {

System.out.println(\提供100M空间的电子邮件服务\ }

}

下面请看测试类 package blog;

public class Test {

public static void main(String[] args) { NetService netservice=new ServiceA(); netservice.adsl(); netservice.email(); netservice=new ServiceB(); netservice.adsl(); netservice.email(); } }

在测试函数中首先定制了A套餐,然后打印A套餐的内容,接下来定制了套餐B,然后打印套餐B的内容。这就是一个自上而下的接口的实现。不知你发现了没有接口也支持多态。这是他最大的好处,对实现类可以进行统一的编程,也称为针对接口编程!

下面我自下而上的讲一个例子,一些手机提供的照相的功能,另一些没有提供,所以我们不能统一的在手机类中添加照相的功能。于是有了接口帮我们方便的实现。我们写一个普通的手机类,如果它又有照相功能我们就让它实现一个照相的接口,于是手机就具有了照相的功能!请看

package blog;

public class MobilePhone { public void dial() {

System.out.println(\手机进行拨号,完成通话!\ } }

写一个具有照相功能的接口,提供了一个照相的空方法 package blog;

public interface Photo { public void photo(); }

然后我们让能能拍照的手机类实现这个接口,这部手机就可以照相了,如下所示 package blog;

public class MobilePhone implements Photo { public void dial() {

System.out.println(\手机进行拨号,完成通话!\ }

public void photo() {

System.out.println(\手机完成拍照功能\ } }

测试函数如下 package blog;

public class Test {

public static void main(String[] args) { MobilePhone mobilephone=new MobilePhone(); mobilephone.dial(); mobilephone.photo(); } }

通过测试我们可以看出普通的手机类通过实现了拍照功能的接口,就具有的拍照的功能,如果你还想让手机有上网的功能也可以自己写一个上网的接口,并且在手机类中实现这个接口,那么手机就会同时具备通话,拍照,上网三个功能了! 切记一个类可以同时实现多个接口,这样就弥补了一个类不能多继承的不足!看看接口是多么巧妙呀,它使我们的编程更面向对象化了,同时也更灵活了!比如

上面 手机的例子,如果希望手机具有拍照和上网的功能可以写一个接口叫PhoNet继承Photo接口,在其中添加一个上网的空方法,然后在手机类中实现这一个 接口解可以了,具体如下 package blog;

public interface PhoNet extends Photo{

public void net(); }

手机类实现该接口 package blog;

public class MobilePhone implements PhoNet { public void dial() {

System.out.println(\手机进行拨号,完成通话!\ }

public void photo() {

System.out.println(\手机完成拍照功能!\ }

public void net() {

System.out.println(\手机提供上网的功能!\ } } 测试类 package blog;

public class Test {

public static void main(String[] args) { MobilePhone mobilephone=new MobilePhone(); mobilephone.dial(); mobilephone.photo(); mobilephone.net(); } }

通过上面的例子我们可以看到接口既可以被实现也可以被另一个接口继承。这样是我们编程的伸缩性大大提高了!

听了这么多是不是有点晕晕的感觉,没关系只要再好好看几遍,心里理解,就会很快掌握的!

现在放松一下把接口的其他语法介绍一下 1、 接口不能被实例化 2、 接口没有构造方法

3、 如果一个类实现某接口则必须实现接口提供的全部方法,否则必须声明为抽象类

4、 由于类不支持多继承,所以Java提供了一个类可以实现多个接口的功能,弥补了先天不足。

5、 对于接口来讲,它可以每多有实现类,同时接口又可以继承多个接口,从而扩充该接口的方法数量

6、 在使用接口方面要有一个原则,就是接口中提供的方法必须是稳定的,如果经常在接口中添加方法,就要在它的实现类中实现这个添加的方法,假如一个接口被 1000个类实现,这是在接口中添加一个方法,就要同时修改1000的类,这是很大的工作量,因此在定义接口时一定要把握这一原则-稳定!

关于接口的基本知识就介绍的这里了,如果能很熟练的运用我在上面介绍的接口,在日常开发中就基本够用了。对于接口的认识是逐步加深的,在开发中细细体味,可能你会有更多惊喜的发现,这就是Java魅力所在!

9、Java集合之Set

关于集合可以谈的地方不多,关键是熟练。所以我在Set中给出了两种常见的排序方法,

一种是实现Comparable接口中的compareTo方法,现在给出实现程序 package blog;

public class Person implements Comparable{ private String name; private int age;

public Person(String name, int age) { this.name = name; this.age = age; }

public int getAge() { return age; }

public String getName() { return name; }

public int hashCode() {

return name.hashCode()*10+age; }

public boolean equals(Object obj) { if(this==obj)return true; else{

if(this.getClass()==obj.getClass()) {

Person temp=(Person)obj;

if(this.name.equals(temp.getName())&&this.age==temp.getAge())

return true; else return false;

}

else return false; } }

public String toString() {

return \姓名:\年龄:\ }

public int compareTo(Object o) { Person temp=(Person)o;

return this.getAge()-temp.getAge(); } }

package blog;

import java.util.Iterator; import java.util.Set; import java.util.TreeSet;

public class Test {

public static void main(String[] args) { TreeSet myset=new TreeSet(); Person person1=new Person(\ Person person2=new Person(\ Person person3=new Person(\ Person person4=new Person(\ Person person5=new Person(\

myset.add(person1); myset.add(person2); myset.add(person3); myset.add(person4); myset.add(person5); showme(myset);

}

public static void showme(Set set) { Iterator it=set.iterator(); while(it.hasNext()) {

Person temp=(Person)it.next(); System.out.println(temp); } } }

另一种方式是写一个比较器,在构造Set的时候持有该比较器的引用 package blog; import java.util.*;

public class MyComparator implements Comparator {

public int compare(Object o1, Object o2) { Person person1=(Person)o1; Person person2=(Person)o2;

return person1.getAge()-person2.getAge(); }

}

package blog;

public class Person { private String name; private int age;

public Person(String name, int age) { this.name = name; this.age = age; }

public int getAge() { return age; }

public String getName() { return name; }

public int hashCode() {

return name.hashCode()*10+age; }

public boolean equals(Object obj) { if(this==obj)return true; else{

if(this.getClass()==obj.getClass()) {

Person temp=(Person)obj;

if(this.name.equals(temp.getName())&&this.age==temp.getAge())

return true; else return false;

}

else return false; } }

public String toString() {

return \姓名:\年龄:\ }

}

package blog;

import java.util.Iterator; import java.util.Set; import java.util.TreeSet;

public class Test {

public static void main(String[] args) {

TreeSet myset=new TreeSet(new MyComparator()); Person person1=new Person(\ Person person2=new Person(\ Person person3=new Person(\ Person person4=new Person(\ Person person5=new Person(\

myset.add(person1); myset.add(person2); myset.add(person3); myset.add(person4); myset.add(person5);

本文来源:https://www.bwwdw.com/article/dwg3.html

Top