Java面向对象特性—组合性

目录

1. 成员类

1.1. 非静态成员类

1.2.静态成员类

2. 局部类

3. 匿名类


       组合性是指整体与部分之间的关系,整体是由一个或多个部分构成的。例如,树是由树根、树枝和树叶等部分构成,订单是由一组订单项构成,计算机是由CPU、内存和硬盘等部分构成的。为了显式地表达类之间的整体-部分关系,Java支持在一个类中声明另一个类,这样的类称为内部类(inner class),内部类所在的类称为外部类(outer class)。根据内部类在外部类中所处的位置可分为:成员类、局部类和匿名类。

1. 成员类

       在一个类中除了可以定义成员变量和成员方法外,还可以定义类,这样的类被称为成员类,成员类不能与外部类重名。与成员变量和成员方法类似,成员类的访问权限也分为四种:public、protected、private和默认,它们的含义与成员变量和成员方法是一致的。如果成员类的前面用final修饰,则该成员来不能被继承。成员类可以定义为抽象类,但是需要被其它的内部类继承或实现。下面介绍非静态成员和静态成员类的定义和使用。

1.1. 非静态成员类

       非静态成员类没有static修饰符,在非静态成员类中不能定义静态成员(静态变量和静态方法)。非静态成员类可以访问外部类的所有成员,在非静态成员类中访问外部类的成员时,若外部类的成员与其内部的成员不重名时,可以直接用成员名称访问,否则,访问外部类成员的语法格式如下:

                外部类名.this.外部类成员变量名; //访问外部类的成员变量

                外部类名.this.外部类成员方法名([实参列表]);//访问外部类的成员方法

       在外部类之外创建非静态成员类的对象时,需要先创建外部类的对象,然后使用以下语句创建非静态成员类的对象:

                外部类名.非静态成员类名 对象名=外部类的对象名.new 非静态成员类名([实参数列表]);

【例1】下面的代码演示了定义非静态成员类的方法。

/*
 * 外部类:订单
 */
public class Order {
	String number; //编号
	double money; //总金额
	Item items[]; //订单项集合
	//带参数的构造方法
	public Order(String number) {
		this.number=number;
	}
	//设置订单项集合
	public void setItem(Item items[]) {
		this.items=items;
	}
	//计算订单总金额
	public void setMoney(){
		money=0;
		for(int i=0;i<items.length;i++) {
			money+=items[i].amount*items[i].money;
		}
	}
	//输出订单信息
	public void print() {
		System.out.println("number:"+number+",money:"+money);
		for(Item item:items) {
			item.print();
		}
	}
	/*
	 * 非静态成员类:订单项
	 */
	class Item{
		String number;  //订单编号
		int no;         //序号
		String product; //产品
		double price;   //价格
		int amount;     //数量
		double money;   //金额
		//带参数构造方法
		Item(int no,String product,double price,int amount){
			number=Order.this.number;//访问外部类中的成员变量
			this.no=no;
			this.product=product;
			this.price=price;
			this.amount=amount;
			money=amount*price;
		}
		//输出订单项信息
		void print() {
			System.out.println(" "+number+","+no+","+product
				+","+amount+","+price+","+money);//访问自己的成员变量
		}
	}
}

在上面代码中,类Item为类Order的一个非静态成员类,类Order中声明了一个数据类型为Item的数组成员变量items。类Item和类Order中都有一个名为number的成员变量,因此,在类Item中,访问类Order的成员变量number时的语句为:Order.this.number。另外,在类Item中还有一个与类Order中重名的变量money,由于是访问Item自己的成员变量,因此可以直接按名访问。

【例2】下面程序演示了创建非静态成员类的对象。

