JavaSE学习笔记——代码块、final关键字、抽象类、模板设计模式、接口、内部类

代码块(初始化块)

1. 作用: 对Java对象进行初始化

2. 程序的执行顺序:
(1)声明成员变量的默认值;
(2)多个代码块依次被执行(同级别下按先后顺序执行);
(3)构造器再对成员进行赋值操作。

3. 语法结构:

修饰符 class 类名{
	{
		语句;
	}
}

4. 静态代码块

  • 代码块只能被static修饰,被static修饰的代码块称为静态代码块,当类被载入时,类属性的声明和静态代码块先后顺序被执行,且 只执行一次。

  • static块用于给类初始化,随着类的加载而加载(初始化static属性或调用static方法)。

(1)例1:

class Person {
	public static int total;
	static {
	        total = 100;//为total赋初值 
	}
	…… //其它属性或方法声明
 }

(2)例2:

public class Person{
	static int age;
	static{ //只能使用静态属性和方法
		age = 1;
		showAge();
	}
	public static void showAge(){
		System.out.println(this.age);
	}
}

5. 注意

非静态代码块:没有static修饰的代码块

  • 可以有输出语句。
  • 可以对成员属性进行初始化操作。
  • 可以调用静态和非静态的变量或方法。
  • 若有多个非静态的代码块,按照从上到下的顺序依次执行。
  • 每次创建对象的时候,都会执行一次,且先于构造器执行。

静态代码块:用static 修饰的代码块

  • 可以有输出语句。
  • 只可以对类属性进行初始化操作。
  • 不可以调用非静态的属性和方法。
  • 若有多个静态的代码块,按照从上到下的顺序依次执行。
  • 静态代码块优先于非静态代码块执行。
  • 静态代码块只执行一次

6. 程序执行顺序

Created with Raphaël 2.2.0 静态代码块(不管new多少对象,只执行一次) 代码块(每new一次对象,执行一次) 构造函数

7. 代码块应用:
静态代码块通常用来初始化类属性,非静态代码块可用于初始化匿名内部类等。
例:匿名内部类

package practice1.test;

public class Person {
	String name;
	int age;
	
	{
		name = "XiaoMing";
		age = 23;
	}
	
	public void showInfo() {
		System.out.println("Person.showInfo");
	}
	
	public void showPersonInfo() {
		System.out.println("Person.showPersonInfo");

	}
}
package practice1.test;

public class Student extends Person{
	String school;

	@Override
	public void showInfo() {
		System.out.println("Student.showInfo");
	}
	
	public void showStudentInfo() {
		System.out.println("Student.showStudentInfo");
	}
	
	public static void main(String[] args) {
		/**
		 * stu继承父类,name和age默认为父类初始值,此时想要改变stu属性的值,
		 * 或想单独输出一些语句,或单独对某些方法重写,但不能影响其他对象实例化时的初始值,可以使用匿名内部类
		 */
		Student stu = new Student() {
			{
				super.age = 22;
				super.name = "LiHua";
			}
			@Override
			public void showInfo() {
				System.out.println("匿名内部类重写的方法" + this.age + this.name);
			}
		};
		
		stu.showInfo();
		
	}
	
}

8. 给出下面程序的输出结果:

package test;

public class StaticDemo{
	static {
		System.out.println("b");
	}
	
	public static void main(String[] args) {
		new StaticCode();
		new StaticCode();
		System.out.println("d");
	}
	
	static {
		System.out.println("c");
	}
}

class StaticCode{
	static {
		System.out.println("a");
	}
}

/* 分析:
 * 执行时先加载主类StaticDemo, 该类中的所有静态代码块随着类的加载也被加载,
 * 因此按照代码块的顺序依次输出 b c, 之后new对象时加载StaticCode类, 输出 a,
 * 最后输出 d。因此输出结果为: b c a d
 */
package test;

public class StaticDemo{
	static {
		System.out.println("e");
	}
	
