Java之美[从菜鸟到高手演变]之类与对象(三)

原创 2012年12月20日 20:18:21

类与对象之类的复用(继承、组合、代理)

作者:egg

微博:http://weibo.com/xtfggef

出处:http://blog.csdn.net/zhangerqing

此章我们主要谈下面向对象编程的代码复用机制。

继承

继承是OOP中最为重要的概念,达到了非常有效的代码重用效果,使得开发效率变得很高!同时也因此,造成了OOP语言执行效率低下,不免被C/C++程序员嘲笑。在Java语言中,两个类之间通过extends关键字实现继承。我们来看个继承的实例:

class A {
	public A() {
		System.out.println("A()!");
	}
}

class B extends A {
	public B() {
		System.out.println("B()!");
	}
}

public class ExtendsTest extends B {

	public ExtendsTest() {
		System.out.println("ExtendsTest()!");
	}

	public static void main(String[] args) {
		new ExtendsTest();
	}

}

ExtendsTest继承自B,B继承自A,当实例化ExtendsTest的时候,却依次打印出了A、B、ExtendsTest构造器中的内容,说明:构造器被依次调用了,这是为什么?因为当类实现继承时,默认的会将基类的一个子对象传给子类,而子类需要对这个子对象进行初始化,所以需要调用父类的构造器,但是,这一切都是隐式进行的,我们看不到,不过可以从实验中得出结论:在对子类进行初始化的时候,会先调用父类的构造器(如果有学过C++的同学,肯定知道,在C++中除了有构造函数,还有析构函数,初始化的时候先调用父类的构造函数,析构的时候,先析构子类对象,再析构父类对象,一个从外到里,再由里到外的过程)。如果父类构造器需要传递参数,则使用super关键字来实现就行了。

class B extends A {
	public B(int n) {
		System.out.println("B()!");
	}
}

public class ExtendsTest extends B {

	public ExtendsTest(int n) {
		super(n);
		System.out.println("ExtendsTest()!");
	}

	public static void main(String[] args) {
		new ExtendsTest(1);
	}

}

下面我们分几种情况讨论下继承:

1、子类不能继承父类私有的域或者方法。如果想要继承父类的私有对象,只能将private改成protected,因为protected的权限控制在包内。因此一般情况,用到继承的话,最好将父类中的域声明为私有(private,因为一般情况不需要继承成员变量),将方法声明为public,方便继承。

2、当子类对象调用一个方法时,如果子类没有,则去调用父类的同名方法,但是调用者保持是子类。

public class A {
	int a = 10;
	void a(){
		System.out.println(a);
		System.out.println(getClass().getName());
	}
}

class B extends A {
	int a = 20;
//	void a(){
//		System.out.println(a);
//		System.out.println(getClass().getName());
//		System.out.println(this.a);
//		System.out.println(super.a);
//	}

	public static void main(String[] args) {
		B b = new B();
		b.a();
	}
}

输出:

10

B

a()B中被注释掉了,则调用的是父类A中的,所以输出的值是A中的成员变量。但是调用getClass()获取的仍然是B。当我们将上述代码中的注释去掉,则输出:

20

B

20

10

B中有a()方法时,屏蔽了A中的a()super关键字调用的是父类的信息,this关键字调用的是当前类的信息。

代理

代理的思想在我们讲得设计模式里面有体现,就是在一个类中持有另一个类的实例,从而代替原类进行一个操作,我们看个例子:

public class ProxyTest {
	Source source = new Source();
	void p(int n){
		source.a(n);
	}
	void p2(int n){
		source.b(n);
	}
	public static void main(String[] args) {
		ProxyTest pt = new ProxyTest();
		pt.p(20);
		pt.p2(50);
	}
}

class Source{
	void a(int n){
		System.out.println("this is : "+n);
	}
	void b(int n){
		System.out.println("this is : "+n);
	}
}

组合

