栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

第七章总结--面向对象核心

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第七章总结--面向对象核心

7.1 类的封装

封装是面向对象编程的核心思想,将对象的属性和行为封装起来。其载体就是类。

无封装代码如下:

public class Restaurant1 {//创建一个类
 
	public static void main(String[] args) {//主方法
		String cookName="Tom Cruise";//厨师的名字叫Tom Cruise
		System.out.println("**请让厨师为我做一份香辣肉丝。***");//输出
		System.out.println(cookName+"切葱花");//输出
		System.out.println(cookName+"洗蔬菜");//输出
		System.out.println(cookName+"开始烹饪"+"香辣肉丝");//输出
		System.out.println("**请问厨师叫什么名字?***");//输出
		System.out.println(cookName);//输出
		System.out.println("请让厨师给我切一点葱花。***");//输出
		System.out.println(cookName+"切葱花");//输出
	}
 
}

运行结果为:

 封装成类代码如下:

public class Restaurant2 {//创建一个类
 
	public static void main(String[] args) {//主方法
		Cook1 cook=new Cook1();//创建厨师类的对象
		System.out.println("**请让厨师为我做一份香辣肉丝。***");//输出
		cook.cooking("香辣肉丝");//厨师烹饪香辣肉丝
		System.out.println("**你们的厨师叫什么名字?***");//输出
		System.out.println(cook.name);//厨师回答自己的名字
		System.out.println("**请让厨师给我切一点葱花。***");//输出
		cook.cutOnion();//厨师去切葱花
 
	}
 
}
class Cook1{//创建类
	String name;//厨师的名字
	public Cook1(){//定义一个方法
		this.name="Tom Cruise";//厨师的名字叫Tom Cruise
	}
	void cutOnion(){//厨师切葱花
		System.out.println(name+"切葱花");//输出信息
	}
	void washVegetables(){//厨师洗蔬菜
		System.out.println(name+"洗蔬菜");//输出信息
	}
	void cooking(String dish){//厨师烹饪顾客点的菜
		washVegetables();//调用洗蔬菜方法
		cutOnion();//调用切葱花方法
		System.out.println(name+"开始烹饪"+dish);//输出信息
	}
}

运行结果为:

使用private修饰代码如下: 

public class Restaurant4 {//创建类
private Cook2 cook=new Cook2();//餐厅封装的厨师类
public void takeOlder(String dish){//下单	Restaurant2 a=new Restaurant2();//创建一个对象
	cook.cooking(dish);//通知厨师做菜
	System.out.println("您的菜好了,请慢用。");//输出信息
}
public String saySorry(){//拒绝顾客请求
	return"抱歉,餐厅不提供此项服务。";//返回字符串
	
}
	public static void main(String[] args) {//主方法
		Restaurant4 water=new Restaurant4();//创建餐厅对象,为顾客提供服务
		System.out.println("**请让厨师为我做一份香辣肉丝。***");//输出
		water.takeOlder("香辣肉丝");//服务员给顾客下单
		System.out.println("**你们的厨师叫什么名字?***");//输出信息
		System.out.println(water.saySorry());//服务员给顾客善意的答复
		System.out.println("**请让厨师给我切一点葱花。***");//输出信息
		System.out.println(water.saySorry());//服务员给顾客善意的答复
	}
 
}

 运行结果为:

7.2类的继承

        继承在面向对象开发思想中是一个非常重要的概念,它使整个程序架构具有一定的弹性,在程序中复用已经定义完善的类不仅可以减少软件开发周期,还可以提高软件的可维护性和可扩展性。其基本思想是基于某个父类的扩展,制定出一个新的子类,子类可以继承父类原有的属性和方法,也可以增加原来父类所不具备的属性和方法,或者直接重写父类中的某些方法。例如,平行四边形是特殊的四边形,可以说平行四边形类继承了四边形类,这时平行四边形类将所有四边形具有的属性和方法都保留下来,并基于四边形类扩展了一些新的平行四边形类特有的属性和方法。

 7.2.1extends 关键字

让一个类继承另一个类,用extends关键字,语法如下:

child  extends parents

代码如下:

class Computer{//父类
	String screen="液晶显示屏";
	void startup(){//开机方法
		System.out.println("电脑正在开机,请等待...");//输出
	}
}
 