	public static void main(String[] args) {
		new StaticCode();
		new StaticCode(4);
	}
	
	static {
		System.out.println("c");
	}
}

class StaticCode{
	StaticCode() {
		System.out.println("b");
	}
	
	static {
		System.out.println("a");
	}
	
	{
		System.out.println("c");
	}
	
	StaticCode(int x){
		System.out.println("d");
	}
	
	public static void show() {
		System.out.println("run");
	}
}

//输出结果为: e c a c b c d 

final关键字

1.在Java中声明类、属性和方法时,可使用关键字final来修饰,表示“最终”。

  • final标记的类不能被继承。 提高安全性,提高程序的可读性。
  • final标记的方法不能被子类重写。
  • final标记的变量(成员变量或局部变量)称为常量。名称大写,且只能被显示赋值一次。
  • final标记的成员变量必须在声明的同时或在每个构造方法中或代码块中显式赋值,然后才能使用。
  • static final:全局常量

2.举例

public final class Test{
	public static int totalNumber = 5;
	public final int ID;
	public Test(){
		//隐式赋值,可赋值多次
		ID = ++totalNumber;  //可在构造方法中给final变量赋值
	}
	public static void main(String[] args) {
		Test t = new Test();
		System.out.println(t.ID);		
		final int I = 10;
		final int J;
		J = 20;//显示赋值,只能赋值一次
//		J = 30;  //非法
	}
}

抽象类

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
在这里插入图片描述

abstract关键字

  • 用abstract修饰类时,这个类叫做抽象类;
  • 用abstract修饰方法时,这个方法叫做抽象方法。
    抽象方法:只有方法的声明,没有方法的实现。以 “ ; ” 结束。
    例如:abstract int abstractMethod( int a );
  • 含有抽象方法的类必须被声明为抽象类。
  • 抽象类不能被实例化。抽象类是用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
  • abstract不能修饰属性、私有方法、构造器、静态方法final方法

抽象类的应用

抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
在这里插入图片描述
解决方案
Java允许类设计者指定:父类声明一个方法但不提供实现,该方法的实现由子类提供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。
Vehicle是一个抽象类,有两个抽象方法。

public abstract class Vehicle{
	public abstract double calcFuelEfficiency();	//计算燃料效率的抽象方法
	public abstract double calcTripDistance();	//计算行驶距离的抽象方法
}