public class OrderManage {
	public static void main(String[] args) {
		//创建订单 (外部类的对象)
		Order order=new Order("fc001");
		//定义订单项数组 (非静态成员类的对象)
		Order.Item items[]=new Order.Item[2];
		//订单项数组的初始化(在外部类之外创建非静态成员类的对象)
		items[0]=order.new Item(1,"computer",0.8,5);
		items[1]=order.new Item(2,"telephone",0.5,10);
		//设置订单的订单项集合
		order.setItem(items);
		//计算订单的总金额
		order.setMoney();
		//输出订单信息
		order.print();
	}
}

程序运行结果为:

    number:fc001,money:70.0

    fc001,1,computer,5,0.8,4.0

    fc001,2,telephone,10,0.5,5.0

1.2.静态成员类

       如果使用static关键字来修饰一个成员类,则该成员类为静态成员类。静态成员类属于外部类的本身,而不属于外部类的某个对象。静态成员类既可以定义静态成员,也可以定义非静态成员。在静态成员类中,可以直接访问外部类的所有静态成员,但不能直接访问外部类的非静态成员。

       在静态成员类中访问外部类的成员时,若外部类的成员与该静态成员类的成员不重名,则可以直接用成员名进行访问,若外部类与该静态成员类的成员重名,则访问外部类的成员语法为:

                外部类名.静态成员变量名;         //访问外部类的静态成员变量

                外部类名.静态成员方法名([实参列表]);//访问外部类的静态成员方法

       在外部类之外创建静态成员类的对象的语法格式为:

                外部类名.静态成员类名 对象名=new 外部类名.静态成员类名([实参列表]);

【例3】下面的代码演示了定义静态成员类的方法。

/*
 * 外部类:计算机
 */
public class Computer {
	String brand;    //品牌
	String model;    //型号   
	CPU cpu;         //CPU
	static int cpuNum;   //当前序号(静态变量)
	//带参数构造方法
	public Computer(String brand,String model,CPU cpu){
		this.brand=brand;
		this.model=model;
		this.cpu=cpu;
	}
	//设置计算机的CPU
	public void setCPU(CPU cpu) {
		this.cpu=cpu;
	}
	//输出计算机信息
	public void print() {
		System.out.println(brand+","+model);
		cpu.print();
	}
	/*
	 * 静态成员类:CPU
	 */
	static class CPU{
		int no;      //编号
		String brand;//品牌
		String type; //类型
		double GHz;  //主频
		int core;    //核数
		//带参数的构造方法
		CPU(String brand,String type,double GHz,int core){
			this.brand=brand;
			this.type=type;
			this.GHz=GHz;
			this.core=core;
			cpuNum++; //访问外部类的静态成员变量
			no=cpuNum;
		}
		//输出CPU信息
		void print() {
			System.out.println(" cpu:"+no+":"+brand+","
+type+","+GHz+"GHz,"+core+"core");
		}
	}
}

在上面代码中,类CPU为类Computer的一个静态成员类,在类Computer中声明了一个数据类型为CPU的成员变量cpu。在静态成员类CPU中的可以访问外部类中的静态成员变量cpuNum,但是,不能访问非静态成员变量。

【例4】下面程序演示了创建静态成员类的对象。

public class ComputerManage {
	public static void main(String[] args) {
		//创建两个CPU对象(成员类的对象)
		Computer.CPU cpu1=new Computer.CPU("Intel","i7",2.81,2);
		Computer.CPU cpu2=new Computer.CPU("Intel","i5",3.2,4);
		//创建两个计算机对象(外部类的对象)
		Computer computer1=new Computer("Lenovo","T470p",cpu1);
		Computer computer2=new Computer("Dell","T3420",cpu2);
		//输出计算机的信息
		computer1.print();
		computer2.print();
	}
}

程序运行结果为:

Lenovo,T470p

     cpu:1:Intel,i7,2.81GHz,2core

Dell,T3420

     cpu:2:Intel,i5,3.2GHz,4core