public class Pad extends Computer{//创建一个类并继承父类
String battery="5000毫安电池";//子类独有的属性
	public static void main(String[] args) {//主方法
		Computer pc=new Computer();//电脑类
		System.out.println("computer的屏幕是:"+pc.screen);//输出
		pc.startup();//调用父类方法
		Pad ipad=new Pad();//平板电脑类
		System.out.println("pad的屏幕是:"+ipad.screen);//子类可以直接使用父类属性
		System.out.println("pad的屏幕是:"+ipad.battery);//子类独有的属性
		ipad.startup();//子类可以直接使用父类方法
 
	}
 
}

运行结果为:

7.2.2方法的重写
  1.重写的实现 
        继承并不只是扩展父类的功能,还可以重写父类的成员方法。重写(还可以称为覆盖)就是类中将父类的成员方法的名称保留,重新编写成员方法的实现内容,更改成员方法的存储权限,可修改成员方法的返回值类型。

代码如下:

class Computer2{//父类:电脑
	void showPicture(){//定义一个方法
		System.out.println("鼠标单击");//输出信息
	}
}
public class Pad2 extends Computer2 {//创建一个类并继承父类
void showPicture(){//重写父类的方法
	System.out.println("手指点击触摸屏");//输出信息
}
	public static void main(String[] args) {//主方法
		Computer2 pc=new Computer2();//电脑类
		System.out.print("pc打开图片:");//输出信息
		pc.showPicture();//调用方法
		Pad2 ipad=new Pad2();//平板电脑类
		System.out.print("ipad打开图片:");//输出信息
		ipad.showPicture();//重写父类方法
		Computer2 computerpad=new Pad2();//父类声明,子类实现
		System.out.print("computerpad打开图片:");//输出信息
		computerpad.showPicture();//调用父类方法,实现子类重写的逻辑
	}
 
}

运行结果为:

2. super关键字
如果想在子类的方法中实现父类原有的方法 解决这种需求,Java 提供了 super 关键字。
super 关键字的使用方法与 this 关键字类似。this 关键字代表本类对象,super关键字代表文对象,使用方法如下:

super.property; //调用父类的属性 
super.method();//调用父类的方法 

代码如下:

class Computer3{//父类:电脑
	String sayHello(){//定义一个方法
		return"欢迎使用";//返回一个字符串
	
	}
	
}
public class Pad3 extends Computer3 {//子类:平板电脑
	String sayHello(){//重写方法
		 return super.sayHello()+"平板电脑";//调用父类方法,在其结果后添加字符串
	}
 
	public static void main(String[] args) {//主方法
Computer3 pc=new Computer3();//电脑类
System.out.println(pc.sayHello());//调用父类的方法并输出
Pad3 ipad=new Pad3();//平板电脑类
System.out.println(ipad.sayHello());//调用子类的方法并输出
 
	}
 
}
 

运行结果为:

7.2.3所有类的父类--Object类
        使用 class关键字定义类时,就应用了继承原理,因或间接继承了java.lang.Object类。Object类是比较特殊的类,它是所有类的父类,是 Java 类层中的最高层类。当创建一个类 class时,总是在继承,除非某个类已经指定要从其他类继承,否则它就是从java.lang.Object类继承而来的,可见Java中的每个类都源于java.lang.Object类,如String、Integer等类都是继承于Object类;除此之外自定义的类也都继承于Object类。由于所有class类都是Object子类,所以在定义类时,省略了 extends Object关键字,在Object类中主要包括cloneO、finalizeequals、toString0等方法,其中常用的两个方法为equals()和toString0方法。由于所有的类都是Object类的子类,所以任何类都可以重写 Object类中的方法。 

1.getClass()方法
        getClass()方法是Object类定义的方法,它会返回对象执行时的 Class实例,然后使用此例用getName()方法可以取得类的名称。
语法如下:

getclass().getName();


可以将getClass()方法与toString()方法联合使用。
2. toString()方法
        toString0方法的功能是将一个对象返回为字符串形式,它会返回一个 String实例。在实际的营用中通常重写toString0)方法,为对象提供一个特定的输出模式。当这个类转换为字符串或与字符甲连接时,将自动调用重写的 toString()方法。

