【Java】高级语言特征

1.静态变量、方法与初始化程序块(Static关键字)
1.1静态变量(类变量)

静态变量:在类的成员变量声明中带有static关键字的变量。

静态变量的创建:

  • 静态变量的创建与实例对象无关。
  • 只在系统加载其所在分配空间并初始化 ,且在创建该类的实例对象不再 分配空间。

    代码建议仔细阅读,后面有注释,含有变量、构造方法调用的顺序。
bash 复制代码
package java004;
//在调用构造方法之前,先把对应类中的变量创建出来,若有static变量,按从上往下的顺序创建(调用构造方法),再创建普通变量
//若static变量之前创建过,再次遇到时跳过,而普通变量需要再次被创建、调用构造方法,如main函数中的两个new Cupboard();
class Bowl {
    Bowl(int i) { System.out.println("Bowl(" + i + ")"); }
    void f1(int i) { System.out.println("f1(" + i + ")"); }
}
class Table {
    static Bowl bowl1 = new Bowl(1);
    Table() {
        System.out.println("Table()");
        bowl2.f1(1);
    }
    void f2(int i) { System.out.println("f2(" + i + ")"); }
    static Bowl bowl2 = new Bowl(2);
}
class Cupboard {
    Bowl bowl3 = new Bowl(3);
    static Bowl bowl4 = new Bowl(4);
    Cupboard() {
        System.out.println("Cupboard()");
        bowl4.f1(2);
    }
    void f3(int i) { System.out.println("f3(" + i + ")"); }
    static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {//这个类包含Static变量,加载这个类的时候,首先要加载Static变量
    public static void main(String[] args) {
        System.out.println("new Cupboard() in main");
        new Cupboard();//在调用构造方法之前,bowl3会再被创建一次,调用new Bowl(3),输出Bowl(3),而静态变量只创建一次,故不再调用
        //调用构造方法,输出Cupboard()、f1(2)
        System.out.println("new Cupboard() in main");
        new Cupboard();//重复上面的new Cupboard();
        table.f2(1);
        cupboard.f3(1);
    }
    static Table table = new Table();//StaticInitialization类包含static变量,第一步,先执行这一句,在数据区创建table变量,接着在调用构造方法之前,先加载Table类的static变量,
    //在数据区创建bowl1变量,Bowl类中无静态变量,调用构造方法,输出Bowl(1)。接着,在数据区创建bowl2变量,Bowl类中无静态变量,调用构造方法,输出Bowl(2)。
    //静态变量加载完后,调用new Table()构造方法,输出Table()、f1(1);
    static Cupboard cupboard = new Cupboard();//第二步,数据区创建cupboard变量,接着在调用构造方法之前,先加载Table类的static变量,
    //在数据区创建bowl4变量,Bowl类中无静态变量,调用new Bowl(4)构造方法,输出Bowl(4)。接着,在数据区创建bowl5变量,Bowl类中无静态变量,调用构造方法,输出Bowl(5)。
    //在栈中创建变量bowl3,Bowl类中无静态变量,调用new Bowl(3)构造方法,输出Bowl(3)。
    //静态变量加载完后,调用new Cupboard()构造方法,输出Cupboard()、f1(2)
    //进入main函数
}

非private的静态变量,可在类外用类名访问(一下两种均可)

bash 复制代码
class Employee{
private int id;
public static int serialNum = 1;
Employee(){ id=serialNum ++; }
}
class OtherClass{
public static void main(String[] args){
      System.out.println(Employee.serialNum);
}
}
bash 复制代码
class Employee{
private int id;
public static int serialNum = 1;
Employee(){ id=serialNum ++; }
}
class OtherClass{
public static void main(String[] args){
      Employee e=new Employee();
      System.out.println(e.serialNum);
}
}
1.2静态方法(类方法)
  • 静态方法:在类的成员方法声明中带有static关键字的方法。
  • main方法是静态方法、程序入口点,不创建实例对象就可以运行该方法
  • 静态方法一般通过类名访问,但特殊情况下也可通过实例对象访问。
bash 复制代码
class GeneralFunction {
	public static int add(int x, int y) {
		return x + y;
	}
}
public class UseGeneral {
	public static void main(String[] args) {
		int c = GeneralFunction.add(9, 10);
		System.out.println("9 + 10 = " + c);
	}
}

静态方法 中没有this引用,需要将实例传入参数才可访问。因此,静态方法不能直接调用实例方法,也不能直接访问所属类的实例成员变量,但可以访问静态变量和静态方法。

bash 复制代码
public class TestStaticMethod{
	public static void main(String[] args){
		StaticMethod obj=new StaticMethod();
		StaticMethod.sPrintXAndY(obj);		}
}
class StaticMethod{
	int x=0;		static int y=1;
	public void iPrintAndIncreaseY(){
		sPrintY(); 
		y++;
	}
	public static void sPrintY(){
		//System.out.println(this.x);	//不能访问实例成员变量
		//iPrintAndIncreaseY();		//不能访问实例方法
		System.out.println(StaticMethod.y);	//可以访问静态变量
	}
	public static void sPrintXAndY(StaticMethod o){
		System.out.println(o.x);	//可以通过o引用访问实例成员变量
		o.iPrintAndIncreaseY();	//可以通过o引用调用实例方法
		sPrintY();		//可以直接调用静态方法
	}

静态方法的重写:
回顾方法重写的规则:

不改变方法的名称、参数列表和返回值,改变方法的内部实现

子类中重写方法的访问权限不能缩小

子类中重写方法不能抛出新的异常

父类中private 的成员,在子类中不能被覆盖(重写)
本节加入以下重写规则:

子类不能把父类的静态 方法重写为非静态

子类不能把父类的非静态 方法重写为静态

子类可以声明与父类静态方法相同的方法

//静态方法的重写不会导致多态性

//构造方法可以看成是static方法,不具有多态性

2.final关键字
2.1final的使用位置

1.在类声明中使用:表示类不能被继承。

2.在成员方法声明及方法参数中使用:成员方法不能被重写,参数变量值不能更改。

3.在成员变量和局部变量声明中使用:表示变量的值不能更改。

2.1.1在类声明中使用final关键字

被定义成final的类不能再派生子类

例: final class Employee {...}

class Manager extends Employee { ...}

2.1.2在成员方法声明中使用final关键字

被定义成final的方法不能被重写。

//将方法定义为final可使运行时的效率优化

//对于final方法,编译器直接产生调用方法的代码,而阻止运行时刻对方法调用的动态绑定

private的方法都隐含指定为是final的,对子类不可见就无所谓被重写。

2.1.3在方法参数中使用final关键字

将方法参数指明为final,则无法在方法中更改参数的值

bash 复制代码
//Cat类含有name和eyeColor两个成员变量
public void m2(final int j) { // final变量不能改变值,final方法不能被重写
		//j = 10; 报错
	}
	
