Java课件笔记:sec1

sec1

1.函数

函数声明

2.动态规划

(1)动态规划
动态规划是实现递归程序的一种通用方法,其基本思想是递归地将一个复杂的问题划分为若干个简单的子问题;存储这些子问题的答案;最后,使用存储的答案来解决原始问题。通过只解决每个子问题一次(而不是一遍又一遍),该技术避免了运行时间中潜在的指数放大。
(2)自上而下的动态规划
在自顶向下的动态编程中,我们存储或缓存所解决的每个子问题的结果,以便下次需要解决相同的子问题时,可以使用缓存的值,而不是从头开始解决子问题。
在这里插入图片描述
(3)自底向上的动态规划。
在自底向上的动态规划中,我们计算所有子问题的解,从最简单的子问题开始,逐步建立越来越复杂子问题的解。

public static long bonacci(int n) {
	long[] f = new long[n+1];
	f[0] = 0;
	f[1] = 1;
	for (int i = 2; i <= n; i++)
		f[i] = f[i-1] + f[i-2];
	return f[n];
}

(4)最大共同子序列
给定两个字符串x和y,我们希望计算它们的(LCS)。如果我们从x中删除了一些字符,从y中删除了一些字符,得到的两个字符串是相等的,那么我们将得到的字符串称为公共子序列。LCS的问题是找到一个尽可能长的两个字符串的公共子序列。例如,GGCACCACG和ACGGCGGATACG的LCS是GGCAACG,一个长度为7的字符串。
现在我们描述一个递归公式,它使我们能够找到两个给定字符串s和t的LCS。让m和n分别是s和t的长度,用符号s[i::m)表示从索引i开始的s的下标, t[j::n)表示从索引j开始的t的下标。
如果s和t以相同的字符开头,那么s和t的LCS包含第一个字符。因此,我们的问题可以归结为寻找下标为s[1::m)和t[1::n]的LCS。如果s和t以不同的字符开头,那么这两个字符不能都是公共子序列的一部分,因此可以安全地丢弃其中一个。在这两种情况下,问题都归结为寻找两个字符串从s[0::m)和t[1::n)或s[1::m)和t[0::n]的LCS。
一般来说,如果我们让opt[i][j]表示下标s[i::m]和t[j::n]的LCS长度,那么下面的递归式成立:

opt[i][j] = 0                                    if i = m or j = n
= opt[i+1][j+1] + 1                              if s[i] = t[j]
= max(opt[i][j+1], opt[i+1][j])                  otherwise

自底向上动态规划方法:
最终的挑战是恢复lcs本身,而不仅仅是它的长度。关键思想是回溯动态规划算法的步骤,重新发现从opt[0][0]到opt[m][n]的选择路径(图中用灰色突出显示)。
为了确定导致opt[i][j]的选择,我们考虑了三种可能性:
(i)字符s[i]与t[j]匹配。在这种情况下,我们必须选择op[i][j] = opt[i+1][j+1] +1, LCS中的下一个字符是s[i]。我们继续从opt[i+1][j+1]回溯。
(ii)LCS不包含s[i]。在这种情况下,opt[i][j] = opt[i+1][j],我们继续从opt[i+1][j]回溯。
(iii)LCS不包含t[j]。在本例中,opt[i][j] = opt[i][j+1],我们继续从opt[i][j+1]回溯。
在这里插入图片描述

import java.util.Scanner;