代码如下:

		public class Can {//创建类
			public String toString(){//重写toString()方法
				return "在"+getClass().getName()+"类中重写toString()方法";//返回值
			}
				public static void main(String[] args) {//主方法
					System.out.println(new Can());//调用方法并输出,打印本类对象
				}
			 
			}
	 

运行结果为:

3. equals()方法
        equals()方法,是比较“==”运算符与equals()方法,说明”==”比是两个对象的引用是否相等,而equals0方法比较的是两个对象的实际内容。

代码如下:

		public class Can {//创建类
			 
				public static void main(String[] args) {//主方法
					String s1="123";//实例化两个对象,内容相同
					String s2="123";//实例化对象
					System.out.println(s1.equals(s2));//使用equals()方法
					Can v1= new Can();//实例化两个类对象
					Can v2=new Can();//实例化对象
					System.out.println(v1.equals(v2));//使用equals()方法
				}
			 
			}

运行结果为:

7.3类的多态
        多态意为一个名字可具有多种语义,在程序设计语言中,多态性是指“一种定义,多种实现”例如,运算符“+”作用于两个整型量时是求和,而作用于两个字符型量时则是将其连接在一起。用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。类的多态性可以从两方面体现:一是方法的重载,二是类的上下转型
7.3.1 方法的重载
        我们知道构造方法的名称由类名决定,所以构造方法只有一个名称,但如果希望以不同的方式来实例化对象,就需要使用多个构造方法来完成。由于这些构造方法都需要根据类名进行命名,为了让方法名相同而形参不同的构造方法同时存在,必须用到“方法重载”虽然方法重载起源于构造方法,但是它也可以应用到其他方法中。
        方法的重载就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同就可。