	public void mCat(final Cat c) {  
		c.eyeColor = "black";//重要!!!!不报错,引用不能改变,但堆里的内容可以改变
		//c = new Cat("name", "color"); 报错,指向新的引用
	}
}
2.1.4在成员变量中使用final关键字
bash 复制代码
class T {
	final int i = 8; //final的变量不能改变值, c++ -> const
	public final void m() { //final方法不能被重写
		//i = 8; 让i=8仍会报错,因为编译器会理解为你在试图改变i的值
	}
}

空白final:若final成员变量声明时未赋初值,则在所属类的每个构造方法 中都必须对该变量赋值。

bash 复制代码
class Poppet {
	private int i;
	Poppet(int ii) { i = ii; }
}
public class BlankFinal {
	private final int i = 0; 	// 被初始化的final
	private final int j; 	// 空白final
	private final Poppet p; 	// 空白final引用
	public BlankFinal() {
		j = 1; 			// 初始化空白final
		p = new Poppet(1); 	// 初始化空白final引用
	}
	public BlankFinal(int x) {
		j = x; 			// 初始化空白final
		p = new Poppet(x); 	// 初始化空白final引用
	}
	public static void main(String[] args) {
		new BlankFinal();
		new BlankFinal(47);
	}
}
2.1.5在局部变量中使用final关键字

被定义成final的局部变量可以在所属方法的任何位置被赋值,但只能赋一次。

2.1.6总结
bash 复制代码
package java004;

public class TestFinal {
	public static void main(String[] args) {
		T t = new T();
		//t.i = 9;
	}
}
class T {// final class T {会报错,有TT继承
	final int i = 8; //final的变量不能改变值, c++ -> const
	public final void m() { //final方法不能被重写
		//i = 8; 让i=8仍会报错,因为编译器会理解为你在试图改变i的值
	}
	