如果大家还记得设计模式里的建造者模式,那么很容易联想到组合机制,就是将一系列的对象组合在一起,组合成一个功能丰富的类,当然,这些对象包括基本数据类型,也包括引用。来看个例子:

class Soap{
	private String s;
	Soap(){
		System.out.println("soap");
		s = "constructor";
	}
	public String toString(){
		return s;
	}
}

public class CompronentTest {
	private String s1 = "happy",s2="Happy",s3,s4;
	private Soap castille;
	private int i;
	public CompronentTest(){
		s3 = "joy";
		castille = new Soap();
	}
	{
		i = 88;
	}
	public String toString(){
		if(s4 == null){
			s4 = "Joy";
		}
			return "s1 = " + s1 + "\n" +
				   "s2 = " + s2 + "\n" +
				   "s3 = " + s3 + "\n" +
				   "s4 = " + s4 + "\n" +
				   "i = " + i + "\n" +
				   "castille = " + castille;

	}
	public static void main(String[] args) {
		CompronentTest ct = new CompronentTest();
		System.out.println(ct);
	}
}

该类就是一个普通的组合类,在组合类中我们应该注意这个对象的初始化方式,此处:1s1s2采用在声明的地方直接赋值,这样能够保证它们在构造器被调用之前被初始化(详细可见类与对象一中关于类的初始化顺序的介绍)。2s3在构造器中初始化。3s4采用的是懒加载(下面会讲)。4i在非静态初始化块中。此处我们说下toString方法,就是一个将其它对象转为String对象的方法,除了非基本类型的对象,其它都有一个toString方法,这是因为toString方法是Object类的固有方法,在Java中任何类都隐式继承Object类,也就说都隐含toString方法。所以,在上述的例子中,当最后的字符串+ castille对象时,需要将castille对象以字符串的形式表现出来,因此调用了toString()

懒加载因为涉及持有对象实例,所以会涉及到懒加载的机制,代码中的:

if(s4 == null){

         s4 = "Joy";

}

就是一种懒加载的机制,这种机制就是解决当所需的对象比较庞大的时候,只有在用的时候才去初始化,节省空间,提高效率!

总结下:

1、初始化方面,注意一些特殊对象的初始化,可以在定义的时候直接初始化,或者在构造方法中或在方法块中,或者在用的时候懒加载。

2toString方法,解决和字符串对象衔接出现的类型不匹配问题。

3、懒加载,提高效率,对于大的对象,延迟加载!

补充:

Java对中文类名、方法名的支持。

public class Test {

	public static void main(String[] args) {
		
		学生 我 = new 学生();
		我.说();
	
	}
}

class 学生{
	public void 说(){
		System.out.println("hello everyone!");
	}
}

 补充一点儿东西,Java中的运算符优先级:

补充:Java中跳出循环的方法:

众所周知,在Java中,如果想跳出for循环,一般情况下有两种方法:break和continue。

break是跳出当前for循环,如下面代码所示:

package com.xtfggef.algo;

public class RecTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		for(int i=0; i<10; i++){
			if(i==5){
				break;
			}
			System.out.print(i+" ");
		}
	}
}

输出:0 1 2 3 4

也就是说,break会跳出(终止)当前循环。

continue是跳出当前循环,开使下一循环,如下所示:

package com.xtfggef.algo;

public class RecTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			if (i == 5) {
				continue;
			}
			System.out.print(i+" ");
		}
	}
}

输出:0 1 2 3 4 6 7 8 9

以上两种方法没有办法跳出多层循环,如果需要从多层循环跳出,则需要使用标签,定义一个标签label,然后再需要跳

出的地方,用break label就行了,代码如下:

package com.xtfggef.algo;

public class RecTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		loop: for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 10; j++) {
				for (int k = 0; k < 10; k++) {
					for (int h = 0; h < 10; h++) {
						if (h == 6) {
							break loop;
						}
						System.out.print(h);
					}
				}
			}
		}
		System.out.println("\nI'm here!");
	}
}