public class lcs{
	public static String lcs(String x,String y) {
		int m=x.length(),n=y.length();
		int[][]opt=new int[m+1][n+1];
		for(int i=m-1;i>=0;i--) {
			for(int j=n-1;j>=0;j--) {
				if(x.charAt(i)==y.charAt(j)) 
					opt[i][j]=opt[i+1][j+1]+1;
				else 
					opt[i][j]=Math.max(opt[i+1][j], opt[i][j+1]);
			}
		}
		String lcs="";
		int i=0,j=0;
		while(i<m&&j<n) {
			if(x.charAt(i)==y.charAt(j)) {
				lcs+=x.charAt(i);
				i++;
				j++;
			}
			else if(opt[i+1][j]>=opt[i][j+1])
				i++;
			else
				j++;
		}
		return lcs;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str1=null,str2=null;
		Scanner in = new Scanner(System.in);
		str1=in.next();
		str2=in.next();
		in.close();
		int x=lcs(str1,str2).length();
		if(x!=0)
			System.out.println(x);
		else
			System.out.println(-1);
		}
}

3.面向对象编程(OOP)

(1)类和实例
类:类是同类对象的定义。换句话说,类是一个蓝图、模板或原型,它定义并描述所有同类对象的共同静态属性和动态行为。
实例:实例是类的特定项的实现。换句话说,实例是类的实例化。类的所有实例都具有类似的属性,如类定义中所述。“对象”一词通常指实例。但是它经常被松散地使用,并且可以引用类或实例。
(2)类
一个类可以被可视化为一个三室的盒子,换句话说,类将静态属性(数据)和动态行为(对数据进行操作的操作)封装在一个框中。
在这里插入图片描述
(i)类名(或标识符):标识类,数据成员和成员函数统称为类成员。
注意:类名的第一个字母大写,且不要用中文。
在这里插入图片描述
(ii)数据成员或变量(或属性、状态、字段):包含该类的静态属性。
(iii)成员函数(或方法、行为、操作):包含类的动态操作。
(iv)以下图片展示了该班级学生的两个实例,以“paul”和“peter”命名。
在这里插入图片描述
我们使用关键字类来定义类,实例:

public class Circle { // class name
	public double radius; // variables
	public String color;
	
	public double getRadius() { ...... } // methods
	public double getArea() {}...... }
}

public class SoccerPlayer { // class name
	public int number; // variables
	public String name;
	public int x, y;
	
	public void run() { ...... } // methods
	public void kickBall() { ...... }
}

(3)创建类的实例
要创建一个类的实例,必须:
(i)声明一个特定类的实例标识符(实例名)。
(ii)构造实例(例如使用“new”运算符,为实例分配存储并初始化实例)。

// Declare 3 instances of the class Circle, c1, c2, and c3
Circle c1, c2, c3; // They hold a special value called null
// Construct the instances via new operator
c1 = new Circle();
c2 = new Circle(2.0);
c3 = new Circle(3.0, "red");

// You can Declare and Construct in the same statement
Circle c4 = new Circle();

当一个实例被声明但没有被构造时,它持有一个名为null的特殊值。
属于类的变量和方法正式称为成员变量和成员方法。要引用成员变量或方法,必须:
(i) 首先确定需要的实例。
(ii)使用点运算符(.)来引用所需的成员变量或方法。

// Suppose that the class Circle has variables radius and color,
// and methods getArea() and getRadius().
// Declare and construct instances c1 and c2 of the class Circle
Circle c1 = new Circle ();
Circle c2 = new Circle ();
// Invoke member methods for the instance c1 via dot operator
System.out.println(c1.getArea());
System.out.println(c1.getRadius());
// Reference member variables for instance c2 via dot operator
c2.radius = 5.0;
c2.color = "blue";

(4)构造函数(constructor)
构造函数看起来像一个特殊的方法,其方法名与类名相同。在上面的Circle类中,我们定义了三个重载版本的构造函数Circle(……)。
构造函数用于构造和初始化所有成员变量。要构造一个类的新实例,需要使用一个特殊的“new”运算符,然后调用其中一个构造函数,例如:

Circle c1 = new Circle();
Circle c2 = new Circle(2.0);
Circle c3 = new Circle(3.0, "red");