	public void m2(final int j) { // final变量不能改变值,final方法不能被重写
		//j = 10; 报错
	}
	
	public void mCat(final Cat c) {  
		c.eyeColor = "black";//重要!!!!不报错,引用不能改变,但堆里的内容可以改变
		//c = new Cat("name", "color"); 报错,指向新的引用
	}
}
class TT extends T { 
	//public void m() {}会报错,final方法不能重写
	
}
3.抽象类与接口
3.1抽象方法

抽象方法:Java允许在类中只声明方法而不提供方法的实现,这种只有声明而没有方法体的方法称为抽象方法。

抽象方法的声明中需加关键字abstract。

3.2抽象类

由关键字abstract声明的类称为抽象类

😊包含抽象方法的类必须是抽象类

😊抽象类可以不包含抽象方法,但一般会包括

😊抽象类可以有构造方法、普通成员变量和方法(只要有一个抽象方法即可)

😊抽象类的构造方法通常声明为protected(只给子类用,因为不能new)

😊不能创建抽象类的实例

😊抽象类的子类也可以是抽象类

💦抽象类的作用--实现动态绑定,进而实现运行时多态

3.3接口

💜接口是一种特殊的抽象,只不过所有的方法都是抽象方法,实际上没有成员变量,但可以定义常量(static final)。

💜接口中只声明方法("做什么",抽象方法)但不定义方法体("怎么做")。

💜 Java不支持多继承 ,通过class Snake extends Animal implements Valuable(接口){}实现。

❓为什么接口体中必须要定义常量,而不能定义普通的成员变量呢❓

为了实现多重继承,Java采用形如class Snake extends Animal implements Protectable(继承一个父类并实现一个接口),在类体中,如果super.成员变量名 (如果父类和接口中的变量名相同),当接口中是常量时就不会报错。如果要访问接口中的变量,通过接口名加.(类变量)。

💜接口中的变量默认 具有public static final 属性。

💜对于class Snake extends Animal implements Protectable{},类体中要重写父类中所有的抽象方法和接口中的所有方法

💜class Snake extends Animal implements Protectable,Animal和Protectable中的方法不要重名,重写时出现麻烦。

💜接口通过子类实例化。

bash 复制代码
public abstract class Animal {
	static final int age = 1;
	String name;
	public Animal(String name){
		this.name = name;
	}
	public abstract void enjoy();
	public abstract void run();
	public abstract void eat();
}
interface Animal2{
	public void enjoy();
	public void run();
	public void eat();
}

💦接口定义=接口声明+接口体

💦接口声明

[public|default] interface 接口名 [extends 父接口列表] { 接口体 }

public / default:public任意类均可使用,default与该接口在同一个包中的类可使用。

一个接口可以有多个父接口,通过extends实现,子接口继承父接口的所有常量和方法。

接口的继承支持多重继承。

💦接口体

接口体=常量定义+方法定义

🐼常量默认 具有public, final, static属性

类型 常量名=常量值;

🐼方法默认 具有public, abstract属性

返回类型 方法名 ([参数列表]);

常量不能为空白final的(接口中没有构造方法)

父接口中的常量可被子接口中的同名常量隐藏(static)

接口中成员不能使用的修饰符:private, protected(接口中的成员方法要被继承重写)

💦接口的使用------用类实现接口

类声明中的implements关键字

类可以使用 接口定义的常量

类必须实现接口定义的所有 方法

一个类可以实现多个接口,例:

interface I1{ ... }

interface I2{ ... }

class Sup { ... }

class C extends Sup implements I1,I2 { ... }

💦接口示例

💥注意:

不能向interface定义中随意增加方法,继承了该接口的所有类都需要重写该方法,工作量大,需要通过定义新的接口,利用接口的继承支持多重继承。

判断对错:

下列接口的定义中,哪些是正确的?

(1) interface Printable{

void print() {};//错误,不能有方法体

}

(2) abstract interface Printable{

void print();//正确,但冗余(abstract )

}

(3) abstract interface Printable extends Interface1, Interface2{

void print() {};//错误,不能有方法体

}

(4) interface Printable{

void print();//正确

}

4.集合类(容器类)--会用就行

一个集合类的实例(集合对象)表示了一组对象,相当于一个容器,集合对象存放指向其他对象的引用。


注意:具有排序功能的Set和Map都要实现Comparable接口

bash 复制代码
public class TestCollection1 {
	public static void main(String[] args) {
		
		//Plant [] p = new Plant[1000];数组大小固定
		//Collection pcollection = new ArrayList();不用考虑数组大小,会自动分配,即自动增减数组大小
		
		//用接口来定义子类
		Collection c = new ArrayList();//接口不能直接new对象,ArrayList是实现Collection接口的子类
		//Collection接口的方法示例,未定义泛型,所有类型存储的元素均为Object类型,任何对象都可以存进去
		c.add("Hello");
		c.add(new Name("San", "Zhang"));
		c.add(new Integer(100));
		System.out.println(c.size());//3
		System.out.println(c);//默认调用c.toString(),ArrayList对toString()方法重写,最后输出[Hello, San.Zhang, 100]
		
		c.remove("Hello");//判断两个对象相等的时候删除
		c.remove(new Integer(100));
		c.remove(new Name("San", "Zhang"));
		System.out.println(c);
		//若Name里没有重写toString方法,则输出[San.Zhang]
		//Name里重写了toString方法,则输出[]
	}
}

//Nama类
class Name /*implements Comparable*/ {
	