public class Truck extends Vehicle{
	public double calcFuelEfficiency( )   { //写出计算卡车的燃料效率的具体方法   }
	public double calcTripDistance( )    {  //写出计算卡车行驶距离的具体方法   }
}

public class RiverBarge extends Vehicle{
	 public double calcFuelEfficiency( ) { //写出计算驳船的燃料效率的具体方法  }
	 public double calcTripDistance( )  {  //写出计算驳船行驶距离的具体方法}

注意:抽象类不能实例化,new Vihicle()是非法的。

思考

  1. 为什么抽象类不可以使用final关键字声明?
    抽象类是用来被继承的,final修饰的类不能被继承。
  2. 抽象类中可以定义构造器吗?
    可以,但不能直接创建抽象类的实例对象,可以继承到子类再调用父类构造器。

练习

编写一个Employee类,声明为抽象类,包含如下三个属性:name,id,salary。提供必要的构造器和抽象方法:work()。对于Manager类来说,他也是员工,还具有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。

package practice1.test;

public abstract class Employee {
	static int start_id = 1;
	String name;
	final int ID;
	double salary;
	
	public Employee(String name, double salary) {
		this.name = name;
		this.ID = start_id++;
		this.salary = salary;
	}
	
	public abstract void work();

}
package practice1.test;

public class CommonEmployee extends Employee{

	public CommonEmployee(String name, double salary) {
		super(name, salary);
	}

	@Override
	public void work() {
		System.out.println("普通员工的工作");
	}
	
	public void getInfo() {
		System.out.println("普通员工 " + "编号:" + this.ID + " 姓名:" + this.name + " 薪水:" + this.salary);
	}
	
}
package practice1.test;

public class Manager extends Employee{
	double bonus;
	
	public Manager(String name, double salary, double bouns) {
		super(name, salary);
		this.bonus = bouns;
	}
	
	@Override
	public void work() {
		System.out.println("管理人员的工作");
	}
	
	public void getInfo() {
		System.out.println("管理人员 " + "编号:" + this.ID + " 姓名:" + super.name + " 薪水:" + this.salary + " 奖金:" + this.bonus);
	}
	
}
package practice1.test;

public class Test1 {
	public static void main(String[] args) {
		CommonEmployee com = new CommonEmployee("小明", 3000);
		Manager man = new Manager("李华", 5000, 2000);
		
		com.work();
		com.getInfo();
		man.work();
		man.getInfo();
	}

}

模板设计模式

  • 在定义功能时,功能内一部分实现是确定的,一部分实现是不确定的,确定部分需要使用不确定部分,这时可以把不确定的部分暴露出去,让子类去实现。
    编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式。
package test;

public class TestGetTime {
	public static void main(String[] args) {
		GetRunningTime grt = new GetTime();
		double time = grt.getTime();
		System.out.println(time);
	}
}
/**
 * 获取程序运行时间的工具类
 * @author 14251
 *
 */
abstract class GetRunningTime{
	public final double getTime() {//不允许子类重写
		double t1 = System.currentTimeMillis();
		runningCode();
		double t2 = System.currentTimeMillis();
		return t2 - t1;
	}
	public abstract void runningCode();
}

class GetTime extends GetRunningTime{

	@Override
	public void runningCode() {
		for(int i=0; i<3000; i++) {
			if(i != 2999) {
				System.out.print(i + ", ");
			}else{
				System.out.println(i);
			}
			if(i % 20 == 19) {
				System.out.println();
			}
		}
	}
	
}

接口

概念

  • 有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
  • 接口(interface)是抽象方法和常量值的定义的集合。
  • 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

接口的实现

class SubClass implements InterfaceA{ }
一个类可以实现多个接口,接口也可以继承其它接口。

接口的特点

  • interface来定义。

  • 所有成员变量都默认是由 public static final 修饰的。

  • 所有方法都默认是由 public abstract 修饰的。

  • 接口没有构造器。

  • 接口采用多层继承机制。

  • 子类只可以继承一个父类,但可以实现多个接口,多个接口用 “ , ” 分隔。

public class Student extends Person implements Interface1, Interface2{
	
	@Override
	public void test1(){
	}
	
	@Override
	public void test2(){
	}
	
}

注意

  • 实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,该类必须定义为抽象类。
  • 接口的主要用途就是被实现类实现(面向接口编程)。
  • 与继承关系类似,接口与实现类之间存在多态性,可以用接口接收类的实例化对象。
    在这里插入图片描述
  • 父类要有稳定的抽象,不能轻易修改父类内容,否则其子类也会由于父类的改动而改动,因此,当真正需要为父类添加某些功能时,可以让父类实现接口,这样不会对子类造成影响。
  • 父类实现的接口,子类也会继承该接口在父类中的实现。
    在这里插入图片描述
  • 一个类可以实现多个接口
interface Runner{ 
	public void run();
	}
interface Swimmer{
	public double swim();
	}
class Creator{
	public int eat(){}
	} 
class Man extends Creator implements Runner, Swimmer{
	public void run(){}
	public double swim(){}
	public int eat(){}
}
  • 与继承关系类似,接口与实现类之间存在多态性
public class Test{
	public static void main(String args[]){
		Test t = new Test();
		Man m = new Man();
		t.m1(m);
		t.m2(m);
		t.m3(m);
	}
	public String m1(Runner f){ 
		f.run(); 
	}
	public void  m2(Swimmer s){
		s.swim();
	}
	public void  m3(Creator a){
		a.eat();
	}
}
  • 如果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类
  • 接口也可以继承另一个接口,使用extends关键字(因为是接口继承接口,因此子接口不需要实现父接口方法)。
interface MyInterface{
	String s=“MyInterface”;
	public void absM1();
}
interface SubInterface extends MyInterface{
	public void absM2();
}
public class SubAdapter implements SubInterface{
	public void absM1(){
		System.out.println(“absM1”);
	}
	public void absM2(){
		System.out.println(“absM2”);
	}
}

实现类SubAdapter必须给出接口SubInterface以及父接口MyInterface中所有方法的实现。

练习

模拟电脑主板工作方式:

package test;
/**
 * 分析: 主板不知道未来会出现什么样的芯片插入到主板上, 因此只能预留出符合一定条件的插槽, 
 * 日后如果有新的芯片需要插到主板上, 只需要让该芯片满足主板预留插槽的条件即可。
 * 
 * 程序中用PCI接口代表主板预留卡槽需要满足的条件, 因此传入到主板中的对象应为PCI接口的子类,
 * 并且所有设备都要实现PCI接口。
 * 
 * 思想: 有关联的几个功能之间(NetCard, SoundCard), 如果没有共同继承同一个接口(PCI), 
 * 那么在接收这几个功能的方法中(MainBoard)要添加许多语句, 尤其是添加新设备的功能时。
 * 因此共同实现接口, 使用对象的多态性完成。
 * 
 * 假设A、B有共同的功能a、b, 则将a、b抽取到接口I中, 让A、B实现接口I, 
 * 再创建一个类C, 在C内新建方法用于接收I的子类, 调用相应方法。
 * 
 * 
 * @author 14251
 *
 */
interface PCI{
	public abstract void run();
	public abstract void close();
}

class MainBoard{
	public void mainBoardRun() {
		System.out.println("MainBoard Run");
	}
	//若没有继承接口, 每新添加一个设备就要多两个方法
	/*
	public void runNetCard(NetCard n) {
		if(n != null) {
			n.run();
		}else {
			System.out.println("error");
		}
	}
	
	public void closeNetCard(NetCard n) {
		if(n != null) {
			n.close();
		}else {
			System.out.println("error");
		}
	}
	*/
	public void runEquipments(PCI p) {
		if(p != null) {
			p.run();
		}else {
			System.out.println("error");
		}
	}
	public void closeEquipments(PCI p) {
		if(p != null) {
			p.close();
		}else {
			System.out.println("error");
		}
	}
}

class NetCard implements PCI{

	@Override
	public void run() {
		System.out.println("NetCard Run");
	}

	@Override
	public void close() {
		System.out.println("NetCard Close");
	}
	
}

class SoundCard implements PCI{
	
	@Override
	public void run() {
		System.out.println("SoundCard Run");
	}

	@Override
	public void close() {
		System.out.println("SoundCard Close");
	}
	
}

public class Computer {
	public static void main(String[] args) {
		MainBoard mb = new MainBoard();
		mb.mainBoardRun();
		mb.runEquipments(new NetCard());
		mb.runEquipments(new SoundCard());
		mb.closeEquipments(new NetCard());
		mb.closeEquipments(new SoundCard());
	}
}
/*MainBoard Run
NetCard Run
SoundCard Run
NetCard Close
SoundCard Close*/

工厂方法(FactoryMethod)

1. 概念:
FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。

2. 举例:
在这里插入图片描述
在这里插入图片描述

//接口BWM
package BWM;

public interface BWM {
	void showInfo();

}
//接口BWMFactory
package BWM;

public interface BWMFactory {
	BWM makeCar();

}
package BWM;

public class BWM3 implements BWM{

	@Override
	public void showInfo() {
		System.out.println("This is BWM3");
	}

}
package BWM;

public class BWM5 implements BWM{

	@Override
	public void showInfo() {
		System.out.println("This is BWM5");
	}

}
package BWM;

public class BWM7 implements BWM{

	@Override
	public void showInfo() {
		System.out.println("This is BWM7");
	}

}
package BWM;

public class BWM3Factory implements BWMFactory{

	@Override
	public BWM makeCar() {
		System.out.println("BWM3 is maked");
		return new BWM3();
	}

}
package BWM;

public class BWM5Factory implements BWMFactory{
	
	@Override
	public BWM makeCar() {
		System.out.println("BWM5 is maked");
		return new BWM5();
	}
	
}
package BWM;

public class BWM7Factory implements BWMFactory{
	
	@Override
	public BWM makeCar() {
		System.out.println("BWM7 is maked");
		return new BWM7();
	}
	
}
package BWM;

public class MakeCar {
	public static void main(String[] args) {
		BWM bwm3 = new BWM3Factory().makeCar();
		BWM bwm5 = new BWM5Factory().makeCar();
		BWM bwm7 = new BWM7Factory().makeCar();
		
		bwm3.showInfo();
		bwm5.showInfo();
		bwm7.showInfo();
	}
	
}

内部类

成员内部类

  • 在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。将内部类理解为成员方法即可。
  • 内部类的名称不能与包含它的外部类的名称相同,不属于同一个外部类的内部类名称可以相同。
  • 一个类可以定义多个内部类。
  • 内部类可以直接访问外部类的成员变量与方法,包括私有成员, 因为它是外部类的成员,省略了外部类名 . this . 成员。
  • 外部类要访问内部类中的成员要建立内部类对象,static成员可用内部类名调用。
  • 在其他类中创建某个类的内部类对象 (内部类非私有)
    外部类名.内部类名 变量名 = 外部类对象.内部类对象;
    OuterClass.InnerClass oi = new OuterClass().new InnerClass();
  • 可以声明为abstract类 ,可以被其它的内部类继承。内部类的最大用处是实现多重继承。
package test;
//成员内部类
public class TestInnerClass {
	public static void main(String[] args) {
		OuterClass oc = new OuterClass();
		oc.useInnerMethod();
		//直接调用内部类方法
		//OuterClass.InnerClass oi = new OuterClass().new InnerClass();
		//oi.showInfo();
	}
}

class OuterClass{
	private int num = 4;
	private int temp = 7;
	
	class InnerClass{
		int num = 5;
		void showInfo() {
			int num = 6;
			System.out.println(temp);//内部类直接访问外部类成员, OuterClass.this.temp, 7
			System.out.println(num);//6
			System.out.println(OuterClass.this.num);//指定访问外部类的num, 4
			System.out.println(this.num);//5
		}
	}
	
	public void useInnerMethod() {
		InnerClass in = new InnerClass();//外部类调用内部类成员时要实例化对象
		in.showInfo();
	}
	
}

静态成员内部类

  • 可以声明为private或protected;
  • 可以声明为static, 此时内部类就具有static的特性。
    (1)当内部类被static修饰后,只能访问外部类中的static成员。
    (2)若内部类中定义了static成员,则该内部类也必须被声明为static的。
    (3)若外部类中的static方法想要访问内部类,则该内部类必须是static的。
    (4)在外部其它类中,如何直接访问静态内部类中的非静态成员? new OuterClass.InnerClass().function();
    (5)在外部其它类中,如何直接访问静态内部类中的静态成员? OuterClass.InnerClass.function();
package test;
//静态成员内部类
public class TestStaticInnerClass {
	public static void main(String[] args) {
		OuterClass.useInnerMethod();
	}
}

class OuterClass{
	
	static class InnerClass{
		public void show() {
			System.out.println("InnerClass Method");
		}
		private static void showInfo() {
			System.out.println("InnerClass Static Method");
		}
	}
	public static void useInnerMethod() {
		new InnerClass().show();
		InnerClass.showInfo();
	}
}

内部类的使用场景:

  • 在描述事物时,事物的内部还有事物,该事物用内部类来描述。继承是树形结构,接口是功能扩展,内部类是包含关系。
    当类A需要直接访问类B的成员时(不通过创建B的对象),可以将A设计成B的内部类,之后将A私有化,对外部其他类提供访问方法。例如人体与各个器官之间,属于包含关系,并且各个器官应该能够直接访问人体成员,可以将各个器官类设计为人体类的内部类,再将器官类私有化,对外部其他类提供访问方法即可。

局部内部类

  • 局部内部类不可以使用权限修饰符修饰, 因为权限修饰符只能修饰类的成员属性和方法。
  • 局部内部类不能使用static修饰, 因为static只能用于修饰类的成员属性和方法,由于局部内部类不能被声明为static的,因此局部内部类中不能有static方法(由下一条可知也不能由static属性)。
  • 局部内部类访问局部变量时,该变量只能为final的(static final也不行), jdk1.8之后可以省略不写final,编译器自动添加。
  • 局部内部类可以直接访问类的成员属性和成员方法。
package test;

public class TestLocalInnerClass {
	public static void main(String[] args) {
		new OuterClass().method(2);
		/*
		 * Method Inner 1 2
		 * LocalClass
		 * ShowInfo
		*/
		new OuterClass().method(3);//形参声明为final, 为什么可以在传入2之后又传入3?
		//因为传入2后,当方法执行完毕后,就释放内存,不存在二次赋值的情况, 
		//但不能在方法内部对传入的实参a进行再赋值。
	}
}

class OuterClass{
	private String name = "LocalInnerClass";
	public void showInfo() {
		System.out.println("ShowInfo");
	}
	public void method(int a) {
//		a++;//错误, final常量不能二次赋值
		//final int a, 自动添加。由于是局部变量, 调用结束后就释放, 
		//因此可以调用多次方法, 传入不同的实参, 而不会出现final常量只能赋值一次的情况
		int x = 1;//final int x = 1; jdk1.8之后可以不写final, 编译器自动添加final
		class Inner{
//			private int num = 0;//可以有自己的成员属性
			public void show(){
				System.out.println("Method Inner " + x + " " + a);//只能访问final类型的局部变量
				System.out.println(name);//局部内部类可以直接调用外部属性, 等价于下面写法
//				System.out.println(OuterClass.this.name);
				showInfo();//局部内部类可以直接调用外部方法
			}
		}
		new Inner().show();
	}
	
}

匿名内部类

  • 匿名内部类:实质上是内部类的简写,只能定义在方法内。
  • 前提:内部类必须继承了父类或实现了接口才能改写成匿名内部类。
  • 格式:new 父类或接口 ( ) { 实现父类或接口或自己的内容 };
  • 注意:匿名内部类其实是其所继承的父类或实现的接口的子类对象 可以理解为有内容的子类对象。
  • 匿名内部类中定义的方法最好不要超过2个, 因此其父类或接口中的抽象方法最好不要超过2个。
  • 由于匿名内部类就是子类, 因此可以有自己的成员属性和特有的成员方法。
  • 由于内部类中有static成员时(属性和方法),内部类要声明为static的,但匿名内部类依托于方法而存在,属于局部内部类,不属于类的成员,因此不能使用static修饰,所以匿名内部类中不能有静态方法和属性。

1. 基本用法:

package test;

interface Inter{
	void show();
	void showInfo();
}

abstract class Father{
	public abstract void test();
}

public class TestAnonymousClass {
	public static void main(String[] args) {
		new AnonymousClass().method_1();
		new AnonymousClass().method_2();
	}
}

class AnonymousClass{
	public void method_1(){
		new Inter() {
			public void show() {//实现接口或父类方法
				System.out.println("show_1");
			}
			public void showInfo() {
				System.out.println("showInfo_1");
			}
			public void ownMethod() {//可以实现自己特有的方法
				System.out.println("ownMethod_1");
			}
		}.show();//.showIndo()或.ownMethod(), 直接调用方法
	}
	public void method_2() { 
		//能否一次调用两个方法?
		Inter in = new Inter() {//多态, 建立对象
			public void show() {
				System.out.println("show_2");
			}
			public void showInfo() {
				System.out.println("showInfo_2");
			}
			public void ownMethod() {
				System.out.println("OwnMethod_2");
			}
		};
		in.show();
		in.showInfo();
//		in.ownMethod();//父类Inter中没有ownMethod()方法, 编译失败
	}
}

class AnonymousInnerClass{
	public void method_3() {
		int x = 1;//final int x = 1;
		new Father() {
			private String str = "匿名内部类的成员属性";
			public void test() {
				System.out.println("method_3" + str + x);
			}
		};
	}
}

2. 补全代码:

package test.practice;

interface Inter{
	void method();
}

class Anonymous{
	//补足代码, 用匿名内部类完成
	static Inter function() {
		 return new Inter() {
			public void method() {
				System.out.println("method");
			}
		};
	}
}

public class AnonymousPractice {
	public static void main(String[] args) {
		Anonymous.function().method();//已知
	}
}

3. 形参是父类或接口时,传入的可以是匿名内部类:

package test.practice;

interface Inner{
	void method();
}
public class MethodAnonymousClass {
	public static void main(String[] args) {
		show(new Inner() {
			public void method() {
				System.out.println("Inner method run");
			}
		});//注意书写
	}
	
	public static void show(Inner in) {
		in.method();
	}
	
}

4. 使用匿名内部类直接调用所需方法,不需要再创建类的对象:

package test.practice;

public class ObjectAnonymousClass {
	public static void main(String[] args) {
		//使用匿名内部类直接调用所需方法, 不需要再创建类的对象
		new Object() {//Object类是根父类
			public void method() {//所需方法实现
				System.out.println("Object method");
			}
		}.method();
		//使用Object匿名内部类直接调用方法时, 要避免创建父类引用,
		//因为父类中可能没有子类定义的方法, 造成编译失败。
//		Object o = new Object() {
//			public void method() {
//				System.out.println("Object method");
//			}
//		};
//		o.method();//Object类中没有method方法, 编译失败
	}
	
}

练习

有三个类,假设为A、B、C,B和C中分别有一个print函数用来打印信息,现在A想同时继承B和C,并重写B和C的print方法,编写程序。

方法1:B和C都构造成A的内部类

package abc;

public class ATest {
	public static void main(String[] args) {
		A a = new A();
		a.testB();
		a.testC();
	}

}

class A{

	public void testB() {
		new InnerB().printB();
	}
	
	public void testC() {
		new InnerC().printC();
	}
	
	class InnerB extends B{
		@Override
		public void printB() {
			System.out.println("InnerB");
		}
	}
	
	class InnerC extends C{
		@Override
		public void printC() {
			System.out.println("InnerC");
		}
	}
}

class B{
	public void printB() {
		System.out.println("B");
	}
}

class C{
	public void printC() {
		System.out.println("C");
	}
}

方法2:B被A继承,C构造成A的内部类

package abc;

public class ATest {
	public static void main(String[] args) {
		A a = new A();
		a.printB();
		a.testC();
	}

}

class A extends B{
	
	@Override
	public void printB() {//调用内部类InnerB
		System.out.println("InnerB");
	}
	
	public void testC() {//调用内部类InnerC
		new InnerC().printC();
	}
	
	class InnerC extends C{
		@Override
		public void printC() {
			System.out.println("InnerC");
		}
	}
}

class B{
	public void printB() {
		System.out.println("B");
	}
}

class C{
	public void printC() {
		System.out.println("C");
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值