代码如下:

		public class Can {//创建类
				public static int add(int a){//定义一个方法并传入一个int型参数
					return a;//返回一个整型值
				}
				public static int add(int a,int b){//定义一个方法并传入两个参数
					return a+b;//返回a+b的值
				}
				public static double add(double a,double b){//定义一个方法并传入两个参数
					return a+b;//返回a+b的值
				}
				public static int add(int a,double b){//定义一个方法并传入两个参数
					return (int)(a+b);//返回a+b的值,同时利用强制转换成int型
				}
				public static int add(double a,int b){//定义一个方法并传入两个参数
					return (int)(a+b);//返回a+b的值,同时利用强制转换成int型
				}
				public static int add(int...a){//定义一个不定长参数方法
					int s=0;//定义一个int型变量并赋予初值
					for(int i=0;i

运行结果为:

7.3.2 向上转型

子类转变成父类类型

代码如下:

class Quadrangle{//四边形类
public static void draw(Quadrangle q){//四边形类中的方法
//SomeSentence
}
}
public class Parallelogram extends Quadrangle{//平行四边形类,继承了四边形类
public static void main(String args[]){//主方法
Parallelogram p=new Parallelogram();//实例化平行四边形类对象引用
draw(p);//调用父类方法
}
}

 7.3.3 向下转型

父类转变成子类 使用强制转换

代码如下:

class Quadrangle{//父类
	public static void draw(Quadrangle q){//父类方法
		//SomeSentence
	}
}
public class Parallelogram extends Quadrangle {//子类继承父类
 
	public static void main(String[] args) {//主方法
	draw(new Parallelogram());//调用方法并传入子类对象
	Quadrangle q=new Parallelogram();//将平行四边形对象看作是四边形对象,称为向上转型操作
	Parallelogram p=q;//向下转型
 
	}
 
}

运行结果为:

 7.3.4 instanceof关键字
        当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生CastException 异常,所以在执行向下转型之前需要养成一个良好的习惯,就是判断父类对象是否子类对象的实例。这个判断通常使用instanceof操作符来完成。可以使用instanceof操作符判断是一个类实现了某个接口(接口会在74节中进行介绍),也可以用它来判断一个实例对象是否属于个类。
instanceof的语法格式如下:
 

myobject instanceof ExampleClass

myobject:某类的对象引用。

ExampleClass:某个类。
        使用instanceof操作符的表达式返回值为布尔值。如果返回值为true,说明myobject 对象ExampleClass 的实例对象;如果返回的值为false,说明myobject对象不是ExampleClass的实例对象。

代码如下:

class Quadrangle{//类名
	public static void draw(Quadrangle q){//构造一个方法并传入一个参数
		//SomeSentence
	}
}
class Square extends Quadrangle{//构造一个类并继承另一个类
	//SomeSentence
}
class Anything{//构造一个类
	//SomeSentence
}
public class Parallelogram extends Quadrangle {//创建一个类并继承另一个类
 
	public static void main(String[] args) {//主方法
		Quadrangle q=new Quadrangle();//创建一个对象
		if(q instanceof Parallelogram){//判断该对象是否属于该类
			Parallelogram p=(Parallelogram)q;//进行强制转换
		}
		if(q instanceof  Square){//判断该对象是否属于该类
			Square s=(Square) q;//进行强制转换
		}
		System.out.println(q instanceof  Anything );//输出信息
	}
 
}

运行结果为:

 7.3 抽象类与接口

7.4.1抽象类与抽象方法
        在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。回提继承和多态原理,继承树中越是在上方的类越抽象,如鸽子类继承鸟类、鸟类继承动物类等。在多态机制中,并不需要将父类初始化对象,我们需要的只是子类对象,所以在 Java 语言中设置抽象不可以实例化对象,因为图形类不能抽象出任何一种具体图形,但它的子类却可以。
        Java中定义抽象类时,需要使用abstract关键字,其语法如下:

[权限修饰符] abstract class 类名 {
类体
                                }


使用abstract关键字定义的类称为抽象类,而使用abstract关键字定义的方法称为抽象方法,抽象方法的定义语法如下:

[权限修饰符] abstract 方法返回值类型 方法名 (参数列表);
public abstract class Market {//创建类
public String name;//商场名称
public String goods;//商品名称
public abstract void shop();//抽象方法,用来输出信息
	
 
}
public class TaobaoMarket extends Market {//创建类并继承商场类
 
	@Override
	public void shop() {//重写方法
		// TODO Auto-generated method stub
		System.out.println(name+"网购"+goods);	//输出信息	
	}
 
}
public class GoShopping {//类名
 
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
Market market=new WallMarket();//向上转型
market.name="沃尔玛";//赋值
market.goods="七匹狼西服";//赋值
market.shop();//调用方法
market=new TaobaoMarket();//创建一个对象
market.name="淘宝";//赋值
market.goods="韩都衣舍花裙";//赋值
market.shop();//调用方法
	}
 
}

运行结果为:

        综上所述,使用抽象类和抽象方法时,需要遵循以 下原则: 
(1)在抽象类中,可以包含抽象方法,也可以不包已含抽象方法,但是包含了抽象方法的类必须被定义为抽象类。
(2)抽象类不能直接实例化,即使抽象类中没有声 明抽象方法,也不能实例化。 
(3)抽象类被继承后,子类需要实现其中所有的抽象方法。
(4)如果继承抽象类的子类也被声明为抽象类,则可以不用实现父类中所有的抽象方法。使用抽象类时,可能会出现这样的问题:程序中会有太多冗余的代码,同时这样的父类局限生很大,例如,上面的例子中,也许某个不需要 shop()方法的子类也必须重写shopO方法。如果将这个shopO方法从父类中拿出,放在别的类里,又会出现新问题,就是某些类想要实现“买衣服”的场景,竟然需要继承两个父类。Java 中规定,类不能同时继承多个父类,面临这种问题时,接口的概念便出现了。 

7.4.2接口的声明及实现
接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。

接口使用interface 关键字进行定义,语法如下:

[ 修饰符 ] interface 接口名 [ extends 父接口名列表 ] {

    [public] [static] [final] 常量;
    [public] [abstract] 方法;


                                                    }

修饰符:可选,用于指定接口的访问权限,可选值为 public。如果省略则使用默认的访权限。
接口名:必选参数,用于指定接口的名称,接口名必须是合法的 Java标识符。一般情况下要求首字母大写。

extends父接口名列表:可选参数,用于指定要定义的接口继承
于哪个父接口。当使用extends关键字时,父接口名为必选参数。方法:接口方法定义而没有被实现。
一个类实现一个接口可以使用implements关键字,代码如下:
 

public class Parallelogram extends Quadrangle implements drawTest{

…//
    }

代码如下:

interface drawTest{//定义接口
	public void draw();//定义方法
}
class ParallelogramgleUseInterface implements drawTest{//创建类并继承接口
 
	@Override
	public void draw() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("平行四边形.draw()");//输出
	}
	
}
class SquareUseInterface implements drawTest{//创建类并继承接口
 
	@Override
	public void draw() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("正方形.draw()");//输出
	}
	
}
public class QuadrangleUseInterface {//创建类
 
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		drawTest[]d={//定义一个一维数组
				new SquareUseInterface(),new ParallelogramgleUseInterface()};//向上转型
		for(int i=0;i 

运行结果为:

7.4.3多重继承
在Java许继承但使用口可以实现多重继承,因为一个类可以同时实现多接口,这样可以将所有需要实现的接口放置在iplents字后并使用逗号”,“隔开,但会在一个类中产生庞大的代码量,因为继承一个接口时需要实现接口中所有的方法。
通过接口实现多重继承的语法如下:

class 类名 implements 接口1,接口2,…,接口n


代码如下:

public interface IFather {//定义一个接口
void smoking();//抽烟的方法
void goFishing();//钓鱼方法
}
public interface IMother {//定义一个接口
void watchTV();//看电视的方法
void cooking();//做饭的方法
}
public class Me implements IFather,IMother {//创建类并继承两个接口
 
	
	public void watchTV() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("我喜欢看电视");//输出信息
	}
 
 
	public void cooking() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("我喜欢做饭");//输出信息
	}
 
	
	public void smoking() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("我喜欢抽烟");//输出信息
	}
 
	@Override
	public void goFishing() {//重写方法
		// TODO Auto-generated method stub
		System.out.println("我喜欢钓鱼");//输出信息
	}
 
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
IFather father=new Me();//进行向上转型
System.out.println("爸爸的爱好:");//输出信息
father.smoking();//调用方法
father.goFishing();//调用方法
IMother mather=new Me();//进行向上转型
System.out.println("妈妈的爱好:");//输出信息
mather.cooking();//调用方法
mather.watchTV();//调用方法
	}
 
 
}