	private String firstName, lastName;
	//private,所以下面定义了get,set方法
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}
 
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Name(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	//方法重写
	public String toString() {
		return firstName +"." + lastName;
	}

	//方法重写
	public boolean equals(Object obj) {
		if(obj instanceof Name) {
			Name n = (Name)obj;
			if(firstName.equals(n.firstName) && lastName.equals(n.lastName))
				return true;
		}
		return super.equals(obj);//默认Object的equals方法
	}
	
	//重写equals方法,一般都需要把hashCode重写一下,一般采用现成的
	//方法重写(这里使用了String的hashCode)
	public int hashCode() {
		return firstName.hashCode();
	}

}
bash 复制代码
public class TestCollection2 {
	public static void main(String[] args) {
		Collection c = new HashSet();
		c.add(new Name("f4", "l4"));
		c.add(new Name("f2", "l2"));
		c.add(new Name("f3", "l3"));
		c.add(new Name("f4", "l4"));
		System.out.println(c.size());
		//如果Name类不重写hashCode(),默认equals方法,并不相同,则输出4
		//重写了hashCode(),输出3
		//Set是集合,不要求有重复的元素,要同时重写equals和hashCode方法,确保相同的对象有相同的哈希值
		System.out.println(c);
		}
}
//Nama类
class Name /*implements Comparable*/ {
	