构造函数在以下方面不同于普通方法:
(i)构造函数方法的名称与类名相同。按照类名的约定,它以大写开头(而不是普通方法的小写)。
(ii)构造函数没有返回类型,它隐式返回void,在构造函数的主体中不允许返回语句。
(iii)构造函数只能通过“new”操作符调用,它只能用于初始化构造的实例。一旦构造了实例,就不能再调用构造函数了。
(iv)构造函数不是继承的。
默认构造函数:没有参数的构造函数称为默认构造函数。它将成员变量初始化为其默认值。例如,上面示例中的Circle()将成员变量的半径和颜色初始化为它们的默认值。
(5)函数重载(Method Overloading)
方法重载意味着相同的方法名可以有不同的实现(版本)。但是,不同的实现必须通过它们的参数列表(参数的数量、参数的类型或顺序)来区分。

public class TestMethodOverloading {
	public static int average(int n1, int n2) { // version A
		System.out.println("Run version A");
		return (n1+n2)/2;
	}
	public static double average(double n1, double n2) { // version B
		System.out.println("Run version B");
		return (n1+n2)/2;
	}
	public static int average(int n1, int n2, int n3) {// version C
			System.out.println("Run version C");
			return (n1+n2+n3)/3;
	}
	public static void main(String[] args) {
		System.out.println(average(1, 2)); // Use A
		System.out.println(average(1.0, 2.0)); // Use B
		System.out.println(average(1, 2, 3)); // Use C
		System.out.println(average(1.0, 2));
		 // Use B - int 2 implicitly casted to double 2.0
	}
}

/*
运行结果:
Run version A
1
Run version B
1.5
Run version C
2
Run version B
1.5
*/

与普通方法一样,构造函数也可以重载。上面的Circle类有三个重载版本的构造函数,它们由参数列表指定,如下所示:
Circle()
Circle(double r)
Circle(double r, String c)
根据调用方法时使用的实际参数列表,将调用匹配的构造函数。如果参数列表与任何方法都不匹配,就会得到编译错误。
(6)访问权限控制修饰符(Access Control Modifi ers)
访问控制修饰符可以用于控制类、成员变量或类中的成员方法的可见性。
(i)public:是可访问的,并且对系统中的所有其他对象可用。
(ii)private:是可访问的,但仅在该类中可用。
信息隐藏:类的成员变量通常是隐藏在外部字之外的,具有private访问权限控制。成员变量的访问是通过public assessor methods提供的,例如getRadius()和getColor()。
在这里插入图片描述
(7)关键字“this”
可以使用关键字“this”来引用类定义中的这个实例,关键词的主要用途之一就是解决歧义。

public class Circle {
	double radius;                       // Member variable called "radius"
	public Circle(double radius) {      // Method's argument also called "radius"
		this.radius = radius;
		// "radius = radius" does not make sense!
		// "this.radius" refers to this instance's member variable
		// "radius" resolved to the method's argument.
		//可用于构造函数
	}
	...
}

在上述代码中,有两个标识符称为radius——类的成员变量和方法的参数,这会导致命名冲突。为了避免命名错误,可以将方法的参数命名为r而不是radius。Java提供了一个名为this的关键字来解决这个命名问题。“this.radius”表示成员变量,而“radius”解析为方法的参数。
this关键字主要有三个应用:
(i)this调用本类中的属性,也就是类中的成员变量;
(ii)this调用本类中的其他方法;
(iii)this调用本类中的其他构造方法,调用时要放在构造方法的首行。

Public Class Student { //引用成员变量
	String name; //定义一个成员变量name
	private void SetName(String name) { //定义一个参数(局部变量)name
		this.name=name; //将局部变量的值传递给成员变量
	}
}
public class Aaa {
	// A private variable named xxx of the type T
	private T xxx;
	
	// Constructor
	public Aaa(T xxx) {
		this.xxx = xxx;
	}
	
	// A getter for variable xxx of type T receives no argument 
	//and return a value of type T
	public T getXxx() {
		return xxx; // or "return this.xxx" for clarity
	}
	