运行结果为:

7.4.4区分抽象类与接口
        抽象类和接口都包含可以由子类继承实现的成员,但抽象类是对根源的抽象,而接口是对动作的抽象。抽象类的功能要远超过接口,那为什么还要使用接口呢?这主要是由于定义抽象类的代价高(因为每个类只能继承一个类,在这个类中,必须继承或编写出其子类的所有共性,因此,虽然接口在功能上会弱化许多,但它只是针对一个动作的描述,而且可以在一个类中同时实现多个接口,这样会降低设计阶段的难度。
抽象类和接口的区别主要有以下几点。
注意:
(1)子类只能继承一个抽象类,但可以实现任意多个接口。
声明类时,如果不使用p
(2)一个类要实现一个接口必须实现接口中的所有方法,而抽象类不必。
(3)抽象类中的成员变量可以是各种类型,而接口中的成员变量只能是public static finalf
口多学两招:
Java语言中,类的权限
(4)接口中只能定义抽象方法,而抽象类中可以定义非抽象方法。
定义一个public的doSt
(5)抽象类中可以有静态方法和静态代码块等,接口中不可以。
下面两段代码是等效的
(6)接口不能被实例化,没有构造方法,但抽象类可以有构造方法。

7.5 访问控制

7.5.1 访问控制符

        前面介绍了面向对象的几个基本特性,其中包括封装性,封装实际上有两方面的含义:把谈藏的隐藏起来、把该暴露的暴露出来,这两个方面都需要通过使用Java提供的“访问控制符”来现,Java中的访问控制符主要包括public、protected、private和default(缺省)等4种,这些控育符控制着类和类的成员变量以及成员方法的访问权限。

使用访问控制符时,需要遵循以下原则。

(1)大部分顶级类都使用public修饰;
(2)如果某个类主要用作其他类的父类,该类中包含的大部分方法只是希望被其子类重写。而不想被外界直接调用,则应该使用protected修饰;
(3)类中的绝大部分属性都应该使用private修饰,除非一些static或者类似全局变量的属性,才考虑使用public 修饰;
(4)当定义的方法只是用于辅助实现该类的其他方法(即工具方法),应该使用private修饰;(5)希望允许其他类自由调用的方法应该使用public修饰。
7.5.2 Java 类包
        在Java中每定义好一个类,通过Java编译器进行编译之后,都会生成一个扩展名为class的文件,当这个程序的规模逐渐庞大时,就很容易发生类名称冲突的现象。那么JDK API中提供了成千上万具有各种功能的类,Java中提供了一种管理类文件的机制,就是类包。Java中每个接口或类都来自不同的类包,无论是JavaAPI中的类与接口还是自定义的类与接口都需要隶属于某一个类包,这个类包包含了一些类和接口。如果没有包的存在,管理程序中的类名称将是一件非常麻烦的事情,如果程序只由一个类定义组成,并不会给程序带来什么影响,但是险着程序代码的增多,难免会出现类同名的问题。例如,在程序中定义一个Login类,因业务需要,还要定义一个名称为Login 的类,但是这两个类所实现的功能完全不同,于是问题就产生了,编译器不会允许存在同名的类文件。解决这类问题的办法是将这两个类放置在不同的类包中,实际上 ava中类的完整名称是包名与类名的组合。

在类中定义包名的语法如下:
package包名1[.包名2[.包名3...]];
        在上面的语法中。包名可以设置多个,包名和包名之间使用.分割,包名的个数没有限制,其中前面的包名包含后面的包名。
在类中指定包名时需要将package放置在程序的第一行,它必须是文件中的第一行非注释代码当使用package关键字为类指定包名之后,包名会成为类名中的一部分,预示着这个类必须指定全名。

7.5.3 final 关键字
1.final 类
定义为final的类不能被继承。如果希望一个类不允许任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类设置为final形式。
final类的语法如下:

final class类名()


        如果将某个类设置为final形式,则类中的所有方法都被隐式地设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。

代码如下:

final class FinalClass {//创建类
	int a=3;//定义一个整型变量并赋予初值
	void doit(){//定义一个方法
	}
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
FinalClass f=new FinalClass();//创建对象
f.a++;//调用成员变量并进行自增运算
System.out.println(f.a);//输出
	}
 
}
 

