封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类。
public class daw {
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 sge {
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);//输出信息
}
}
运行结果:
public class cde {
public static void main(String[] args) {//主方法
Cook2 cook=new Cook2();//创建厨师类的对象
System.out.println("**请让厨师为我做一份香辣肉丝。***");//输出
cook.cooking("香辣肉丝");//厨师烹饪香辣肉丝
System.out.println("**你们的厨师叫什么名字?***");//输出
System.out.println(cook.name);//厨师回答自己的名字
System.out.println("**请让厨师给我切一点葱花。***");//输出
cook.cutOnion();//厨师去切葱花
}
}
class Cook2{//创建类
String name;//厨师的名字
public Cook2(){//定义方法
this.name="Tom Cruise";//厨师的名字叫Tom Cruise
}
void cutOnion(){//厨师切葱花
System.out.println(name+"切葱花");//输出信息
}
private void washVegetables(){//厨师洗蔬菜
System.out.println(name+"洗蔬菜");//输出信息
}
void cooking(String dish){//厨师烹饪顾客点的菜
washVegetables();//调用方法
cutOnion();//调用方法
System.out.println(name+"开始烹饪"+dish);//输出信息
}
}
运行结果:
public class Restaurant4 {
private Cook2 cook = new Cook2();//餐厅封装的厨师类
private void takeOrder(String dish) {//下单
cook.cooking(dish);//通知厨师做菜
System.out.println("您的菜做好了,请慢用。");
}
public String saySorry() {//拒绝顾客请求
return "抱歉,餐厅不提供此项服务。";
}
public static void main(String[] args) {
Restaurant4 water = new Restaurant4();//创建餐厅对象,为顾客服务
System.out.println("**请让厨师为我做一份香辣肉丝。***");
water.takeOrder("香辣肉丝");//服务员给顾客下单
System.out.println("**你们的厨师叫什么名字?");
System.out.println(water.saySorry());//服务员给顾客满意的答复
System.out.println("**请让厨师给我切一点葱花。***");
System.out.println(water.saySorry());//服务员给顾客满意的答复
}
}
运行结果:
7.2类的继承:继承在面向对象开发思想中是一个非常重要的概念,它使整个程序具有一定的弹性,在程序中复用已经定义完善的类不仅可以减少软件开发周期,还可以提高软件的可维护性和可扩展性。
继承其基本思想是基于某父类的扩展,制定出一个新的子类,子类可以继承父类原有的属性和方法,也可以增加原来父类所不具备的属性和方法,或者直接重写父类中的某些方法。
1.extends关键字
在java中,让一个类继承另一个类,用extends关键字
child extends parents//子类继承父类
注意:java中的类只支持单继承,即一个子类只能继承一个父类,类似下面的代码是错误的:
child extends parents1,parent2{
//错误的继承语法
}
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();//子类可以直接使用父类方法
}
}
运行结果:
从这个结果可以看出,Pad类继承了Computer类之后,虽然没有定义任何成员方法,但仍然可以调用父类的方法,这个方法就是从父类那里继承过来的。
7.2.2方法的重写继承并不只是扩展父类的功能,还可以重写父类的成员方法。重写(还可以称为覆盖)就是在子类中将父类的成员方法的名称保留。重新编写成员方法的实现内容,更改成员方法的存储权限,或是修改成员方法的返回值类型 (重写父类成员方法的返回值是基于J2SE 5.0版本以上的编译器提供的新功能)。
在继承中还有一种特殊的重写方式,子类与父类的成员方法返回值、方法名称、参数类型及个数完全相同,唯一不同的是方法实现内容,这种特殊重写方式被称为重构。
注意:当重写父类的方法时,修改方法的修饰权限只能从小的范围到大的范围改变,例如,父类中的doSomething()方法的修饰权限为protected,继承后子类中的方法doSomething()的修饰权限只能修改为public,不能修改为private。
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();//调用父类方法,实现子类重写的逻辑
}
}
运行结果:
注意:在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());//调用子类的方法并输出
}
}
运行结果:
注意:如果在子类构造方法中使用类似super()构造方法,其他初始化代码只能写在super()之后,不能写在前面,否则会报错。
7.2.3Object类——所有类的父类在java中,所有的类都直接或间接继承了java.lang.Object类。Object类是所有类的父类,是java类层中的最高层类。
注意:Object类中的getClass()、notify()、notifyAll()、wait()等方法不能被重写,因为这些方法被定义为final类型。
1.getClass()方法
getClass()方法是Object类定义的方法,它会返回对象执行时的Class实例,然后使用此实例调用getName ()方法可以取得类的名称。
getClass().getName();
可以将getClass()方法与toString()方法联合使用。
2.toString()方法
toString()方法的功能是将一个对象返回为字符串形式,它会返回一个String实例。在实际的应用中通常重写toString()方法。
public class Objectlnstance {
public String toString(){//重写toString()方法
return "在"+getClass().getName()+"类中重写toString()方法";//返回值
}
public static void main(String[] args) {//主方法
System.out.println(new Objectlnstance());//调用方法并输出,打印本类对象
}
}
运行结果:
3.equals()方法
比较两个对象的实际内容
package java7;
public class OverWriteEquals {
public static void main(String[] args) {//主方法
String s1="123";//实例化两个对象,内容相同
String s2="123";//实例化对象
System.out.println(s1.equals(s2));//使用equals()方法
OverWriteEquals v1=new OverWriteEquals ();//实例化两个V类对象
OverWriteEquals v2=new OverWriteEquals ();//实例化对象
System.out.println(v1.equals(v2));//使用equals()方法
}
}
运行结果:
7.3类的多态类的多态性指“一种定义,多种实现”,类的多态性可以从两方面 体现:方法的重载,类的上下转型。
方法的重载:重载(不需要继承):返回参数不同、传入参数不同、 方法名相同
package java7;
public class OverLoadTest {
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
运行结果:
注意:虽然在方法的重载中可以使两个方法的返回类型不同,但只有返回类型不同不足以区分两个方法的重载,还需要通过参数的个数以及参数的类型来设置。
向上转型:子类转变成父类类型
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);//调用父类方法{
}
}
无运行结果
向下转型:父类转变成子类 使用强制转换
package java7;
class Quadrangle{//父类
public static void draw(Quadrangle q){//父类方法
//SomeSentence
}
public static void main(String[] args) {//主方法
draw(new Quadrangle());//调用方法并传入子类对象
Quadrangle q=new Quadrangle();//将平行四边形对象看作是四边形对象,称为向上转型操作
Quadrangle p=q;//向下转型
}
}
运行结果:
7.3.4instanceof关键字当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生classcastException异常,所以在执行向下转型之前需要养成一个良好的习惯,就是判断父类对象是否为子类对象的实例。
myobject instanceof ExampleClass
myobject:某类的对象引用。
ExampleClass:某个类
使用instanceof操作符的表达式返回值为布尔值。
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.4抽象类与接口抽象类与抽象方法:在java中设置抽象类不可以实例化对象。
[权限修饰符] 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); //输出信息
}
}
package java7;
import hello.java.Market;
import hello.java.TaobaoMarket;
import hello.java.WallMarKet;
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();//调用方法
}
}
运行结果:
7.4.2接口的声明及实现接口是抽象类的延申,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。即全部都是抽象方法。
[修饰符]interface 接口名[extends 父接口名列表]{
[public] [static] [final]常量;
[public] [abstract] 方法;
}
一个类实现一个接口可以使用implements关键字
public class Parallelogram extends Quadrangle implements drawTest{
....//
}
说明:在接口中定义的任何变量都自动是static和final的,因此,在接口中定义变量时,必须进行初始化,而且,实现接口的子类不能对接口的变量重新赋值。
package java7;
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中不允许多重继承,但使用接口就可以实现多重继承,因为一个类可以同时实现多个接口。
class 类名 implements 接口1,接口2,接口3...接口n
public interface IFather {//定义一个接口
void smoking();//抽烟的方法
void goFishing();//钓鱼方法
}
public interface IMother {//定义一个接口
void watchTV();//看电视的方法
void cooking();//做饭的方法
}
package java7;
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("我喜欢抽烟");//输出信息
}
public void goFishing() {//重写方法
// TODO Auto-generated method stub
System.out.println("我喜欢钓鱼");//输出信息
}
public static void main(String[] args) {//主方法
// TODO Auto-generated method stub
IFather father=(IFather) new Me();//进行向上转型
System.out.println("爸爸的爱好:");//输出信息
((Me) father).smoking();//调用方法
((Me) father).goFishing();//调用方法
Me mather=new Me();//进行向上转型
System.out.println("妈妈的爱好:");//输出信息
mather.cooking();//调用方法
mather.watchTV();//调用方法
}
}
运行结果:
7.4.4 区分抽象类与接口
抽象类和接口都包含可以由子类继承实现的成员,但抽象类是对根源的抽象,而接口是对动作的抽象。抽象类的功能要远超过接口,那为什么还要使用接口呢?这主要是由于定义抽象类的代价高(因为每个类只能继承一个类,在这个类中,必须继承或编写出其子类的所有共性,因此,虽然接口在功能上会弱化许多,但它只是针对一个动作的描述,而且可以在一个类中同时实现多个接口,这样会降低设计阶段的难度。
7.5 访问控制
前面多次提到了public、private、包等关键字或者概念,这些都是用来控制类、方法或者变量的访问范围的,Java中主要通过访问控制符、类包和final关键字对类、方法或者变量的访问范围进行控制。
7.5.1 访问控制符
面向对象的几个基本特性,其中包括封装性,封装实际上有两方面的含义:把该隐藏的隐藏起来、把该暴露的暴露出来,这两个方面都需要通过使用Java提供的“访问控制符”来实现。
Java中的访问控制符主要包括public、protected、private和default(缺省)等4种,这些控制符控制着类和类的成员变量以及成员方法的访问权限。
表7.2中描述了public、protected、private和default(缺省)这4种访问控制符的访问权限。
7.5.2Java类包
当我们开发项⽬的时候,会⽤到很多的类文件,这样就不⽅便管理
我们可以通过包对类进⾏管理分类,也可以避免重名的问题,⼀种类型的java类放在⼀个包⾥⾯,或者⼀个模块的java类放在⼀个包⾥⾯,不同包⾥⾯可以包含同名的类,通过包类区分。
7.5.3 final 关键字
1.final类
定义为fǐnal的类不能被继承。
如果希望一个类不允许任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类设置为fǐnal形式。fǐnal类的语法如下:
final class类名()
如果将某个类设置为final形式,则类中的所有方法都被隐式地设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。
final class FinalClass {
int a = 3;
void doit() {
}
public static void main(String args[]) {
FinalClass f = new FinalClass();
f.a++;
System.out.println(f.a);
}
}
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() { // 在子类中定义一个doit()方法
System.out.println("子类.doit()");
}
// final void doit2(){ //final方法不能覆盖
// System.out.println("子类.doit2()");
// }
public void doit3() {
System.out.println("子类.doit3()");
}
}
public class FinglMethod {
public static void main(String[] args) {
Sub s = new Sub(); // 实例化
s.doit(); // 调用dot()方法
Parents p = s; // 执行向上转型操作
// p.doit(); //不能调用private方法
p.doit2();
p.doit3();
}
}
运行结果:
3. final 变量
final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使用如下语句:
final double PI=3.14;
当在程序中使用PI这个常量时,它的值就是3.14,如果在程序中再次对定义为final的常量赋值,编译器将不会接受。
final关键字定义的变量必须在声明时对其进行赋值操作。final除了可以修饰基本数据类型的常量,还可以修饰对象引用。由于数组也可以被看作一个对象来引用,所以final可以修饰数组。一旦一个对象引用被修饰为final后,它只能恒定指向一个对象,无法将其改变以指向另一个对象。一个既是static又是final的字段只占据一段不能改变的存储空间。为了深入了解 final关键字,来看下面的实例。
package java7;
import static java.lang.System.out;
import java.util.Random;
class Test {
int i = 0;
}
public class FinalData {
static Random rand = new Random();
private final int VALUE_1 = 9; // 声明一个final常量
private static final int VALUE_2 = 10; // 声明一个final、static常量
private final Test test = new Test(); // 声明一个final引用
private Test test2 = new Test(); // 声明一个不是final的引用
private final int[] a = { 1, 2, 3, 4, 5, 6 }; // 声明一个定义为final的数组
private final int i4 = rand.nextInt(20);
private static final int i5 = rand.nextInt(20);
public String toString() {
return i4 + " " + i5 + " ";
}
public static void main(String[] args) {
FinalData data = new FinalData();
//data.test = new Test();
// 可以对指定为final的引用中的成员变量赋值
// 但不能将定义为final的引用指向其他引用
//data.value2++;
// 不能改变定义为final的常量值
data.test2 = new Test(); // 可以将没有定义为final的引用指向其他引用
for (int i = 0; i < data.a.length; i++) {
// a[i]=9;
// 不能对定义为final的数组赋值
}
out.println(data);
out.println("data2");
out.println(new FinalData());
out.println(data);
}
}
运行结果:
package java7;
import java.util.Random;
import static java.lang.System.out;
public class FinalStaticData {
private static Random rand = new Random();//实例化一个Random类对象
//随机产生0~10之间的随机数赋予定义为final的a1
final int a1 = rand.nextInt(10);
//随机产生0~10之间的随机数赋予定义为static final的a2
private static final int a2 = rand.nextInt(10);
public static void main(String[] args) {
FinalStaticData fdata = new FinalStaticData(); //实例化一个对象
//调用定义为final的a1
out.println("重新实例化对象调用a1的值:" + fdata.a1);
//调用定义为static final的a2
out.println("重新实例化对象调用a1的值:" + fdata.a2);
//实例化另一个对象
FinalStaticData fdata2 = new FinalStaticData();
out.println("重新实例化对象调用a1的值:" + fdata2.a1);
out.println("重新实例化对象调用a2的值:" + fdata2.a2);
}
}
运行结果:
7.6 内部类
1.成员内部类
成员内部类看起来像是外部类的一个成员,所以内部类可以拥有private、public等访问权限修饰。也可以用static来修饰。成员内部类分为:
静态成员内部类:使用static修饰类;
非静态成员内部类:未用static修饰类,在没有说明是静态成员内部类时,默认成员内部类指的就是非静态成员内部类;
public class OuterClass {
innerClass in = new innerClass(); // 在外部类实例化内部类对象引用
public void ouf() {
in.inf(); // 在外部类方法中调用内部类方法
}
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();
}
}
public class InterfaceInner {
public static void main(String args[]) {
OuterClass2 out = new OuterClass2 (); // 实例化一个OuterClass2对象
// 调用dot()方法,返回一个OutInterface接口
OutInterface outinter = out.doit();
outinter.f(); // 调用f()方法
}
}
class OuterClass2 {
// 定义一个内部类实现OutInterface接口
private class InnerClass implements OutInterface {
InnerClass(String s) { // 内部类构造方法
System.out.println(s);
}
public void f() { // 实现接口中的f()方法
System.out.println("访问内部类中的f()方法");
}
}
public OutInterface doit() { // 定义一个方法,返回值类型为OutInterface接口
return new InnerClass("访问内部类构造方法");
}
}
运行结果:
public class TheSameName {
private int x;
private class Inner {
private int x = 9;
public void doit(int x) {
x++; //调用的是形参x
this.x++; //调用内部类的变量x
TheSameName.this.x++; //调用外部类的变量x
}
}
}
7.6.2局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
interface OutInterface2 { // 定义一个接口
}
class OuterClass3 {
public OutInterface2 doit(final String x) { // doit()方法参数为final类型
// 在doit()方法中定义一个内部类
class InnerClass2 implements OutInterface2 {
InnerClass2(String s) {
s = x;
System.out.println(s);
}
}
return new InnerClass2("doit");
}
}
7.6.3匿名内部类
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
interface OutInterface2 { // 定义一个接口
}
class OuterClass4 {
public OutInterface2 doit() { // 定义doit()方法
return new OutInterface2() { // 声明匿名内部类
private int i = 0;
public int getValue() {
return i;
}
};
}
7.6.4静态内部类
静态内部类可以使用 static 关键字定义,静态内部类我们不需要创建外部类来访问,可以直接访问它。
public class StaticInnerClass {
int x = 100;
static class Inner {
void doitInner() {
// System.out.println("外部类"+x);
}
public static void main(String args[]) {
System.out.println();
}
}
}
7.6.5内部类的继承
内部类和其他普通类一样,同样可以被继承,这样给本来就十分灵活的内部类增加了更好的结构性和代码复用性。只是内部类的继承和普通类有一些不同之处,是在使用时需要多加注意的。因为内部类在创建时需要外部类的引用,所以在内部类的继承上也需要外部类的协助。
public class OutputInnerClass extends ClassA.ClassB { // 继承内部类ClassB
public OutputInnerClass(ClassA a) {
a.super();
}
}
class ClassA {
class ClassB {
}
}