	private String firstName, lastName;
	//private,所以下面定义了get,set方法
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}
 
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Name(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	//方法重写
	public String toString() {
		return firstName +"." + lastName;
	}

	//方法重写
	public boolean equals(Object obj) {
		if(obj instanceof Name) {
			Name n = (Name)obj;
			if(firstName.equals(n.firstName) && lastName.equals(n.lastName))
				return true;
		}
		return super.equals(obj);//默认Object的equals方法
	}
	
	//重写equals方法,一般都需要把hashCode重写一下,一般采用现成的
	//方法重写(这里使用了String的hashCode)
	public int hashCode() {
		return firstName.hashCode();
	}
}

重写equals方法,一般都需要把hashCode重写一下

4.0泛型的基本概念

如果希望创建一个能够存放String对象的ArrayList,应使用ArrayList进行声明。ArrayList总是可以被看作一个具体的类,该类的实例作为容器可以存放String类型的对象。

eg:Set s = new HashSet ()

<K,V>< E>都是泛型,且K、V、E是类,不能是基本类型

bash 复制代码
public class FindDups {
	public static void main(String args[]) {//aaa bbb ccc aaa aaa
		// 创建一个HashSet对象,缺省的初始容量是16
		Set<String> s = new HashSet<String>();
		// 将命令行中的每个字符串加入到集合s中,
		//其中重复的字符串将不能加入,并被打印输出
		for (int i = 0; i < args.length; i++) {
		        if (!s.add(args[i]))
			System.out.println("Duplicate detected: " + args[i]);
		}
		//Set不能添加重复元素,已重写equals和hasoCode方法
		//Duplicate detected:aaa
		//Duplicate detected:aaa
		// 输出集合s的元素个数以及集合中的所有元素:
		System.out.println(s.size() + " distinct words detected: " + s);
		//[aaa,ccc,bbb]
	}
}
4.1Collection接口

Collection接口中所定义的方法:

int size() ;

boolean isEmpty();

void clear();

boolean contain(Object element);

boolean add(Object element);

boolean remove(Object element);

Iterator iterator();

boolean containAll(Collection c);

boolean addAll(Collection c);

boolean removeAll(Collection c);

boolean retainAll(Collection c);

Object[] toArray();

4.2迭代器(Iterator接口)

Iterator是一个轻量级对象(接口),用于遍历并选择序列中的对象

每个对象遍历序列的方式不一样(像数组、链表),所以迭代器为接口。

在Collection接口的方法中,含有Iterator interator();方法。

bash 复制代码
public class TestCollection2 {
	public static void main(String[] args) {
		Collection c = new HashSet(); 
		c.add(new Name("f4", "l4"));
		c.add(new Name("f2", "l2"));
		c.add(new Name("f3", "l3"));
		c.add(new Name("f4", "l4"));
		System.out.println(c.size());
		System.out.println(c);
		Iterator i = c.iterator();
		while(i.hasNext()) {
			Name n = (Name)i.next();
			System.out.println(n.getFirstName() + " ");
			if(n.getFirstName() == "f2") {
				i.remove(); // 只能用Iterator的remove方法,执行了锁定(在该循环里面返回了迭代器)
				//不能用c.remove(n);会抛出异常
			}
		}
		System.out.println(c);
		
		//用增强型的for循环实现迭代器的功能
		int [] arr = {1,2,3,4,5};
		for(int v : arr) {
			System.out.println(v);
		}
		
		for(Object o: c) {
			System.out.println(o); //好处:语法简便;缺点:1、不能访问下标指向的元素,2、不能删除特定元素
			//c.remove(o);也会抛出异常
			//也就是说,增强型的for循环也不能调用Collection的remove()方法
		}
	}
}
4.3set接口

集合,无序,不能包含重复元素。

三种接口实现:HashSet, TreeSet, LinkedHashSet

//HashSet:(最常用)采用Hash表实现了Set接口,元素无固定顺序,对元素的访问效率高

//TreeSet:实现了SortedSet接口,采用有序树结构存储集合元素,元素按照比较结果的升序排列

//LinkedHashSet:实现了Set接口,采用Hash表和链表结合的结构存储集合元素,元素按照被添加的先后顺序保存

//Set的主要接口方法和Collection完全一样

bash 复制代码
/**
Set方法测试,注意String类已重写equals和hashcode,重复元素不会添加到Set中。
Name类也已重写equals和hashcode
set无序、集合、不含有重复元素
 */
public class TestSet {
	public static void main(String[] args) {
		Set s1 = new HashSet();
		Set s2 = new HashSet();
		// s1
		s1.add("a"); s1.add("b"); s1.add("a"); s1.add("d"); //String类已默认重写了equals和hanshCode方法
		s1.add(new Name("f1","l1"));
		s1.add(new Name("f1","l1"));//Name类已重写了equals和hashCode方法
		System.out.println(s1);//HashSet();已重写了toString方法
		//[a,b,c,f1,f2]
		// s2
		s2.add("a"); s2.add("b"); s2.add("c"); 
		System.out.println(s2);
		//[a,b,c]
		// sn1
		Set sn1 = new HashSet(s1);
		sn1.retainAll(s2);//求交集
		System.out.println(sn1);
		//[a,b]
		Set sn2 = new HashSet(s1);
		sn2.addAll(s2);//求并集
		System.out.println(sn2);
		//[a,b,c,d,f1,f2]
	}
}
4.4List接口

列表,有序,可包含重复元素,可通过索引序号访问元素

(列表的 "有序" 指的是元素会按照插入顺序排列,并且可以通过索引(下标)访问。集合的 "无序" 指的是元素没有固定的顺序,无法通过索引访问,且会自动去重。)
两种接口实现:ArrayList, LinkedList

//ArrayList:采用可变大小的数组实现List接口

无需声明上限,随着元素的增加,长度自动增加

对元素的随机访问速度快,插入/移除元素较慢

该类是非同步的,相对于Vector(legacy)效率高

//LinkedList:采用链表结构实现List接口

实际上实现了List接口、Queue接口和双端队列Deque接口,因此可用来实现堆栈、队列或双端队列

插入/移除元素快,对元素的随机访问较慢

该类是非同步的

List接口方法:

bash 复制代码
public class UseArrayList {
	public static void main(String[] args) {
		List scores = new ArrayList();
		scores.add("86");	// 添加元素
		scores.add("98");	// 添加元素
		scores.add(1, "99");	// 插入元素,在下标为1处添加99,其余的往后移
		for (int i = 0; i < scores.size(); i++) {
			System.out.print(scores.get(i) + " ");// 输出结果
		}
		// 86 99 98
		System.out.println(scores);
		//[86,99,98]因为ArrayList的toString方法已被修改
		scores.set(1, "77");	// 修改第二个元素
		scores.remove(0);	// 删除第一个元素
		System.out.println("\n修改并删除之后");
		for (int i = 0; i < scores.size(); i++) {
			System.out.print(scores.get(i) + " ");
		}
		//77 98
		System.out.println(" \n按字符串输出\n" + scores.toString());
		//[77,98]
	}
}		

Collections类的一些方法

bash 复制代码
public class TestArrayList {
	public static void main(String[] args) {
		List l1 = new ArrayList();
		for(int i = 0; i <= 9; i++) {
			l1.add("a" + i);
		}
		System.out.println(l1);
		Collections.shuffle(l1); //打乱顺序
		System.out.println(l1);
		Collections.reverse(l1); //逆转顺序
		System.out.println(l1);
		Collections.sort(l1); //排序(String类已经重写了compareTo方法)
		System.out.println(l1);
		System.out.println(Collections.binarySearch(l1, "a5")); //ֲ二分查找,返回下标
		
		List l2 = new ArrayList();
		l2.add(new Name("Kevin", "Durant"));
		l2.add(new Name("Stephen", "Curry"));
		l2.add(new Name("Klay", "Thompson"));
		l2.add(new Name("Draymond", "Green"));
		System.out.println(l2);
		Collections.sort(l2);//若Name类里面不重写compareTo方法就会报错,因为是自定义的类,并不知道比较规则
		System.out.println(l2);
	}
}
//Nama类实现Comparable接口
class Name implements Comparable {
	