	 // A setter for variable xxx of type T receives a parameter of type T and return void
	public void setXxx(T xxx) {
		this.xxx = xxx;
	}
}

补充:
(i)this.varName是指该实例的varName,this.methodName(…)调用此实例的methodName(…)。
(ii)在构造函数中,我们可以使用this(…)来调用另一个构造函数。
(iii)在一个方法中,我们可以使用语句“return this”将这个实例返回给调用者。
(8)Method toString()
每个设计良好的Java类都应该有一个名为toString()的public method,该方法返回这个实例的字符串描述。可以通过调用anInstanceName.toString ()显式地调用toString()方法。toString(),或通过println()或字符串连接运算符“+”隐式表示。
例如,在Circle类中包含以下toString()方法:

// Return a String description of this instance
public String toString() {
	return "Circle[radius=" + radius + ",color=" + color + "]";
}

//get a description of a Circle instance
Circle c1 = new Circle();
System.out.println(c1.toString());          // Explicitly calling toString()
System.out.println(c1);                     // Implicit call to c1.toString()
System.out.println("c1 is: " + c1);         
// '+' invokes toString() to get a String before concatenation

(9)Constants (fi nal)
常数是修饰符final定义的变量。一个final变量只能被赋值一次,其值不能再被赋值一次。例如:

public nal double X REFERENCE = 1.234;

private nal int MAX ID = 9999;
MAX ID = 10000; // error: cannot assign a value to nal variable MAX ID

// 需要在声明期间初始化一个final成员变量
private nal int SIZE; // error: variable SIZE might not have been initialized

扩展:
(i)不能重新分配final原语变量。
(ii)不能为final实例重新分配新对象。
(iii)final类不能子类化(或扩展)。
(iv)不能覆盖final方法。
非访问控制符:
在这里插入图片描述
(10)应用举例:The Account Class
图中显示了一个名为Account的类,它对银行帐户进行建模。
在这里插入图片描述
它包含以下成员:
(i)两个private实例变量:accountNumber (int)和balance (double),它们负责维护经常账户余额。
(ii)构造函数(重载)。
(iii)private实例变量的getter和setter。accountNumber没有setterr,因为它不是设计用来更改的。
(iv)public methods credit() and debit():从余额中分别加减给定的金额。
(v)toString():返回“A/C no:xxx, Balance=$xxx”,余额四舍五入到小数点后两位。

public class Account {
	// The private instance variables
	private int accountNumber;
	private double balance;
	
	// The constructors (overloaded)
	public Account(int accountNumber, double balance) {
		this.accountNumber = accountNumber;
		this.balance = balance;
	}
	public Account(int accountNumber) { // with default balance
		this.accountNumber = accountNumber;
		this.balance = 0.0; // "this." optional
	}
	
	// The public getters/setters for the private instance variables.
	// No setter for accountNumber because it is not designed to be changed.
	public int getAccountNumber() {
		return this.accountNumber; // "this." optional
	}
	public double getBalance() {
		return this.balance; // "this." optional
	}
	public void setBalance(double balance) {
		this.balance = balance;
	}
	
	// Add the given amount to the balance.
	public void credit(double amount) {
		balance += amount;
	}
	// Subtract the given amount from balance, if applicable.
	public void debit(double amount) {
		if (balance < amount) {
			System.out.println("amount withdrawn exceeds the current balance!");
		}
		 else {
			balance -= amount;
		}
	}
	
	// The toString() returns a string description of this instance.
	public String toString() {
		// Use built-in function System.format() to form a formatted String
		return String.format("A/C no%d, Balance=%.2f", accountNumber, balance);
	}
}

/*
* A Test Driver for the Account class.
*/