2.final方法

定义的final的方法不能被重写,在父类中定义为private final 可以被子类覆盖。

代码如下:

class Parents{//类名
	private final void doit(){//方法
		System.out.println("父类.doit()");//输出
	}
	final void doit2(){//方法
		System.out.println("父类.doit2()");//输出
	}
	public void doit3(){//方法
		System.out.println("父类.doit3()");//输出
	}
}
class Sub extends Parents{//创建类并继承父类
	public final void doit(){//方法
		System.out.println("子类.doit()");//输出
	}
//	final void doit2(){//方法
	//	System.out.println("父类.doit2()");
		
	//}
	public void doit3(){//方法
		System.out.println("子类.doit3()");//输出
	}
}
public class FinalMethod {//创建类
 
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
Sub s=new Sub();//创建对象
s.doit();//调用方法
Parents p=s;//执行向上转型操作
//p.doit();//不能调用private方法
p.doit2();//调用方法
p.doit3();//调用方法
	}
 
}

运行结果为:

 3.final 变量
f        inal关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使用如下语句:

final double PI=3.14;


        当在程序中使用PI这个常量时,它的值就是3.14,如果在程序中再次对定义为 final的常量赋值,编译器将不会接受。
        final关键字定义的变量必须在声明时对其进行赋值操作。final除了可以修饰基本数据类型的常量,还可以修饰对象引用。由于数组也可以被看作一个对象来引用,所以final可以修饰数组。一旦一个对象引用被修饰为final 后,它只能恒定指向一个对象,无法将其改变以指向另一个对象。一个是static 又是 final 的字段只占据一段不能改变的存储空间。

代码如下:

import java.util.Random;//导入random方法
import static java.lang.System.out;//导入方法
 