2. 局部类

       局部类是在外部类的方法中定义的类,其名称不能与其所在的外部类重名。与局部变量类似,局部类的作用域是定义它的代码块。局部类可以是abstract和final型,权限访问符只能是缺省的,不能是public、private或protected。局部类中不允许包括静态成员(变量和方法)。在局部类中只能访问它所在方法中的final型变量,而不能访问非final型的变量。局部类只在定义它的代码段中可见,只能在外部类的内部使用,在外部类之外是不可见的,不能在外部类之外创建局部类的对象。

       在局部类中可以访问外部类的成员,如果局部类成员与外部类成员不重名,可以直接用成员名进行访问,如果外部类成员与局部类成员重名,访问规则如下:

(1)访问外部类的非静态成员需要使用以下语法:

                外部类名.this.外部类成员变量名;

                外部类名.this.外部类成员方法名([实参列表]);

(2)访问外部类静态成员的语法:

                外部类名.静态成员变量名;        

                外部类名.静态成员方法名([实参列表]);

局部类的典型用法是与接口相配合,用局部类来实现接口,并在方法中返回接口类型。

【例5】下面程序演示了局部类的定义与使用方法。

public interface OuterInter {
	public int sign(int value);
}
public class OuterClass {
	public OuterInter getInterface(){
		//局部类(实现外部接口)
		class LocalClass implements OuterInter{
			//实现接口的方法
			public int sign(int value) {
				if(value<0)
					return -1;
				else if(value==0)
					return 0;
				else
					return 1;
			}
		}
		//常见局部类的对象并返回
		return new LocalClass();
	}
	public static void main(String[] args) {
		OuterClass oc=new OuterClass();
		OuterInter oi=oc.getInterface();
		System.out.println("10的符号为:"+oi.sign(10));
		System.out.println("0的符号为:"+oi.sign(0));
		System.out.println("-10的符号为:"+oi.sign(-10));
	}
}

执行类OuterClass,程序运行结果为:

10的符号为:1

0的符号为:0

-10的符号为:-1

3. 匿名类

       匿名类是指没有名称的类。一般情况下,如果用一个类对另一个类进行扩展(继承)或者实现一个特定的接口,同时,这个类实现的功能比较简单,或者在程序中只使用一次,就可以用匿名类的方式创建这个类的对象。

       匿名类可以直接用其父类的名称或接口的名称来定义,其语法格式如下:

        new 父类名或接口名(){

                类体;

        }

      匿名类具有如下特征:

       (1)匿名类必须是一个具体的对象,不允许是abstract的,也不可以是static。

       (2)匿名类的类体必须将其继承或实现的内容具体化,这与普通类没有差别。

       (3)匿名类本身没有名字,所以没有构造方法,只能用super关键字调用其父类的构造方法。

       (4)匿名类只能是final型的,其中包括的所有变量和方法都是final型的。

       由匿名类的定义可知,其返回的是一个对象的引用,因此,可以直接使用或者将其赋给一个引用变量,也可以将其作为方法调用的实参。

【例6】下面的程序演示了匿名类的定义与使用。

public class OuterClass1 {
	public void print() {
		System.out.println("这是一个外部类");
	}
}
public class AnonyClassDemo {
	public static void print(OuterClass1 oc) {
		oc.print();
	}
	public static void main(String[] args) {
		OuterClass1 oc=new OuterClass1();
		oc.print();
		//直接使用匿名类
		(new OuterClass1() {
			public void print() {
				System.out.println("直接使用匿名类");
			}
		}).print();
		
		//将匿名类的返回值赋给一个引用变量
		OuterClass1 obj=new OuterClass1() {
			public void print() {
				System.out.println("将匿名类的返回值赋给一个引用变量");
			}
		};
		obj.print();
		
		//将匿名类的返回值赋给方法的参数
		print(new OuterClass1() {
			public void print() {
				System.out.println("将匿名类的返回值赋给方法的参数");
			}
		});
		
	}
}

执行类AnonyClassDemo,程序运行的结果为:

这是一个外部类

直接使用匿名类

将匿名类的返回值赋给一个引用变量

将匿名类的返回值赋给方法的参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值