抽象类和接口的学习
来源:互联网 发布:二手正版pk10ub软件 编辑:程序博客网 时间:2024/05/24 06:33
抽象类和接口学习笔记
已经学习了如何编写简单的程序创建和现实GUI组件,你能编写代码以响应像点击一个按钮一样的用户动作吗?如下图所示,当点击一个按钮时,控制台上就会显示一条消息。
为了编写这样的代码,必修要很了解接口。借口就是定义多个类(特别是不相关的类)的共同行为。在学习接口之前,我来介绍一下相关主题:抽象类。
抽象类
和C++一样,抽象类就是包含抽象方法的类。为什么需要抽象方法呢,举一个例子来说。Circle和矩Rectangle都是Shape类的子类,Circle和Rectangle都有getArea()和getPerimeter()方法,但是所有的Shape都有这两种方法,所以最好的方式就是在Shape类中定义getArea()和getPerimeter()方法,但是这两个方法不能再Shape类中实现,因为它们的具体实现方式都取决于具体的形状,所以这样的方法成为抽象方法。在方法头中使用abstract修饰符即可,如:
public abstract class GeometricObject {public abstract double getArea();public abstract double getPerimeter();}
抽象类的构造方法一般被定义为protected,因为它只被子类使用。
关于抽象类的几个注意点:
1. 抽象方法不能包含在非抽象类中。如果抽象父类的子类不能实现所有的抽象方法,那子类也必须定义为抽象的。还要注意到,抽象方法是非静态的。
2. 抽象类是不能使用new操作符来初始化的,但是仍然可以定义它的构造方法,这个构造方法在它的子类的构造方法中调用。
3. 包含抽象对象的类必须是抽象的,但是也可以定义一个不包含抽象方法的抽象类。
4. 即使子类的父类的方法是具体的,子类也可以是抽象的。
5. 子类可以覆盖父类的方法并将它定义为abstract。
6. 不能使用new操作符从一个抽象类创建一个实例,但是抽象类可以作为一种数据类型
为什么要使用抽象类
举一个例子来说,人,兔子,老虎都属于动物,动物都有一系列的相同属性,比如都有眼睛鼻子耳朵嘴巴还有四肢,但是人,兔子,老虎吃的方式不一样,人要煮熟了吃,兔子慢慢啃,老虎用咬的。于是,我们定义一个动物类(定义为抽象类),人,兔子,老虎为其派生类,其他的属性因为都一样,我们只要为派生类”定制“它们的特征方法就行了,这样书写代码简单而又高效。
接口
接口是一种与类相似的结构, 只包含常量和抽象方法。接口在很多地方都与抽象类相似,但是它的目的是指明多个对象的共同行为。一个类要继承一个接口的时候需要用关键字implement。
Comparable接口
接口定义为:
public interface Comparable{ Public int compareTo(Object o);}
compareTo 方法判断这个对象对于给定对象o的顺序,并且当这个对象小于等于或大于给定对象o,分别返回负整数,0,或正整数。Java类库中的许多类如String和Date,都实现了Comparable接口以定义对象的自然顺序。
自定义继承Comparable 类 comparableRectangle
代码如下:
public class comparableRectangle extends Rectangle implements Comparable {public comparableRectangle(double width, double height) {super(width, height);}public int compareTo(Object o) {if (getArea() > ((comparableRectangle) o).getArea())return 1;else if (getArea() < ((comparableRectangle) o).getArea())return -1;elsereturn 0;}}
定义了comparableRectangle类之后就可以方便比较原来不方便比较的对象,从而可以实现方法Max以得到对象的最大值。
ActionListener接口
现在你已经准备好了编写一个小程序来解决文章开头的提出的问题。为了响应一个按钮的点击,需要编写代码来处理点击动作。按钮是动作的源对象。需要创建一个对象能够处理按钮上的动作事件。这个对象称为监听器(listener)。
不是所有的对象都能成为动作事件的监听器。一个对象要成为源对象上的动作事件的监听器,需要满足两个条件:
1. 这个对象必须是ActionListener(事件监听器)接口的一个实例。该接口定义了所有动作监听器的共有动作。
2. ActionListener对象listener必须使用方法source.addActionListener(listene)注册给源对象。
ActionListener接口包含处理事件的actionPerformed方法。监听器必须覆盖该方法来响应事件。下面的代码实现了点击OK,就会显示“OK button clicked”,点击Cancel显示“Cancel button clicked”。
HandleEvent 类
import javax.swing.*;import java.awt.*;import java.awt.event.*;public class HandleEvent extends JFrame{ public HandleEvent() { JButton jbtOK = new JButton("OK"); JButton jbtCancel = new JButton("Cancel"); JPanel p = new JPanel(); p.add(jbtOK); p.add(jbtCancel); add(p); OKListenerClass listener1 = new OKListenerClass(); CancelListenerClass listener2 = new CancelListenerClass(); jbtOK.addActionListener(listener1); jbtCancel.addActionListener(listener2); }}class OKListenerClass implements ActionListener{public void actionPerformed(ActionEvent e){JOptionPane.showMessageDialog(null, "OK!");}}class CancelListenerClass implements ActionListener{public void actionPerformed(ActionEvent e){JOptionPane.showMessageDialog(null, "Cancel!");}}
Main函数
import java.util.*;import javax.swing.*;import java.io.*;public class Main {public static void main(String[] args) {JFrame frame = new HandleEvent();frame.setTitle("Handle Event");frame.setSize(200,150);frame.setLocation(200, 100);frame.setDefaultCloseOperation(HandleEvent.EXIT_ON_CLOSE);frame.setVisible(true);}}
Cloneable接口
接口包括常量和抽象方法,但是Cloneable接口是一个特殊情况,它的定义如下:
package java.lang;public interface Cloneable{}
这个接口是空的,它用来标记某些特定的属性,接下来看下面一段代码:
public class Main {public static void main(String[] args) {Calendar date = new GregorianCalendar(2003,2,1);Calendar date1 = date;Calendar date2 = (Calendar)date.clone();System.out.println("date == date1 is "+(date==date1)); //trueSystem.out.println("date == date2 is "+(date==date2)); //falseSystem.out.println("date.equals(date2) is "+date.equals(date2)); //true}}
代码中,将date的引用复制给date1,所以date和date1都指向相同的date对象,接下来创建了一个新对象,它是date的克隆,然后将这个新对象的引用赋值给date2.date2和date是内容相同的不同对象。这个克隆的意义和人类社会的克隆意义相同。
当然,也可以用clone方法克隆一个数组。
接口与抽象类
用Comparable接口实现对一个对象数组的排序
import java.util.*;import javax.swing.*;import java.io.*;public class Main {public static void sort(Comparable[] list){Comparable currentMin;int currentMinIndex;for(int i=0;i<list.length;++i){currentMin = list[i];currentMinIndex = i;for(int j = i+1;j<list.length-1;++i){if(currentMin.compareTo(list[j])>0){currentMin = list[j];currentMinIndex = j;}}if(currentMinIndex != i){list[currentMinIndex] = list[i];list[i]=currentMin;}}}public static void printList(Object[] list){for(int i=0;i<list.length;++i){System.out.print(list[i]+" ");}System.out.println();}public static void main(String[] args) {Integer[] intArray = {new Integer(2),new Integer(4),new Integer(3)};Double[] doubleArray={new Double(3.4),new Double(1.3),new Double(-22.1)};Character[] charArray={new Character('a'),new Character('J'),new Character('r')};String[] stringArray = {"Tom","John","Fred"};sort(intArray);sort(doubleArray);sort(charArray);sort(stringArray);printList(intArray);printList(doubleArray);printList(charArray);printList(stringArray);}}
Biginteger和BigDecimal类
有时候会碰到计算特别大的数,比如111111111111111111111111*12233333333333,这样的计算需要显然不能用之前的方式来进行。我们不能用任何的数据类型来装下这么大的数,它已经操作了int、float、double的数据类型的范围。那么如何解决这样的计算需求呢?这时候,就需要进行大数操作。
在java.math这个包中有两个进行大数操作的类:java.math.BigInteger和java.math.BigDecimal。从名字上可以知道这两个类的作用了吧。很明显,前者是进行整数的大数操作的,后者是进行小数的大数操作的。下面来看一下实例。
实例1:
import java.math.BigInteger;public classBigIntegerDemo01 { public static voidmain(String[] args){ String num1="88379348888888478403839479"; String num2="838777777333333333337"; BigInteger big1=newBigInteger(num1); BigInteger big2=newBigInteger(num2); System.out.println(big1.add(big2));//加法操作 System.out.println(big1.subtract(big2));//加法操作 System.out.println(big1.multiply(big2));//乘法操作 System.out.println(big1.divide(big2));//除法操作 BigInteger[] result=big1.divideAndRemainder(big2); System.out.println(big1.toString()+"/"+big2.toString()+"的商:"+result[0]); System.out.println(big1.toString()+"/"+big2.toString()+"的余数:"+result[1]); }}
构造方法publicBigInteger(String val)是 将 BigInteger 的十进制字符串表示形式转换为BigInteger。大整数操作可以像其它类型的数据一样进行加法、减法、乘法、除法等操作。需要特别说明的是除法操作。publicBigInteger divide(BigInteger val)这个方法只能得到一个“商“,要想的到余数需要用public BigInteger[] divideAndRemainder(BigInteger val)这个方法。divideAndRemainder()这个方法返回的是存储有”商“和”余数“的BigInteger数组。下面看看BigDecimal如何使用。
实例2:
package cn.tty.math;import java.math.BigDecimal;public classBigDecimalDemo02 { public static voidmain(String[] args) { String num1="84995.333333333323"; String num2="894.99"; //保留5位小数 System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.add(num1, num2), 5)); //保留4位小数 System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.subtract(num1, num2), 4)); //保留3位小数 System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.multiply(num1, num2), 3)); //保留2位小数 System.out.println(BigDecimalDemo02.divide(num1, num2,2)); } public static doubleadd(String num1,String num2){ //将 BigDecimal 的字符串表示形式转换为BigDecimal BigDecimal b1=newBigDecimal(num1); BigDecimal b2=newBigDecimal(num2); returnb1.add(b2).doubleValue(); } public static doublesubtract(String num1,String num2){ //将 BigDecimal 的字符串表示形式转换为BigDecimal BigDecimal b1=newBigDecimal(num1); BigDecimal b2=newBigDecimal(num2); returnb1.subtract(b2).doubleValue(); } public static doublemultiply(String num1,String num2){ //将 BigDecimal 的字符串表示形式转换为BigDecimal BigDecimal b1=newBigDecimal(num1); BigDecimal b2=newBigDecimal(num2); returnb1.multiply(b2).doubleValue(); } public static doubledivide(String num1,String num2,int scale){ BigDecimal b1=newBigDecimal(num1); BigDecimal b2=newBigDecimal(num2); //下面的“2”表示需要保留的小数位数,“BigDecimal.ROUND_HALF_UP”常量表示的是四舍五入的模式 returnb1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } public static double round(doublenum1,int scale){ BigDecimal big1=newBigDecimal(num1); BigDecimal big2=newBigDecimal(1); returnbig1.divide(big2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();//任何数除于1都等于本身 }}
上面的例子重新包装了BigDecimal的加减乘除操作,是这些方法的使用更符合本例的需要。加减乘的操作就不用多说了,很直接,很简单,需要说明的还是除法操作。
BigDecimal的除法重载了很多。其中有一种是publicBigDecimal divide(BigDecimal divisor,int scale,RoundingMode roundingMode)。这种方法指定了保留的小数位数(scale)和四舍五入的模式(roundingMode)。比如,“ROUND_HALF_DOWN“的模式表示向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
//下面的操作不涉及大数操作的内容,但涉及到保留小数位数 double x=874.748; double y=893.32; double z=x*y; System.out.println("x * Y = "+z); System.out.println("x * Y = "+(int)(z*10)/10.0);//保留1为小数 System.out.println("x * Y = "+(int)(z*100)/100.0);//保留2为小数 System.out.println("x * Y = "+(int)(z*1000)/1000.0);//保留3为小数
这种方式并不能完全指定四舍五入的小数位数,可以称之为“伪四舍五入“,因为这某种巧合的情况下,它并不能很好的实现指定小数位数的功能。比如x=874.738,y=893.32那么 z= 781420.9501600001。(int)(z*1000)/1000.0的输出结果仍为”781420.95“,并没有预想的保留3位小数。原因很简单,z*1000=781420950. 1600001,(int)(z*1000)=781420950,那么(int)(z*1000)/1000.0=781420.95。因为末位是0,因此被舍掉了。
虽然这种方式的保留小数位数的方式不保险,但这种方式简单便捷,在要求并不严苛的情况下可以使用。
还有个四舍五入的方法,在java.lang.Math类中:
public staticlong round(double a)
publicstatic int round(float a)
显然,这两个方法返回的数将是整型数据,并不会保留任何小数。
package cn.tty.format;import java.text.DecimalFormat;public classDecimalFormatDemo02 { public static String round(String pattern,double value){ DecimalFormat formatter=new DecimalFormat(pattern); String rv=formatter.format(value); return rv; } public static void main(String[] args){ //指定模式:保留2为小数 String roundedValue=DecimalFormatDemo02.round("####.00",838.666);//保留两位小数 System.out.println(roundedValue); }}
本章小结
1.接口是一种与类很类似的结构,只是包含常量和抽象方法。接口在许多方面与抽象类很接近,但是抽象类除了包含常量和抽象方法之外,还可以包含变量和具体方法。
2.在Java中接口被认为是一种特殊的类。(用implement实现)就像常规类一样,每一个接口都被编译为独立的字节码文件。
3.接口Cloneable是一个标记接口(空接口)。实现Cloneable接口的对象是可克隆的。
4.一个类仅能继承一个父类,但是一个类可以实现一个或多个接口。
5.一个类如果实现了一个借口,则要实现该接口的所有方法。
6.一个接口可以扩展为多个接口。(interface a extends b,c,d)
7.许多Java方法要求使用对象作为参数,Java提供了一个便捷的办法,将基本数据类型合并或包装到一个对象中(如,包装int值到Integer类中,包装double到Double类中)。对应的类称作包装类。使用包装对象而不是基本数据类型的变量,将有助于通用程序设计
8.Java可以根据上下文自动将基本类型值转换为包装对象,反之亦然
9.BigInteger类在计算和处理任意大小的正整数方面是很有用的。BigDecimal类可以用于计算和处理待人以精度的浮点数。
10.因为接口的方法默认是public类型的,所以在实现的时候一定要用public来修饰(否则默认为protected类型,缩小了方法的使用范围)。- Java抽象类和接口的学习
- 抽象类和接口的学习
- 学习Java的接口和抽象类
- Java抽象类和接口的学习
- 抽象类和接口的学习
- 学习接口和抽象类
- 抽象类和接口的相同点和不同点,学习笔记
- java普通类、抽象类和接口的再学习
- C# 中抽象类和接口的学习
- interface学习以及 抽象类和接口的异同点
- 抽象类和接口的区别——学习笔记
- 关于抽象类和接口的学习总结一
- 抽象类和接口的学习比较心得
- 深入学习Java的接口和抽象类
- 【面向对象】抽象类和接口的对比学习
- 【学习笔记】Java抽象类和接口的一些总结
- java抽象类和接口的多种实现---学习日志
- 对接口和抽象类的学习总结
- Java反射笔记
- Android:一个可以随意涂鸦的画板应用
- 取下一个物料号码
- awk使用相关网址
- AFNetworking 3.0携带参数上传文件Demo
- 抽象类和接口的学习
- kafka consumer demo 消费者
- Lua 初识之 loadfile、require、module - 十五
- php 生成唯一id的几种解决方法
- ehcache memcache redis 三大缓存区别
- Oracle 10.2.0.5又出现了undo 表空间使用率不断增长
- Redis入门很简单之一【简介与环境搭建】
- 安卓一键修改IMEI号码、修改串号工具,撸客一族的必备
- Java中带包的类的编译与执行