class Test{//类名
	int i=0;//定义一个整型变量并初始化
}
public class FinalData {//创建类
static Random rand=new Random();//创建对象
private final int VALUE_1=9;//定义常量
private static final int VALUE_2=10;//定义常量
private  final Test test=new Test();//创建对象
private Test test2=new Test();//创建对象
private final int[]a={1,2,3,4,5,6};//定义一个一维数组并赋值
private final int i4=rand.nextInt(20);//定义变量并随即赋值
private static final int i5=rand.nextInt(20);//定义变量随机赋值
public String toString(){//使用toString()方法
	return i4+" "+i5+" ";//返回字符串
}
	public static void main(String[] args) {//主方法
	FinalData data=new FinalData();//创建对象
	data.test=new Test();//创建对象
	data.VALUE_2;//调用变量
	data.test2=new Test();//向上转型
for(int i=0;i 

运行结果为:

import java.util.Random;//导入Random方法
import static java.lang.System.out;//导入方法
 
public class FinalStaticData {//创建类
private static Random rand=new Random();//实例化一个Random类对象
private final int a1=rand.nextInt(10);//随机赋值
private static final int a2=rand.nextInt(10);//随机赋值
 
	public static void main(String[] args) {//主方法
		FinalStaticData fdata=new FinalStaticData();//创建对象
		out.println("重新实例化对象调用a1的值:"+fdata.a1);//输出
		out.println("重新实例化对象调用a1的值:"+fdata.a2);//输出
		FinalStaticData fdata2=new FinalStaticData();//创建对象
		out.println("重新实例化对象调用a1的值:"+fdata2.a1);//输出
		out.println("重新实例化对象调用a2的值:"+fdata2.a2);//输出
	}
 
}

 运行结果为:

        从本实例的运行结果中可以看出,定义为 final的常量不是恒定不变的,将随机数赋予定义为 final的常量,可以做到每次运行程序时改变al的值。但是a2与al不同,由于它被声明为 static final形式,所以在内存中为a2开辟了一个恒定不变的区域,当再次实例化一个FinalStaticData对象时,仍然指向a2这块内存区域,所以a2的值保持不变。a2 是在三装载时被初始化,并不是每次创建新对象时都被初始化,而al会在重新实例化对象时被更改。 

7.6内部类

7.6.1 成员内部类

 在一个类使用内部类,可以在内部类中直接存取其所在类的私有成员变量。

        语法如下:

public class OuterClass{            //外部类
     private class  InnerClass    {    //内部类
        //...
    }       
}

在内部类中可以随意使用外部类的成员方法以及成员变量,尽管这些成员被修饰为private。

        内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象。那么内部类对象就会绑定在外部类对象上。内部类初始化方式与其他初始化方式相同,都是使用new 关键字。

代码如下:

public class OuterClass {//创建类
innerClass in=new innerClass();//创建对象
public void ouf(){//方法
	
}
class innerClass{//类名
	innerClass(){//方法
		
	}
	public void inf(){//方法
	}
	int y=0;//定义变量
	}
	public innerClass doit(){//方法
		//y=4;
		in.y=4;//调用变量
		return new innerClass();//返回对象
	}
 
	public static void main(String[] args) {//主方法
		OuterClass out=new OuterClass();//创建对象
		OuterClass.innerClass in=out.doit();//调用方法
		OuterClass.innerClass in2=out.new innerClass();//向上转型
 
	}
 
}

2.内部类向上转型为接口:

2.内部类向上转型为接口
        如果将一个权限修饰符为private的内部类向上转型为其父类对象,或者直接向上转型为一个提
口,在程序中就可以完全隐藏内部类的具体实现过程。 可以在外部提供一个接口,在接口中声明- 
个方法。如果在实现该接口的内部类中实现该接口的方法,就可以定义多个内部类以不同的方式实现接口中的同一个方法,而在一般的类中是不能多次实现接口中同一个方法的,这种技巧经常被用在Swing编程中,可以在一个类中做出多个不同的响应事件。

代码如下:

interface OutInterface{//定义接口
	public void f();//抽象方法
}
public class InterfaceInner {//创建类
 
	public static void main(String[] args) {主方法
		OuterClass2 out=new OuterClass2();//创建对象
		OutInterface outinter=out.doit();//调用方法
		outinter.f();//调用方法
	}
}
class OuterClass2{//类名
	private class InnerClass implements OutInterface{//继承接口
InnerClass(String s){//重写方法
	System.out.println(s);//输出
}
		
		public void f() {//重写方法
			System.out.println("访问内部类中的f()方法");//输出信息
		}
		
	}
	public OutInterface doit(){//重写方法
		return new InnerClass("访问内部类构造方法");//输出信息
		
	}
}

运行结果为:

 3.使用this关键字获取内部类与外部类的引用。

如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字》

代码如下:

public class TheSameName {//类名
private int x;//定义整型变量
private class Inner{//定义方法
	private int x=9;//定义整型变量并初始化
	public void doit(int x){//方法
		x++;//自增运算
		this.x++;//自增运算
		TheSameName.this.x++;//自增运算
	}
}
}

在类中,如果遇到内部类与外部类的成员变量重名相同,可以使用this关键字进行处理。

使用成员内部类时,应该遵循以下原则:
(1)可以有各种修饰符,可以用 porivate、public、protected、static、final、abstract等修饰;

(2)如果内部类有static限定,就是类级别的,否则为对象级别。类级别可以通过外部类直接访问,对象级别需要先生成外部的对象后才能访问;
(3)内外部类不能同名;
(4)非静态内部类中不能声明任何 static 成员; 
(5)内部类可以互相调用。

7.6.2 局部内部类

内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可以定义内部类。

代码如下:

interface OutInterface2{//定义接口
	
}
	
 class OuterClass3 {//类名
public OutInterface2 doit(final String x){//方法
	class InnerClass2 implements OutInterface2(String s){类继承
		InnerClass2(String s){//内部类
			
		s=x;//赋值
		System.out.println(s);//输出
	}
	
}
	return new InnerClass2("doit");//返回值
}
}

7.6.3 匿名内部类

代码如下:

interface OutInterface2{//定义一个接口
}
class OuterClass4{//创建类
public OutInterface2 doit(){//定义方法
return new OutInterface2(){//返回值
private int i=0;//定义变量并初始化
public int getValue(){//方法
return i;//返回值
                        }    
                    };
                }
            }

匿名类的所有实现代码都需要在大括号之间进行编写,语法如下:

return new A() {
        ...//内部类体
};

其中,A指类名。
        由于匿名内部类没有名称,所以匿名内部类使用默认构造方法来生成Outlnterface2 对象。在匿名内部类定义结束后,需要加分号标识,这个分号并不是代表定义内部类结束的标识,而是代表创建OutInterface2引用表达式的标识。
说明:
匿名内部类编译以后,会产生以“外部类名S序号”为名称的class文件,序号以1~n排列,分别代表I~n个圈名内部类。
使用匿名内部类时应该遵循以下原则:

(1)匿名类没有构造方法;
(2)匿名类不能定义静态的成员;
(3)匿名类不能用private、public、protected、static、final、abstract等修饰;

(4)只可以创建一个匿名类实例。

7.6.4 静态内部类

在内部类前添加修饰符static,这个内部类就变为静态内部类了,一个静态内部类可以声明静态成员,但是在非静态内部类中不可以声明静态成员。静态内部类有一个最大的特点,就是不能用外部类的非静态成员,所以静态内部类在程序开发中比较少见。
可以这样认为,普通的内部类对象隐式地在外部保存了一个引用,指向创建它的外部类对象但如果内部类被定义为static,就会有更多的限制。

静态内部类具有以下两个特点:
(1)如果创建静态内部类的对象,不需要创建其外部类的对象;

(2)不能从静态内部类的对象中访问非静态外部类的对象。

代码如下:

public class StaticInnerClass {//创建类
	int x=100;//定义一个整型变量并初始化
	static class Inner{//内部类
	void doitInner(){//方法
	//System. out. printin("外部类"+x);//输出
	}
	public static void main(String args[]){//主方法
	
	
	System. out. println();//换行
	}
}
}

7.6.5 内部类的继承

内部类和其他普通类一样可以被继承,但是继承内部类比继承普通类更复杂,需要设置专门的语法来完成。

代码如下:

public class OutputInnerClass extends ClassA.ClassB{//创建类并继承另一个类
public OutputInnerClass(ClassA a){//方法
a.super();//调用父类构造方法
}
}
class ClassA{//外部类
class ClassB{//内部类
}
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/848028.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号