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());
}
}