public class TestAccount {
	public static void main(String[] args) {
		// Test Constructors and toString()
		Account a1 = new Account(1234, 99.99);
		System.out.println(a1); // toString()
		Account a2 = new Account(8888);
		System.out.println(a2); // toString()
		
		// Test Setters and Getters
		a1.setBalance(88.88);
		System.out.println(a1); // run toString() to inspect the modied instance
		System.out.println("The account Number is: " + a1.getAccountNumber());
		System.out.println("The balance is: " + a1.getBalance());
		
		// Test credit() and debit()
		a1.credit(10);
		System.out.println(a1); // run toString() to inspect the modied instance
		a1.debit(5);
		System.out.println(a1);
		a1.debit(500); // Test debit() error
		System.out.println(a1);
	}
}
	
/*
The expected outputs are:
A/C no:1234, Balance=99.99
A/C no:8888, Balance=0.00
A/C no:1234, Balance=88.88
Account Number is: 1234
Balance is: 88.88
A/C no:1234, Balance=98.88
A/C no:1234, Balance=93.88
amount withdrawn exceeds the current balance!
A/C no:1234, Balance=93.88
*/

(11)继承
(i)继承的概念
Java继承是指Java中一个类从另一个类继承的能力。在Java中,这也称为扩展类。一个类可以扩展另一个类,从而从这个类继承。当一个类从Java中的另一个类继承时,这两个类将扮演某些角色。扩展的类(继承自另一个类)是子类(subclass),而被扩展的类(被继承类)是超类(superclass)。换句话说,子类扩展了超类。或者,子类继承自超类。继承的另一个常用术语是专门化(specialization)和泛化(generalization)。子类是超类的专门化,超类是一个或多个子类的泛化。
继承是一种代码重用方法。继承是在具有某些共同特征的类之间共享代码的有效方法,同时允许类具有一些不同的部分。
这是一个名为Vehicle的类的图解,它有两个子类Car和Truck:
在这里插入图片描述
Vehicle类是Car和Truck的超类,Car和Truck是Vehicle的子类。Vehicle类可以包含所有Vehicle需要的字段和方法(例如车牌、所有者等),而Car和Truck可以包含特定于Car和Trucks的字段和方法。
(ii)超类和子类
超类和子类形成于继承结构(也称为类层次结构),在类层次结构的顶部有超类,在类层次结构的底部有子类。一个类层次结构可能有多个级别,即超类和子类的多个级别。子类本身可以是其他子类的超类等等。
当一个类从超类继承时,它继承了超类方法和字段的一部分。子类也可以覆盖(redefi ne)继承的方法。字段不能被覆盖,但是可以在子类中被“隐藏”。
(iii)继承的什么
当子类扩展Java中的超类时,所有受保护的和公共的字段以及超类的方法都由子类继承。所谓继承,是指这些字段和方法是子类的一部分,就好像子类本身声明了它们一样。可以调用和引用受保护的和公共的字段,就像在子类中直接声明的方法一样。
只有当子类与超类位于同一个包中时,具有default (package)访问修饰符的字段和方法才能被子类访问。父类的私有字段和方法永远不能被子类直接引用,然而,它们可以通过从子类(例如default (package),protected and public methods)中获得的方法间接引用。
(iv)Java只支持单一继承:
Java继承机制只允许Java类从单个超类(单一继承)继承。在一些编程语言中,比如c++,子类可以从多个超类继承(multiple inheritance)。由于多重继承可能会产生一些奇怪的问题,例如,如果超类包含具有相同名称和参数的方法,于是在Java中就忽略了多重继承。
(v)声明继承
在Java继承中,使用extends关键字声明。通过在类的定义中使用extends关键字,来声明一个类扩展另一个类。

public class Vehicle {
	protected String licensePlate = null;
	
	public void setLicensePlate(String license) {
		this.licensePlate = license;
	}
}
public class Car extends Vehicle {
	int numberOfSeats = 0;
	
	public String getNumberOfSeats() {
		return this.numberOfSeats;
	}
}

