Java面向对象程序设计--接口和内部类
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java面向对象程序设计--接口和内部类,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含14611字,纯文字阅读大概需要21分钟。
内容图文
![Java面向对象程序设计--接口和内部类](/upload/InfoBanner/zyjiaocheng/740/9aab2e1b8bc04cba8d5a0d089029dae8.jpg)
1.接口的定义:
In the Java programming language, an interface is not a class but a set of requirements for classes that want to conform the interface.
说明: 1) Interface 不是class,虽然interface具有class的一些特点,例如能够继承,能够定义相同类型的变量,而且和C++的abstract class非常像,但Java
的interface和class在本质上已经有所区别!
2) Interface 是一组要求。类的接口是类的调用者和被调用者之间的一个契约,这个契约定义了interface实现者所要提供的功能和功能提供的方式,也定义了
interface调用者获取 interface实现者服务的方式。
为了让某个class实现一个接口,只需要以下两个步骤:
1) 声明你所定义的类将实现某个接口;
2) 在你的类中实现接口中所有的方法;
下面的Employee类实现了compareTo接口,那么就可以使用Array的sort方法来对Emplyee对象形成的数组进行排序;
?1?import?java.util.Arrays;
?2?
?3?
?4?public?class?EmployeeSortTest?
?5?{
?6?????public?static?void?main(String[]?args)?
?7?????{
?8?????????Employee[]?staff?=?new?Employee[3];
?9?????????
10?????????staff[0]?=?new?Employee("Harry?Hacker",35000);
11?????????staff[1]?=?new?Employee("Carl?Cracker",75000);
12?????????staff[2]?=?new?Employee("Tony?Tester",38000);
13?????????
14?????????Arrays.sort(staff);
15?????????
16?????????for(Employee?e?:?staff)
17?????????????System.out.println("name?=?"?+?e.getName()?+?",salary="?+?e.getSalary());
18?????}
19?}
20?
21?class?Employee?implements?Comparable<Employee>
22?{
23?????public?Employee(String?n,double?s)
24?????{
25?????????name?=?n;
26?????????salary?=?s;
27?????}
28?????
29?????public?String?getName()
30?????{
31?????????return?name;
32?????}
33?????
34?????public?double?getSalary()
35?????{
36?????????return?salary;
37?????}
38?????
39?????public?void?raiseSalary(double?byPercent)
40?????{
41?????????double?raise?=?salary?*?byPercent?/?100;
42?????????salary?+=?raise;
43?????}
44?????
45?????/**
46??????*?Compares?employees?by?salary
47??????*/
48?????public?int?compareTo(Employee?other)
49?????{
50?????????if(salary?<?other.salary)?return?-1;
51?????????if(salary?>?other.salary)?return?1;
52?????????return?0;
53?????}
54?????
55?????private?String?name;
56?????private?double?salary;
57?}
接口的一些特性:
1.接口不是类,你无法new出一个接口实例:
2.虽然无法构建出接口实例,但是可以定义接口变量; 并且接口变量只能指向一个实现该接口的类的对象;
Comparable x;
x = new Employee(...);
3.就像使用instanceof判断一个对象是不是一个类的实例一样,你也可以使用instanceof判断一个类的对象是否实现了某个接口。
if(anObject instanceof Comparable) {}
4.就像类的使用一样,接口也可以用来被继承;
5.Java中的类只能继承一个父类,但却可以实现多个接口!这个特性为定义一个类的行为提供的很大的方便。
接口和抽象类:
为什么不使用抽象类来代替接口的概念呢?--Java中不存在多重继承!Java中用接口来实现了C++中复杂的多继承功能!
2. 对象克隆(Object Cloning):
对任何一个对象你需要认清下面几点:
a). 默认的clone函数是否已经足够优秀!
b). Clone一个基类对象时要Clone其成员的每个mutable部分;
c). Clone是否根本无法实现;
对象型变量实际存储的是对象实例的地址,而不是对象实例本身,这是Java设计的一个遗憾!
1 import java.util.*;
?2??3?public?class?CloneTest?
?4?{
?5?????public?static?void?main(String[]?args)?
?6?????{
?7?????????try
?8?????????{
?9?????????????MyEmployee?original?=?new?MyEmployee("John?Q.?Public",50000);
10?????????????original.setHireDay(2000,?1,?1);
11?????????????MyEmployee?copy?=?original.clone();
12?????????????copy.raiseSalary(10);
13?????????????copy.setHireDay(2002,?12,?31);
14?????????????System.out.println("original="+original);
15?????????????System.out.println("Copy="+copy);
16?????????}
17?????????catch(CloneNotSupportedException?e)
18?????????{
19?????????????e.printStackTrace();
20?????????}
21?????}
22?}
23?
24?class?MyEmployee?implements?Cloneable
25?{
26?????public?MyEmployee(String?n,double?s)
27?????{
28?????????name?=?n;
29?????????salary?=?s;
30?????????hireDay?=?new?Date();
31?????}
32?????
33?????public?MyEmployee?clone()?throws?CloneNotSupportedException
34?????{
35?????????MyEmployee?cloned?=?(MyEmployee)super.clone();
36?????????
37?????????cloned.hireDay?=?(Date)hireDay.clone();
38?????????
39?????????return?cloned;
40?????}
41?????
42?????public?void?setHireDay(int?year,int?month,int?day)
43?????{
44?????????Date?newHireDay?=?new?GregorianCalendar(year,month-1,day).getTime();
45?????????hireDay.setTime(newHireDay.getTime());
46?????}
47?????
48?????public?void?raiseSalary(double?byPercent)
49?????{
50?????????double?raise?=?salary?*?byPercent?/?100;
51?????????salary?+=?raise;
52?????}
53?????
54?????public?String?toString()
55?????{
56?????????return?"MyEmployee[name="+name+",salary="+salary+"hireDay="+hireDay+"]";
57?????}
58?????
59?????private?String?name;
60?????private?double?salary;
61?????private?Date?hireDay;
62?}
结果如下:
original=MyEmployee[name=John Q. Public,salary=50000.0hireDay=Sat Jan 01 00:00:00 CST 2000]
Copy=MyEmployee[name=John?Q.?Public,salary=55000.0hireDay=Tue?Dec?31?00:00:00?CST?2002]
3.接口和回调:
一个在编程中常用的模型称为callback(模型),当一个事件发生时要制定处理动作。比如当按钮被按下后执行的特定动作,或者选择了一个
菜单选项之后执行的特定动作!
Java语言利用传递对象来实现这一点,但C++使用传递函数指针来实现这一点的!
1 /**
?2????@version?1.00?2000-04-13?3????@author?Cay?Horstmann
?4?*/
?5?
?6?import?java.awt.*;
?7?import?java.awt.event.*;
?8?import?java.util.*;
?9?import?javax.swing.*;
10?import?javax.swing.Timer;?
11?//?to?resolve?conflict?with?java.util.Timer
12?
13?public?class?TimerTest
14?{??
15????public?static?void?main(String[]?args)
16????{??
17???????ActionListener?listener?=?new?TimePrinter();
18?
19???????//?construct?a?timer?that?calls?the?listener
20???????//?once?every?10?seconds
21???????Timer?t?=?new?Timer(10000,?listener);
22???????t.start();
23?
24???????JOptionPane.showMessageDialog(null,?"Quit?program?");
25???????System.exit(0);
26????}
27?}
28?
29?class?TimePrinter?implements?ActionListener
30?{??
31????public?void?actionPerformed(ActionEvent?event)
32????{??
33???????Date?now?=?new?Date();
34???????System.out.println("At?the?tone,?the?time?is?"?+?now);
35???????Toolkit.getDefaultToolkit().beep();
36????}
37?}
4. 内部类:
内部类是一个定义在其他类中的类,为何要使用内部类呢?下面是常见的3种理由:
- 内部类中的方法可以访问内部类定义处的数据,即使这些数据是private类型的;
- 内部类对同一个包中的其他类是隐藏的,即包中的其他类是看不到这个内部类的;
- 匿名内部类在定义回调函数时非常有用;
4.1 使用内部类来访问对象的状态:
?1?import?java.awt.*;
?2?import?java.awt.event.*;
?3?import?java.util.*;
?4?import?javax.swing.*;
?5?import?javax.swing.Timer;
?6?
?7?public?class?InnerClassTest
?8?{
?9?????public?static?void?main(String[]?args)
10?????{
11??????????????TalkingClock?clock?=?new?TalkingClock(1000,true);
12??????????????clock.start();
13?
14??????????//keep?program?running?until?user?selects?"OK"
15??????????JOptionPane.showMessageDialog(null,"Quit?program?");
16??????????System.exit(0);
17?????}
18?}
19?
20?/**
21??*?A?clock?that?prints?the?time?in?regular?interval
22??*/
23?class?TalkingClock
24?{
25?????/**
26??????*?Constucts?a?taking?clock
27??????*?@param?interval?the?interval?between?message(in?milliseconds)
28??????*?@param?beep?true?if?the?clock?should?beep
29??????*/
30?????public?TalkingClock(int?interval,boolean?beep)
31?????{
32?????????this.interval?=?interval;
33?????????this.beep?=?beep;
34?????}
35?
36?????/**
37??????*?Starts?the?clock
38??????*/
39?????public?void?start()
40?????{
41?????????ActionListener?listener?=?new?TimePrinter();
42?????????Timer?t?=?new?Timer(interval,listener);
43?????????t.start();
44?????}
45?
46?????private?int?interval;
47?????private?boolean?beep;
48?
49 public class TimePrinter implements ActionListener
50 {
51 public void actionPerformed(ActionEvent e)
52 {
53 Date now = new Date();
54 System.out.println("At the tone, the time is "+now);
55 if(beep)
56 System.out.println("Beep!");
57 }
58 }
59?}
上述红色代码部分定义了一个内部监听器类,用来监听事件的发生并采取相应的动作:
if(beep)
System.out.println("Beep!");
表明这个内部类可以直接访问其外部类的private字段!相当于内部类中存在一个对外部类的隐含引用!
这个代码可以改成:
if(TalkingClock.this.beep)?System.out.println("Beep!");
4.2 内部类的实用性,内部类真的又存在的必要吗? 内部类的安全性如何呢?
Java 引入内部类机制更多的是为了显得优雅有趣,而非实用性!
内部类最好是只和其所在的外部类进行交互: 一方面让内部类只访问其所在的外部类的数据,另一方面,也让内部类只在其所处的外部类的方法中使用。
让内部类只作为其所处的外部类的处理逻辑的一部分。实际开发中尽量少用或不用内部类。
4.3 本地内部类: 将内部类定义在外部类的某个成员函数中,这样,只有这个外部类的成员函数才会去使用这个内部类的对象。
?1?public?void?start()
?2?{
?3? ? ?class?TimePrinter?implements?ActionListener
?5?????{
?6?????????public?void?actionPerformed(ActionEvent?e)
?7?????????{
?8?????????????Date?now?=?new?Date();
?9?????????????System.out.println("At?the?tone,?the?time?is?"+now);
10?????????????if(TalkingClock.this.beep)?
11?????????????????System.out.println("Beep!");
12?????????}
13?????}
15? ? ?ActionListener?listener?=?new?TimePrinter();
16? ? ?Timer?t?=?new?Timer(interval,listener);
17? ? ?t.start();
18?}
注意,本地内部类并没有定义一个访问控制符:(public or private),因为本地内部类的有效作用区域只在定义本地内部类的代码块之中。
4.4 匿名内部类:
?1?public?void?start(int?iterval,final?boolean?beep)
?2?????{
?3?????????ActionListener?listener?=?new?Actionlistener()
?4? ? ? ? ?{
?5?????
?6? ? ? ? ? ? ? ?public?void?actionPerformed(ActionEvent?e)
?7? ? ? ? ? ? ? ?{
?8? ? ? ? ? ? ? ? ? ?Date?now?=?new?Date();
?9? ? ? ? ? ? ? ? ? ?System.out.println("At?the?tone,?the?time?is?"+now);
10? ? ? ? ? ? ? ? ? ?if(TalkingClock.this.beep)?
11? ? ? ? ? ? ? ? ? ? ? ? System.out.println("Beep!");
12? ? ? ? ? ? ? ?}
13? ? ? ? ? }
14?????????Timer?t?=?new?Timer(interval,listener);
15?????????t.start();
16?????}
只使用上述内部类的一个对象!
上述这段代码的意思是:
1.定义了一个匿名的类,这个匿名的类实现了Actionlistener接口
2.创建了一个匿名类的实例,在本程序中将其赋给变量listener;
匿名内部类的对象的创建规则是:
new SuperType(construction parameters)
{
inner class method and data;
}
在这里,这个SuperType可以是一个接口,比如上面程序中的Actionlistener,或者是一个基类,这样这个内部类就继承了这个基类;
由于匿名内部类是没有名称的,不然也就不叫"匿名"了,所以匿名内部类是没有构造函数的,
a) 当SuperType是一个类的时候,将construction parameters传递给SuperType类的构造函数。
b) 当SuperType是一个接口的时候,new InterfaceType() {methods and data}
4.5 静态内部类(static):
有些时候,你只是希望在一个类中使用内部类,但并不希望用内部类来访问外部类中的对象。你可以将内部类声明为
static来限制这种内部类对外部类的访问。
引入static 内部类的一个重要原因:
static 方法执行时不会有类的实例与之对应,所以,当一个内部类需要在其所在的外部类的static方法中使用时,内部
类就不能获得其所在外部类实例的引用。下面是一个静态内部类的使用实例:
?1?/**
?2????@version?1.00?1998-04-07
?3????@author?Cay?Horstmann
?4?*/
?5?
?6?public?class?StaticInnerClassTest
?7?{??
?8????public?static?void?main(String[]?args)
?9????{??
10???????double[]?d?=?new?double[20];
11???????for?(int?i?=?0;?i?<?d.length;?i++)
12??????????d[i]?=?100?*?Math.random();
13???????ArrayAlg.Pair?p?=?ArrayAlg.minmax(d);
14???????System.out.println("min?=?"?+?p.getFirst());
15???????System.out.println("max?=?"?+?p.getSecond());
16????}
17?}
18?
19?class?ArrayAlg
20?{??
21????/**
22???????A?pair?of?floating?point?numbers
23????*/
24????public?static?class?Pair
25????{?
26???????/**?
27???????????Constructs?a?pair?from?two?floating?point?numbers
28???????????@param?f?the?first?number
29???????????@param?s?the?second?number
30???????*/
31???????public?Pair(double?f,?double?s)
32???????{??
33??????????first?=?f;
34??????????second?=?s;
35???????}
36?
37???????/**
38??????????Returns?the?first?number?of?the?pair
39??????????@return?the?first?number
40???????*/
41???????public?double?getFirst()
42???????{??
43??????????return?first;
44???????}
45?
46???????/**
47??????????Returns?the?second?number?of?the?pair
48??????????@return?the?second?number
49???????*/
50???????public?double?getSecond()
51???????{??
52??????????return?second;
53???????}
54?
55???????private?double?first;
56???????private?double?second;
57????}
58?
59????/**
60???????Computes?both?the?minimum?and?the?maximum?of?an?array?
61???????@param?a?an?array?of?floating?point?numbers
62???????@return?a?pair?whose?first?element?is?the?minimum?and?whose
63???????second?element?is?the?maximum
64????*/
65????public?static?Pair?minmax(double[]?d)
66????{??
67???????if?(d.length?==?0)?return?new?Pair(0,?0);
68???????double?min?=?d[0];
69???????double?max?=?d[0];
70???????for?(int?i?=?1;?i?<?d.length;?i++)
71???????{??
72??????????if?(min?>?d[i])?min?=?d[i];
73??????????if?(max?<?d[i])?max?=?d[i];
74???????}
75???????return?new?Pair(min,?max);
76????}
77?}
4.6 代理(Proxies):
1 import java.lang.reflect.*;
?2?import?java.util.*;?3?
?4?/**
?5??*?An?invocation?handler?that?prints?out?the?method?name?and?parameters,?then
?6??*?invokes?the?original?method
?7??*/
?8?class?TraceHandler?implements?InvocationHandler
?9?{
10?????/**
11??????*?Constructs?a?TraceHandler
12??????*?@param?t?the?implicit?parameter?of?the?method?call
13??????*/
14?????public?TraceHandler(Object?t)
15?????{
16?????????target?=?t;
17?????}
18?
19?????public?Object?invoke(Object?proxy,Method?m,Object[]?args)?throws?Throwable
20?????{
21?????????//print?implicit?argument
22?????????System.out.print(target);
23?
24?????????//print?method?name
25?????????System.out.print("."+m.getName()+"(");
26?
27?????????//print?explicit?arguments
28?????????if(args?!=?null)
29?????????{
30?????????????for(int?i?=?0;?i?<?args.length;?i++)
31?????????????{
32?????????????????System.out.print(args[i]);
33?????????????????if(i?<?args.length?-?1)?System.out.print(",?");
34?????????????}
35?????????}
36?
37?????????System.out.println(")");
38?
39?????????//invoke?actual?method
40?????????return?m.invoke(target,args);
41?????}
42?
43?????private?Object?target;
44?}
45?
46?public?class?ProxyTest
47?{
48?????public?static?void?main(String[]?args)
49?????{
50?????????Object[]?elements?=?new?Object[1000];
51?
52?????????//fill?elements?with?proxies?for?the?integers?1...1000
53?????????for(int?i?=?0;?i?<?elements.length;?i++)
54?????????{
55?????????????Integer?value?=?i+1;
56?????????????InvocationHandler?handler?=?new?TraceHandler(value);
57?????????????Object?proxy?=?Proxy.newProxyInstance(null,new?Class[]?{Comparable.class},handler);
58?????????????elements[i]?=?proxy;
59?????????}
60?
61?????????//?construct?a?random?integer
62?????????Integer?key?=?new?Random().nextInt(elements.length)?+?1;
63?
64?????????//?search?for?the?key
65?????????int?result?=?Arrays.binarySearch(elements,key);
66?
67?????????//print?match?if?found
68?????????if(result?>=?0)?System.out.println(elements[result]);
69?????}
70?}
代理机制属于模式设计范畴,在以后的博客中会专门开辟一篇探究Java的代理机制。
转载于:https://www.cnblogs.com/jiangheng/p/3750979.html
内容总结
以上是互联网集市为您收集整理的Java面向对象程序设计--接口和内部类全部内容,希望文章能够帮你解决Java面向对象程序设计--接口和内部类所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。