	private String firstName, lastName;
	//private,所以下面定义了get,set方法
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}
 
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Name(String firstName, String lastName) {
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	//方法重写
	public String toString() {
		return firstName +"." + lastName;
	}

	//方法重写
	public boolean equals(Object obj) {
		if(obj instanceof Name) {
			Name n = (Name)obj;
			if(firstName.equals(n.firstName) && lastName.equals(n.lastName))
				return true;
		}
		return super.equals(obj);//默认Object的equals方法
	}
	
	//重写equals方法,一般都需要把hashCode重写一下,一般采用现成的
	//方法重写(这里使用了String的hashCode)
	public int hashCode() {
		return firstName.hashCode();
	}
	
	//方法重写
	public int compareTo(Object obj) {
		Name n = (Name) obj;
		int lastCmp = lastName.compareTo(n.lastName);
		return lastCmp != 0 ? lastCmp: firstName.compareTo(n.firstName);//String 类已经重写了compareTo方法
	}
}
4.5Queue接口

两种接口实现:LinkedList (即可List,也可Queue,不同之处主要体现在List、Queue两种接口方法的差异上), PriorityQueue (优先队列)

队列:先入先出

Queue接口方法:

优先队列:

优先队列的优先级在排序中有compareTo方法的重写。

bash 复制代码
public class QueueDemo {
	public static void printQ(Queue queue) {
		while (queue.peek() != null)
			System.out.print(queue.remove() + " ");
		System.out.println();
	}
	public static void main(String[] args) {
		Queue queue = new PriorityQueue();//优先队列
		
		queue.add(new Name("A","Z"));
		queue.add(new Name("B1","N"));
		queue.add(new Name("B2","N"));
		queue.add(new Name("B","M"));
		printQ(queue);
		//B.M B1.N B2.N A.Z//Name类已重写toString方法,重写了compareTo()方法
		//如果是new LinkedList(),则这里的输出应该是A.Z B1.N B2.N B.M
		System.out.println(queue);
		//[]
		//调用了printQ()方法后变空了
	}
}
4.6Map接口

接口实现:HashMap, TreeMap, LinkedHashMap

把键映射到某个值:

一个键最多只能映射一个值

一个值可对应多个键

最常用:HashMap(无序)和TreeMap(有序)

Map接口方法:

bash 复制代码
public class Freq {
	public static void main(String args[]) {
		String[] words = { "if", "it", "is", "to", "be", "it", 
				"is", "up", "to", "me", "to", "delegate" };
		Integer freq;
		Map<String, Integer> m = new TreeMap<String, Integer>();
		
		for (String a : words) {//以(单词,词频)为键值对, 构造频率表
			freq = m.get(a); // 获取指定单词的词频。
			if (freq == null) { // 词频递增
				freq = 1;
			} else {
				freq++;// .intValue()
			}
			m.put(a, freq); // 在Map中更改词频
		}
		System.out.println(m.size() + " distinct words detected:");
		System.out.println(m);
		//8 distinct words detected:
		//{be=1, delegate=1, if=1, is=2, it=2, me=1, to=3, up=1}TreeMap重写的toString方法
	}
}
5.枚举类型

枚举类型和类有同等地位,枚举类可以在public class内部定义,也可以在外部定义。该类可以包含方法和其他属性,以支持对枚举值的操作,还可以实现任意的接口。

枚举常量默认static、final,可以通过类名、对象名访问。
枚举类型变量属于引用变量,变量取值范围为所有可能的枚举常量。

[public] enum 枚举类型名 [implements 接口名表] { 枚举常量定义(主要) //[枚举体定义] }

枚举体定义:

可以包含变量、构造方法和成员方法

构造方法只能为private,保证用户不会创建新的枚举常量。

bash 复制代码
package java004;
enum level{
	LOW,MEDIUM,HIGH;//默认static、final,可以通过类名、对象名访问
}
public class LetsDoEnum {
	public static void main(String[] args) {
		level l = level.HIGH;
		System.out.println(l);//HIGH
		System.out.println(l.name());//HIGH   name()返回当前枚举常量的名字
		System.out.println(l.ordinal());//2   ordinal()返回该枚举常量在声明中的次序值(类似于数组下标)
		//通过对象名访问
		switch(l.MEDIUM) {
		case HIGH:
			System.out.println("困难模式");
			break;
		case MEDIUM:
			System.out.println("普通模式");
			break;
		case LOW:
			System.out.println("简单模式");
			break;
		}
	}
}

enum.values()

bash 复制代码
enum Week {
	SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
	THURSDAY, FRIDAY, SATURDAY
}

public class EnumValuesTest {
	public static void main(String args[]) {
		for (Week w : Week.values()) {//ElementType[] values():返回一个数组,数组包含该枚举类型的所有枚举常量,且数组中的元素严格保持其在枚举类型中的声明顺序
			System.out.print(w.name() + ". ");
		}
		System.out.println();
	}
}

枚举类型高级实现(理解即可)

bash 复制代码
package java004;

enum Scholar{
	xiaozhang("Java","18"),
	xiaoli("Math","19"),
	laowang("Art","23");
	private final String d;
	private final String y;
	Scholar(String s,String b){
		d=s;
		y=b;
	}
	public String getd() {
		return d;
	}
	public String gety() {
		return y;
	}
}
public class LetsDoEnum2 {
	public static void main(String[] args) {
		for(Scholar people:Scholar.values()) {
			System.out.printf("%s\t%s\t%s\n",people,people.getd(),people.gety());
		}
		//xiaoli	Math	19
		//laowang	Art	23
	}
}
6.Wrapper类

Wrapper将基本类型表示成类

bash 复制代码
package java004;

import java.util.ArrayList;

public class TestWrapper {
	public static void main(String[] args) {
		int i = 6;
		Integer ii = new Integer(5);//Boxing
		Integer jj = 5;//Auto-Boxing 
		int j = jj.intValue();//UnBoxing
		int k = jj;//Auto-Boxing
		//在包装类里面建议使用包装类
		ArrayList<Integer> values = new ArrayList<Integer>();//ctrl+shift+o自动导入包
		values.add(0);
		values.add(10);
		//在遍历里面使用基本类型
		for(int m = 0; i < 100; i++) {
		}
	}
}
bash 复制代码
public class AutoBoxingTest {
	public static void main(String args[]) {
		Integer x, y;
		int c;
		x = 22;// autoboxing
		y = 15;// autoboxing
		if ((c = x.compareTo(y)) == 0)
			System.out.println("x is equal to y");
		else if (c < 0)
			System.out.println("x is less than y");
		else
			System.out.println("x is greater than y");
		System.out.println("x + y = " + (x + y));// autounboxing
		//实际上是System.out.println("x + y = " + (x.intValue() + y.intValue());
	}
}
相关推荐
怀旧,3 分钟前
【Python】2. 基础语法(2)
开发语言·python
敲代码的瓦龙7 分钟前
C++?继承!!!
c语言·开发语言·c++·windows·后端·算法
非凡ghost12 分钟前
Pic手机拼图软件:创意拼图,轻松上手
android·智能手机·软件需求
武昌库里写JAVA14 分钟前
Quartus 开发可实现人工智能加速的 FPGA 系统
java·vue.js·spring boot·课程设计·宠物管理
沐知全栈开发16 分钟前
Django 视图 - FBV 与 CBV
开发语言
xujinwei_gingko17 分钟前
服务发现Nacos
java·服务发现
wirepuller_king27 分钟前
Python安装、pycharm配置和添加库下载
开发语言·python·pycharm
心想好事成32 分钟前
尚硅谷redis7 47-48 redis事务之理论简介
java·数据库·redis
雪风飞舞35 分钟前
Python解压多种格式压缩包
开发语言·python