(vi)类型转换(Type Casting)
可以将子类引用为它的一个超类的实例。例如,使用上一节示例中的类定义,可以将Car类的实例引用为Vehicle类的实例。因为Car类继承了Vehicle类,所以它也被称为Vehicle。

Car car = new Car();
Vehicle vehicle = car;

将类的对象作为与类本身不同的类型引用的过程称为类型转换。将对象从一种类型转换为另一种类型。可以将子类的对象转换为它的一个超类,这称为向上转换(upcasting)(从子类类型到超类类型)。也可以将一个对象从超类类型转换为子类类型,但前提是该对象确实是该子类的实例(或该子类的子类的实例),这称为向下转换(downcasting)(从超类类型到子类类型)。因此,这个向下强制转换的例子是有效的:

Car car = new Car();

//upcast to Vehicle
Vehicle vehicle = car;

//downcast to car again
Car car2 = (Car) vehicle;

但是,下面的示例无效。Java编译器将接受它,但是在运行时执行此代码时,代码将抛出ClassCastException。

//Truck对象可以向上转换为Vehicle对象,但以后不能向下转换为Vehicle对象,
//这将导致ClassCastException
Truck truck = new Truck();

// upcast to Vehicle
Vehicle vehicle = truck;

//downcast to car again
Car car = (Car) vehicle;

(vii)覆盖重载方法(Overriding Methods)
在子类中,可以重写超类中指定的(rede fine)方法。下面是一个Java方法重写示例:

public class Vehicle {
	String licensePlate = null;
	public void setLicensePlate(String licensePlate) {
		this.licensePlate = licensePlate;
	}
}

public class Car extends Vehicle {
	public void setLicensePlate(String license) {
		this.licensePlate = license.toLowerCase();
	}
}

注意Vehicle类和Car类是如何构造一个名为setLicensePlate()的方法的。现在,无论何时在Car对象上调用setLicensePlate()方法,调用的都是Car类中指定的方法,超类中的方法将被忽略。
要覆盖一个方法,子类中的方法名必须与超类中的相同。这意味着子类中的方法定义必须具有完全相同的名称、相同数量和相同类型的参数,并且这些参数必须以与超类相同的顺序列出,否则子类中的方法将被视为一个单独的方法。
在Java中,不能覆盖超类的private method。如果超类从其他方法内部调用private method,它将继续从超类调用该方法,即使在子类中创建具有相同名称的private method也是如此。
(vii)覆盖注释(@override Annotation)
可以将Java @override注释置于覆盖超类中的方法的方法之上:

public class Car extends Vehicle {
	@Override
	public void setLicensePlate(String license) {
		this.licensePlate = license.toLowerCase();
	}
}

(viii)调用父类方法
如果在子类中重写了一个方法,但仍然需要调用超类中指定的方法,那么可以使用超引用(super reference):

public class Car extends Vehicle {
	public void setLicensePlate(String license) {}
		super.setLicensePlate(license);
	}
}

可以从子类中的任何方法调用超类实现,它不必来自重写的方法本身。例如,也可以从Car类中名为updateLicensePlate()的方法调用super.setLicensePlate(),该方法不覆盖setLicensePlate()方法。
(ix)instanceof指令
Java包含一条名为instanceof的指令,instanceof指令可以确定给定对象是否为某个类的实例。

Car car = new Car();
boolean isCar = car instanceof Car;
//执行此代码后,isCar变量将包含值true

也可以使用instanceof指令来确定对象是否是其类的超类的实例。

Car car = new Car();
boolean isVehicle = car instanceof Vehicle;
//假设Car类继承自Vehicle类,isVehicle变量将在执行此代码后包含true值
//Car对象也是一个Vehicle对象,因为Car是Vehicle的子类