输出:

012345
I'm here!

意思很显然!

 

持续更新中...

Java之美[从菜鸟到高手演变]之多线程简介

从本篇文章起,我将在Java多线程方面进行深入剖析,这是很大的一部分内容,也是我们作为Java开发者必须要跨过的一道坎儿!因为Java本身就是多线程的语言,想要真正掌握Java,那么请先掌握多线程!文...
  • zhangerqing
  • zhangerqing
  • 2012-12-11 21:59:53
  • 11428

Java之美[从菜鸟到高手演变]之优秀资源集合

专门开一篇文章,记录一些优秀的技术http://www.ibm.com/developerworks/cn/java/
  • zhangerqing
  • zhangerqing
  • 2014-11-08 21:09:51
  • 5381

Java之美[从菜鸟到高手演变]之spring框架初识

初识轻量级Java开源框架 --- Spring作者:egg微博:http://weibo.com/xtfggef出处:http://blog.csdn.net/zhangerqingspring是一...
  • zhangerqing
  • zhangerqing
  • 2014-12-01 23:04:36
  • 53153

C语言编程,从菜鸟到高手

    IT行业,应届毕业生不能顺利地找到理想工作的原因在于,没有编程的实战经验,即使是计算机科班出身的也会有相当的困惑!    就是说,即使你不是计算机科班出身,通过自己的积极努力,照样可以提高自己...
  • surfer1212
  • surfer1212
  • 2006-10-30 17:26:00
  • 658

C语言编程,从菜鸟到高手

    IT行业,应届毕业生不能顺利地找到理想工作的原因在于,没有编程的实战经验,即使是计算机科班出身的也会有相当的困惑!    就是说,即使你不是计算机科班出身,通过自己的积极努力,照样可以提高自己...
  • pony12
  • pony12
  • 2006-10-30 15:30:00
  • 2254

JVM菜鸟进阶高手之路五

参考gc,发现大概一小时运行一次FGC,特别奇怪,笨神一看这样的问题就知道是system gc导致的,rmi默认一小时主动触发一次,由于没有gc日志,通过jstat命令观察2小时发现 ...
  • lirenzuo
  • lirenzuo
  • 2017-07-28 15:04:55
  • 1455

传智播客C语言视频第一季(有效下载期为10.1-10.7,10.8关闭)

J:\传智播客_尹成_C语言从菜鸟到高手├─传智播客_尹成_C语言从菜鸟到高手_第一章C语言概述A│      第一讲1.1C语言第一阶段.mp4│      第二讲1.2c语言入门教程.mp4│  ...
  • yincheng01
  • yincheng01
  • 2014-10-03 15:50:16
  • 9964

JVM 菜鸟进阶高手之路三

笨神大大分享: 在微信小程序里面搜索:JVMPocket,这个小程序是笨神大大提供的,里面可以搜索相关JVM参数,用法。 -XX:MaxTenuringThreshold,这个参数主要是设置YGC的时...
  • lirenzuo
  • lirenzuo
  • 2017-07-22 10:09:31
  • 1721

清华尹成C语言从菜鸟到高手.pdf

  • 2017年02月01日 02:27
  • 95.25MB
  • 下载

嵌入式从菜鸟到高手学习步骤

嵌入式从菜鸟到高手学习步骤 关于学习嵌入式的步骤。 ★实践是最锻炼人的方式,但是我想在校生很少有这样的机会。所以我想学习嵌入式要从个人的知识背景和现实条件出发。订立合适的阶段目标,在允许的条件...
  • qianrushi1234
  • qianrushi1234
  • 2014-05-22 15:28:16
  • 548
收藏助手
不良信息举报
您举报文章:Java之美[从菜鸟到高手演变]之类与对象(三)
举报原因:
原因补充:

(最多只允许输入30个字)