(x)构造函数与继承
Java继承机制不包括构造函数。换句话说,超类的构造函数不会被子类继承。子类仍然可以使用super()构造函数调用超类中的构造函数。实际上,子类构造函数需要调用超类中的一个构造函数,作为构造函数体中的第一个操作。

public class Vehicle {
	public Vehicle() {
	}
}
public class Car extends Vehicle{
	public Car() {
		super();
		//perform other initialization here
	}
}

(xi)嵌套类(Nested Classes)
在Java嵌套类中,类是在另一个类中定义的。嵌套类的目的是明确地将嵌套类与其周围的类分组,表明这两个类将一起使用。或者嵌套类只能从它的封闭(拥有)类内部使用。Java开发人员通常将嵌套类称为内部类(inner classes),但是内部类(非静态嵌套类,(non-static nested classes)只是Java中嵌套类的几种不同类型中的一种。可以在Java中创建几种不同类型的嵌套类,Java嵌套类类型有:
a)Static Nested Classes
在Java中,静态嵌套类本质上是一个普通的类,它被嵌套在另一个类中:

public class Outer {
	public static class Nested {
	
	}
}

为了创建嵌套类的实例,必须通过使用外部类名预估它来引用它,如下所示:

Outer.Nested instance = new Outer.Nested();

静态嵌套类只能通过对封闭类实例的引用访问封闭类的实例变量。
b)Non-static Nested Classes (Inner Classes)
Java中的非静态嵌套类也称为内部类。内部类与封闭类的实例相关联。因此,必须首先创建封闭类的实例,以创建内部类的实例。

public class Outer {
	public class Inner {

	}
}

//Here is how you create an instance of the Inner class:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();

非静态嵌套类(内部类)可以访问封闭类的字段,即使它们被声明为私有的。

public class Outer {
	private String text = "I am private!";
	
	public class Inner {
		public void printText() {
		System.out.println(text);
		}
	}
}

如果Java内部类声明了与封闭类中的字段或方法同名的字段或方法,那么内部字段或方法就会被称为遮蔽了外部字段或方法。

public class Outer {
	private String text = "I am Outer private!";
	
	public class Inner {
		private String text = "I am Inner private";
		
		public void printText() {
			System.out.println(text);
		}
	}
}

在上面的示例中,外部类和内部类都包含一个字段名称的文本。当内部类引用文本时,它引用自己的字段。当外部指的是文本时,它也指的是它自己的领域。
但是,Java使内部类可以引用外部类的文本字段。要做到这一点,它必须在文本字段引用前加上Outer.this。(the outer class name + .this. + eld name):

public class Outer {
	private String text = "I am Outer private!";
	
	public class Inner {
		private String text = "I am Inner private";
		
		public void printText() {
			System.out.println(text);
			System.out.println(Outer.this.text);
		}
	}
}

c)Local Classes
Java中的本地类类似于内部类(非静态嵌套类),它们是在方法或在一个方法作用域块(…)中指定的。

class Outer {
	public void printText() {
		class Local {
		
		}
		Local local = new Local();
	}
}

本地类只能从指定它们的方法或作用域块内部访问。本地类可以访问其封闭类的成员(字段和方法),就像常规的内部类一样。
d)Anonymous Classes
Java中的匿名类是没有类名的嵌套类。它们通常被声明为现有类的子类,或者是某个接口的实现。匿名类在实例化时被删除。下面是一个声明超类的匿名子类的例子,该子类称为超类。

public class SuperClass {
	public void doIt() {
		System.out.println("SuperClass doIt()");
	}
}

SuperClass instance = new SuperClass() {
	public void doIt() {
		System.out.println("Anonymous class doIt()");
	}
};
instance.doIt();
//运行此Java代码将导致将匿名类doIt()打印到System.out
//匿名类子类(扩展)超类并覆盖doIt()方法

Java匿名类也可以实现接口,而不是扩展类。

猜你喜欢

转载自blog.csdn.net/qq_41897243/article/details/82953381
sec