1、集合框架和泛型
1.1 为什么使用集合框架
学习Java基本时,都学过数组(Array)。数组的特点就是只能存储同一数据类型;固定长度;
//数组的声明
//数据类型[] 数组名称 = new 数据类型[长度];
int[] myArray = new int[5];
//数组的访问以及赋值,是通过数组下标来得到对应的数据元素(存储的数据)
myArray[0] = 12; //赋值
System.out.println(myArray[0]); //访问数组元素
假如我要保存一个班的学习,如数量是20;经过一段时间之后,班上又来了一位新同学?此时该如何处理??
String[] students = new String[20];
students[0] = "张小花";
....
students[19] = "刘德华";
//到后面来新同学难到我们就手动改数组的固定长度值吗?这样操作合不合理??
//为了能够实现班上不断插入新同学能够更好的管理这个数组固定长度那么我们就可以来学习使用
//集合框架
结论:如果并不知道程序运行时会需要多少对象(学生),或者需要更复杂方式存储对象(学生)——可以使用Java集合框架
1.2 JAVA集合框架
集合框架只是一个技术名词
,只不过对于这个集合框架Java提供了很多的接口和类供我们使用;同时,java中的集合框架都在java.util
包中,以及Collection集合都是数组类型唯独Map是键值对。
1.3 集合框架之间的区别
1). Collection接口存储一组不唯一
,无序的对象
分析: Collection保存的对象就好比把多个鸡蛋放入到一个篮子当中。篮子中的鸡蛋是没有序列号!不唯一
就是可以存储相同值;
2). List接口存储一组不唯一
,有序(按插入顺序进行标记)的对象
3). Set接口存储一组唯一
,无序的对象
4). Map接口存储一组键值
对象,提供key
到value
的映射(可以通过key拿到value值)
1.4 List\Set接口实现类
关于List的接口实现有很多,这里主要讲到ArrayList和LinkedList;
ArrayList实现了长度可变的数组,在内存中分配连续的空间,遍历元素和随机访问元素的效率比较高。
LinkedList采用链表存储方式,插入、删除元素时效率比较高。
上面类图讲到的是Collection、List、Set接口的方法,ArrayList、LinkedList都有一样的方法,只要我们自己使用就可以了。
总结:如果数据要频繁的插入和删除可以使用LinkedList,只是读取那么最好使用ArrayList
1.5 ArrayList案例
需求:使用ArrayList进行保存新闻数据对象;
- 存储新闻数据对象(新闻ID、标题、作者)
- 输出新闻数据对象总数
- 逐行打印新闻数据对象
分析:每一条新闻都可以理解为一个对象;而后再把这一些对象存储到我们学习的ArrayList集合当中。因此我们需要一个新闻类和一个测试类来完成
//这是新闻类,类有三个属性分别id、titleName、creater
//NewTitles.java
public class NewTitles {
private int id; //新闻标题
private String titleName; //新闻名称
private String creater; //作者
public NewTitles(int id, String titleName, String creater) {
this.id = id;
this.titleName = titleName;
this.creater = creater;
}
public NewTitles() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitleName() {
return titleName;
}
public void setTitleName(String titleName) {
this.titleName = titleName;
}
public String getCreater() {
return creater;
}
public void setCreater(String creater) {
this.creater = creater;
}
@Override
public String toString() {
return "NewTitles{" +
"id=" + id +
", titleName='" + titleName + '\'' +
", creater='" + creater + '\'' +
'}';
}
}
//测试类 NewTitleTest.java
import java.util.ArrayList;
import java.util.List;
public class NewTitleTest {
public static void main(String[] args) {
//创建多条新闻
NewTitles titles1 = new NewTitles(1, "我爷叫李刚刚", "警察叔叔,你不要来追我了!");
NewTitles titles2 = new NewTitles(2, "我爸叫李刚", "警察叔叔,你要来追我,我让你丢职!");
// 2、创建存储各类新闻标题的集合对象,要有一个东西来进行存储上面的新闻对象了
//ArrayList是List的实现类,所以默认就支持向上转型
List<NewTitles> arrayList = new ArrayList<NewTitles>(); //有了存储新闻对象的东西
//现在我们要考虑是,如何把新闻丢到这个arrayList的对象当中???
//ArrayList有一个方法add(param); 作用:将指定的元素追加到此列表的末尾
arrayList.add(titles1);
arrayList.add(titles2);
// 4、获取新闻标题的总数,ArrayList实现类有一个size()方法,是专门来获得此集合元素总数
System.out.println("新闻一共有" + arrayList.size() + "?");
//如何进行逐个遍历输出arrayList集合里的对象
//ArrayList最后都是toArray,也就是数组所以我们可以通过for的方式来进行实现
for (int i = 0; i < arrayList.size() ; i++) {
System.out.println(arrayList.get(i));
}
}
}
//输出
//新闻一共有2?
//NewTitles{id=1, titleName='我爷叫李刚刚', creater='警察叔叔,你不要来追我了!'}
//NewTitles{id=2, titleName='我爸叫李刚', creater='警察叔叔,你要来追我,我让你丢职!'}
1.6ArrayList和Colletion常用方法
方法名 | 说明 |
---|---|
boolean add(Object o) | 在列表的末尾顺序添加元素,起始索引位置从0开始 |
void add(int index,Object o) | 在指定的索引添加元素。索引位置必须介于0和列表个数之间 |
int size() | 返回列表中的元素个数 |
Object get(int index) | 返回指定索引位置处的元素,取出的元素是Object类型,使用前需要进行强制类型转换 |
boolean contains(Object o) | 判断列表中是否存在指定元素 |
boolean remove(Object o) | 从列表中删除元素 |
boolean remove(int index) | 从列表删除指定的元素 |
collection的常用方法
方法名 | 说明 |
---|---|
void clear() | 从集合中删除索引元素(可选操作) |
boolean isEmpty() | 如果集合不包含元素,则返回true |
lterator iterator() | 返回此集合中元素的迭代器 |
Object[] toArray() | 返回一个包含此集合中所有元素的数组 |
boolea equals(Object o) | 将指定的对象与此集合进行比较以获得相等性 |
1.7 LinkedList 案例
需求:使用LinkedList进行保存新闻数据对象;
1.存储新闻数据对象(新闻ID、标题、作者)
2.输出新闻数据对象总数
3.逐行打印新闻数据对象
分析: 每一条新闻都可以理解为一个对象;然后再把这一些对象储存到我们学习的LinkedList集合当中。因此我们需要一个新闻类和一个测试类来完成
package H09one.集合框架和泛型;
/**
* 新闻类
*/
public class Serializable {
private int id;
private String tname;
private String creator;
@Override
public String toString(){
return "Serializable{"+
"id="+ id +
",tname"+tname+'\''+
",creator="+creator+'\''+
'}';
}
public Serializable() {
}
public Serializable(int id, String tname, String creator) {
this.id = id;
this.tname = tname;
this.creator = creator;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
}
package H09one.集合框架和泛型;
import java.util.Collection;
import java.util.LinkedList;
public class NewTitleTest1 {
public static void main(String[] args) {
//不管做什么事情,我们一定要清楚我们的初衷是什么?
//此实例就是通过LinkedList来进行储存新闻对象
//在储存之前我们是不是有新闻对象没有?? 答案:没有,要先创造
//当有新闻对象时,我们是不是有一些东西可以来储存这一些对象? 答案:没有,也要创建
//1.创建新闻对象
NewTitles title1 = new NewTitles(1,"广州疫情很严重","长沙新华网");
NewTitles title2 = new NewTitles(2,"大中华各个地区各个村全面进行疫苗接种","长沙新华网");
//2.是否有LinkedList对象进行储存新闻对象
// Collection list = new LinkedList();//子类对象用父类转型
LinkedList list = new LinkedList();
//3.创建用来储存新闻对象的空间,接下来考虑如何入到这个空间当中?
list.add(title1);
list.add(title2);
//4.获得linkedList一个保存了几个对象
System.out.println("size="+list.size());
// list.remove(title1);//删除对象为title1的元素
list.remove(1);
//5.循环打印索引linkedList当中的对象
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
1.8 LinkedList常用方法
方法名 | 说明 |
---|---|
void addFirst(Object o) | 在列表的首部添加元素 |
void addLast(Object o) | 在列表的末尾添加元素 |
Object getFirst() | 返回列表中的第一个元素 |
Object getLast() | 返回列表的最后一个元素 |
Object removeFirst() | 删除列表的第一个元素 |
Object removeLast() | 删除列表的最后一个元素 |
1.9 Set接口
1.Set 接口存储一组唯一
且无序的对象
2.HashSet是Set接口常用的无序实现类
3.Set中存放对象的引用
package H09one.集合框架和泛型;
import java.util.HashSet;
import java.util.Set;
public class NewTitleTest2 {
public static void main(String[] args) {
//得到一个HashSet的实例
Set set = new HashSet();
//得到要进行保存的字符串对象
String php = new String("PHP");
String i_love_java = new String("I love java");
String friendIsJava = new String("My GirlsFriend Is Java");
//存放到HashSet的集合当中来
set.add(php);
set.add(i_love_java);
set.add(friendIsJava);
//打印HashSet中有几个对象
System.out.println(set.size());
}
}
1.9.1 Set保存的对象只能是唯一
package H09one.集合框架和泛型;
import java.util.HashSet;
public class hashsetTest {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
String java = new String("java");
String java2 = java;//把java变量的内存地址传递给了java2这个变量
String java3 = new String("java");
hashSet.add(java);
hashSet.add(java2);
hashSet.add(java3);
System.out.println("hashSet count=" + hashSet.size());
}
}
1.10 迭代器
在我们学习姐框架的时,对于所有的列表均可使用迭代器来进行元素遍历。接口都会提供访问入口获得Iterator对象。
在Collection源码中我们可以找到定义的获得迭代器对象的接口
/**
* Returns an iterator over the elements in this collection. There are no
* guarantees concerning the order in which the elements are returned
* (unless this collection is an instance of some class that provides a
* guarantee).
*
* @return an <tt>Iterator</tt> over the elements in this collection
*/
Iterator<E> iterator();
HashSet.java中对iterator的接口实现
/**
* Returns an iterator over the elements in this set. The elements
* are returned in no particular order.
*
* @return an Iterator over the elements in this set
* @see ConcurrentModificationException
*/
public Iterator<E> iterator() {
return map.keySet().iterator();
}
HashSet中对于获得Iterator对象,实际上map字典的keySet集合。(无序集合的索引key组合而成新集合)
案例:
package H09one.集合框架和泛型;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class IteratorHashSetTest {
public static void main(String[] args) {
//1.创建新闻对象
NewTitles title1 = new NewTitles(1,"广州疫情很严重","长沙新华网");
NewTitles title2 = new NewTitles(2,"大中华各个地区各个村全面进行疫苗接种","长沙新华网");
Set hashSet = new HashSet();
hashSet.add(title1);
hashSet.add(title2);
System.out.println("size = "+hashSet.size());
//通过集合当中的Iterator方法得到此集合的迭代器对象
Iterator iterator = hashSet.iterator();
//hashNext判断是否还有下一个对象
//Next就是当前循环的对象
while (iterator.hasNext()){
NewTitles next = (NewTitles) iterator.next();
System.out.println(next);
}
for (Object obj:hashSet){
NewTitles obj1 = (NewTitles) obj;
System.out.println("obj1 = "+obj1);
}
}
}
1.11Map 接口
Map是将键映射到值的对象。Map不能包含重复的键;每一个键可以映射到最多一个值。允许将映射的内容作为一级键;值的集合;键值映射集合;
package H09one.Map;
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
public static void main(String[] args) {
//1.使用最简单的HashMap来实现简称和国家全程的映射
Map hashMap = new HashMap();
//2.在有了能保存数据的对象空间之后我们如何实现数据的存储?
hashMap.put("CN","中华人民共和国");
hashMap.put("US","美利坚共和国");
hashMap.put("RU","俄罗斯联邦");
hashMap.put("FR","法兰西共和国");
//3.显示"CN"对应国家的中文全称
String cn = (String) hashMap.get("CN");
System.out.println("CN对应的国家是:"+cn);
//4.显示集合中的元素个数
System.out.println("HashMap中一共有:"+hashMap.size());
//5.两次判断Map是否存在"FR"键
System.out.println("Map中包含FR的key吗?"+hashMap.containsKey("FR"));
hashMap.remove("FR");
System.out.println("Map中包含FR的key吗?"+hashMap.containsKey("FR"));
//6.分别显示键集、值集和键值对集
System.out.println(hashMap.keySet());
System.out.println(hashMap.values());
System.out.println(hashMap);
//7.清空HashMap,并判断是否有内容
hashMap.clear();
System.out.println(hashMap.isEmpty());
}
}
/*
结果:
CN对应的国家是:中华人民共和国
HashMap中一共有:4
Map中包含FR的key吗?true
Map中包含FR的key吗?false
[RU, CN, US]
[俄罗斯联邦, 中华人民共和国, 美利坚共和国]
{RU=俄罗斯联邦, CN=中华人民共和国, US=美利坚共和国}
true
*/
1.11.1 Map常用方法
方法名 | 说明 |
---|---|
Object put(Object key,Object value) | 以"键-值"对的方式进行存储,存放到map对象当中去 |
Object get(Object key) | 根据键返回相关联的值,如果不存在指定的键,返回null |
Object remove(Object key) | 删除由指定的键映射的"键-值对" |
int size() | 返回map集合对象元素的个数 |
Set keySet() | 返回键的集合 |
Collection values() | 返回值的集合 |
boolean contaisKey(Object key) | 如果存在由指定的映射的"键-值对",返回true |
Map.Entry entrySet() | 返回此Map中包含的映射Set ,就是Map集合当中的一个子项 |
1.11.2 遍历
方法1:通过迭代器Iterator进行循环遍历
package h09.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HashMapListFor {
public static void main(String[] args) {
//1.使用最简单的HashMap来实现简称和国家全程的映射
Map hashMap = new HashMap();
//2.在有了能保存数据的对象空间之后我们如何实现数据的存储?
hashMap.put("CN","中华人民共和国");
hashMap.put("US","美利坚共和国");
hashMap.put("RU","俄罗斯联邦");
hashMap.put("FR","法兰西共和国");
//使用迭代器来进行遍历
// Iterator<Map.Entry<Integer,String>> entries = hashMap.entrySet().iterator();
Iterator iterator = hashMap.entrySet().iterator();
while (iterator.hasNext()){
//得到一个HashMap对象,需要强制类型转换,但不知道
//如何告诉我们编译器,所以Map一个方法就是entry方式来进行转换
//iterator.next();
//entry就是HashMap集合的子项,子项包含着key和value
Map.Entry entry = (Map.Entry) iterator.next();
System.out.println(entry.getKey());
}
}
}
/*
结果:
RU
CN
FR
US
*/
方法2:键值对方式
package h09.Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class HashMapListFor1 {
public static void main(String[] args) {
//1.使用最简单的HashMap来实现简称和国家全程的映射
Map hashMap = new HashMap();
//2.在有了能保存数据的对象空间之后我们如何实现数据的存储?
hashMap.put("CN","中华人民共和国");
hashMap.put("US","美利坚共和国");
hashMap.put("RU","俄罗斯联邦");
hashMap.put("FR","法兰西共和国");
Collection values = hashMap.values();
for (Object obj:values){
System.out.println("obj = " + (String)obj);
}
}
}
/*
结果:
obj = 俄罗斯联邦
obj = 中华人民共和国
obj = 法兰西共和国
obj = 美利坚共和国
*/
1.12 泛型
将对象得到类型转换作为参数,指定到其他类或者方法上,从而保证类型换换的安全性和稳定性。
package h09.Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class GenerityTest {
public static void main(String[] args) {
Map map = new HashMap();
map.put("key1","value1");
map.put("key4",1212);
map.put("key2","value2");
map.put("key3","value3");
//循环遍历
Collection collection = map.values();
for (Object ob : collection) {
System.out.println((String)ob);
}
}
}
/*
输出:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
value1
value2
at h09.Map.GenerityTest.main(GenerityTest.java:17)
value3
*/
从上面实例我们得到结论,往map集合中put数据时我们可以任意为之。但是在进行遍历是要进行数据类型换换;当我们指定到某一种数据类型时,实际情况map存储的数据类型就有很多;可以存储int、String、double等等。这样一来我们就不好类型转换操作了。为了解决这一问题。我们就要学习泛型
,泛型
的出现可以指定存储数据类型。
package h09.Map;
public abstract class Pet {
protected String name = "无名氏";
protected int health = 100;//健康值
protected int love = 0; //亲密度
//定义吃的抽象方法
public abstract void eat();
public Pet(String name, int health, int love) {
this.name = name;
this.health = health;
this.love = love;
}
public Pet(String name) {
}
public String getName() {
return name;
}
public int getHealth() {
return health;
}
public int getLove() {
return love;
}
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
", health=" + health +
", love=" + love +
'}';
}
}
package h09.Map;
public class Dog extends Pet {
private String strain; //品种
public Dog(String name,String strain) {
super(name);
this.strain = strain;
}
public String getStrain() {
return strain;
}
@Override
public void eat() {
super.health = super.health + 3;
System.out.println("狗狗" + super.name +"吃饱了!健康值增加3。");
}
@Override
public String toString() {
return "Dog{" +
"strain='" + strain + '\'' +
", name='" + name + '\'' +
", health=" + health +
", love=" + love +
'}';
}
}
package h09.Map;
import java.util.ArrayList;
import java.util.List;
public class DogListTest {
public static void main(String[] args) {
//1.创建多个狗狗对象
Dog dog1 = new Dog("欧欧", "雪娜瑞");
Dog dog2 = new Dog("亚亚", "拉布拉多");
Dog dog3 = new Dog("美美", "雪娜瑞");
Dog dog4 = new Dog("菲菲", "拉布拉多");
//2.创建ArrayList集合对象并把多个狗狗对象并把多个狗狗对象放入其中
//List arrayList = new ArrayList();此实现方式可以存放任意数据
List<Dog> dogs = new ArrayList<>();
dogs.add(dog1);
dogs.add(dog2);
dogs.add(dog3);
dogs.add(dog4);
//3.显示第三个元素的信息
Dog dog = dogs.get(2);
System.out.println(dog);
//4.使用foreach语句遍历dogs对象
for (Dog d : dogs) {
d.eat();
System.out.println(d);
}
}
}
/*
结果:
Dog{strain='雪娜瑞', name='无名氏', health=100, love=0}
狗狗无名氏吃饱了!健康值增加3。
Dog{strain='雪娜瑞', name='无名氏', health=103, love=0}
狗狗无名氏吃饱了!健康值增加3。
Dog{strain='拉布拉多', name='无名氏', health=103, love=0}
狗狗无名氏吃饱了!健康值增加3。
Dog{strain='雪娜瑞', name='无名氏', health=103, love=0}
狗狗无名氏吃饱了!健康值增加3。
Dog{strain='拉布拉多', name='无名氏', health=103, love=0}
*/
泛型特征:泛型集合内的元素类型;泛型结合中的数据不在转换为Object;
深入了解
package h09.Map;
import java.util.*;
public class HashMapListFor2 {
public static void main(String[] args) {
//1.使用最简单的HashMap来实现简称和国家全程的映射
Map hashMap = new HashMap();
//2.在有了能保存数据的对象空间之后我们如何实现数据的存储?
hashMap.put("CN","中华人民共和国");
hashMap.put("US","美利坚共和国");
hashMap.put("RU","俄罗斯联邦");
hashMap.put("FR","法兰西共和国");
//3.使用迭代器来完成遍历
Iterator<Map.Entry<String,String>> iterator = hashMap.entrySet().iterator();
while (iterator.hasNext()){
//得到一个Object对象,需要强制类型转换,但不知道
//如何告诉我们编译器,所以Map一个方法就是entry方式来进行转换
//iterator.next();
//entry就是HashMap集合的子项,子项包含着key和value
Map.Entry entry = (Map.Entry) iterator.next();
System.out.println(entry.getKey());
}
}
}
/*
结果:
RU
CN
FR
US
*/
1.13 Collections
Java集合框架将针对不同数据结构算法的实现都保存在工具类中(Collections);Collections类定义了一个系列用于操作集合的静态方法;Colletions和Collection不同,前者试剂盒的操作类,后者是集合接口Collections就是用来操作集合的。
package h09.Map;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class CollectionsTest {
public static void main(String[] args) {
//创建集合
ArrayList<String> list = new ArrayList<>();
//增加10不同的单词
list.add("this");
list.add("is");
list.add("collection");
list.add("test");
list.add("and");
list.add("we");
list.add("can");
list.add("learn");
list.add("how");
list.add("to");
//打印输出集合中最大元素和最小元素
System.out.println("list中最大值:" + (String)Collections.max(list));
System.out.println("list中最小值:" + (String)Collections.min(list));
//按升序打印输出集合中所有元素
Collections.sort(list);
for (String ob : list) {
System.out.println(ob);
}
//指定元素进行搜索,检索到了返回1否则为-2
System.out.println(Collections.binarySearch(list,"caln"));
//按升序打印输出集合中所有元素
Collections.reverse(list);
for (String ob : list) {
System.out.println(ob);
}
}
}
/*结果:
list中最大值:we
list中最小值:and
and
can
collection
how
is
learn
test
this
to
we
-2
we
to
this
test
learn
is
how
collection
can
and
*/
1.12.1 Collections排序
Collections类可以对集合进行排序、查找和替换操作。实现一个类的对象之间比较大小,改类实现comparable
接口重写compareTo()
方法
package h09.Map;
public class Student implements Comparable {
private int number = 0; //学号
private String name = ""; //姓名
private String gender = ""; //性别
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public int compareTo(Object o) {
Student student = (Student) o;
if (student.number == this.number){
//如果学号相同,那么两者就是相等的
return 0;
}else if (this.number > student.getNumber()){
//如果这个学生的学号大于传入学生的学号
return 1;
}else{
//如果这个学生的学号小于传入学生的学号
return -1;
}
}
}
package h09.Map;
import java.util.*;
public class StudentSortTest {
public static void main(String[] args) {
Student student1 = new Student();
student1.setNumber(5);
Student student2 = new Student();
student2.setNumber(1);
Student student3 = new Student();
student3.setNumber(4);
Student student4 = new Student();
student4.setNumber(1);
List<Student> students = new ArrayList<>();
students.add(student1);
students.add(student2);
students.add(student3);
students.add(student4);
System.out.println("----------排序前----------");
Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next().getNumber());
}
//使用Collections的sort方法对list进行排序
System.out.println("----------排序后----------");
Collections.sort(students);
iterator = students.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next().getNumber());
}
}
}
总结:
1.Collection、List、Set、Map接口的联系和区别
2.ArrayList和LinkedList的异同之处及各自的应用场合
3.遍历集合的方法
4.泛型集合用法及好处
2、枚举
枚举是指由一组固定常量组成的类型;如一年的4个季节,一年的12个月份,一个星期的7天,方向有东南西北等。都可以作为枚举。Java枚举类事业enum关键字来定义,各个常量使用逗号,来分割。
//语法
<access-modifier> enum <enum-type-name> {
//List of comma separated names of enum constants
}
<access-modifier>
与类的访问修饰符相同:public
,private
,protected
,package-leve1
,<enum-type-name>
是有效的Java
标识符。枚举类型的主体放在大括号中,名称后面。主体可以通过有逗号分隔的常数和其他元素的列表,例如实例变量,方法等。
2.1 枚举类型的实例
声明一个枚举类Gender,有两个常量分别为MALE和FEMALE
public enum Gender {
MALE,FEMALE
}
/*
*定义名字叫Gender的枚举类
*/
public enum Gender {
//MALE,FEMALE
男, 女;
}
public class GenderEnumTest {
public static void main(String[] args) {
Gender male = Gender.男;
System.out.println(male);
}
}
//输出:男
枚举类型作为对象属性数据类型时,随意赋值会有以下错误
enum Gender{
Male,Female
}
public class StudentsTest {
public Gender sex;
public static void main(String[] args) {
StudentsTest studentsTest = new StudentsTest();
studentsTest.sex = "ddd";
studentsTest.sex = Gender;
}
}
//Error:(12, 28) java: 不兼容的类型: java.lang.String无法转换为
// www.derek.enums.Genders
使用枚举类型对象类型安全、易于输入和代码清晰。
为大数据岗位课程三个学习阶段定义枚举:L1、L2、L3,分别表示第一、二、三阶段编程输出每个单元的学习目标
L1:大数据开发工程师
L2:大数据挖掘工程师
L3:大数据架构师
public class JavaStudentsTest {
/*
类中的枚举类
*/
public enum Leve1{
L1,L2,L3;
}
public void show(Leve1 l){
switch (l){
case L1:
System.out.println("大数据开发工程师");
break;
case L2:
System.out.println("大数据挖掘工程师");
break;
case L3:
System.out.println("大数据架构师");
break;
default:
System.out.println("你没在我们学校");
break;
}
}
public static void main(String[] args) {
JavaStudentsTest test = new JavaStudentsTest();
test.show(Leve1.L1);
}
}
//输出:大数据开发工程师
3、String类
https://www.cnblogs.com/zhangyinhua/p/7689974.html#_label0
可以去此网站了解!
String 类代表字符串,Java 程序中的所有字符串字面值(如“abc”)都作为此类的实例实现。字符串是常量,他们的值在创建之后不会被更改。字面量类型的变量在声明和赋值时,如果想对其值进行更新那么更新之后,原先的值就会进入到VM垃圾回栈当中。相当于是一个全新的变量。字符串缓冲区支持可变的字符串。因 String 对象是不可变的,所以可以共享。
//String 字符串类源码
public class StringTest2
implementsjava.io.Serializable,Comparable<String>,CharSequence{
//...
}
//当我们进行new String() 时,实际上String类内部是这样处理的
//在String类当中,value是String类的一个属性,而这个value属性的数据类型是一个数组
//String当中的hash是这个value数组的第一个元素
//value属性的源码
private final char value[];
public String(){
this.value = "".value;
}
//hash的源码
/** Cache the hash code for the string*/
private int hash;// Default to 0
3.1创建字符串对象的两种法师及区别
1.直接赋值创建字符串对象,此方式创建的字符串对象是保存在内容的栈当中也就是常量池
String name = "张三";
2.通过构造方法来创建字符串对象,此方法创建的字符串队形是保存在内存的堆当中,主要是通过new关键得到的
String neme = new String("张三");
字符串对象的比较:
package h09.String类;
public class StringTest {
public static void main(String[] args) {
String str1 = "laowang";
String str2 = new String("laowang");
String str3 = str2;
String str4 = "laowang";
/*
Java中比较运算符"=="
基本数据类型:比较的是基本数据类型的值是否相同
引用数据类型:比较的是引用数据类型的地址值是否相同
结:String类对象"=="比较,比较的是地址,而不是内容
*/
System.out.println(str1 == str2);//地址不同,false
System.out.println(str1 == str3);//地址不同,false
System.out.println(str3 == str2);//地址不同,true
System.out.println(str1 == str4);//地址不同,true
}
}
内存中的示意图:
只是为了方便理解,实际意义实际意义上在内存里只有一个“laowang” 1.字面量传创建的UI想 2.通过new关键创建的对象所表达的方式。
上面的图说明了通过字面量和new关键字创建对象内存示意图
深入了解String str = “abc”;
(1)当常量池中不存在"abc"这个字符串的引用,在堆内存中new一个String对象,复制这个对象加入常量池,返回常量池中的对象。
(2)当常量池中存在"abc"这个字符串对象,str指向这个对象的引用;
3.2 String中intern方法
(1)当常量池中不存在"abc"这个字符串的引用,将这个对象加入常量池,返回常量池中的对象。
(2)当常量池中存在"abc"这个字符串对象,返回这个对象的引用;
package h09.String类;
public class StringTest1 {
public static void main(String[] args) {
//在创建字符串对象时通过字符串对象intern方法吧"laowang"压入到常量池中,
//并返回地址,此时常量池中已经有了"laowang",str == str1
String str = new String("laowang").intern();
String str1 = "laowang";
System.out.println(str1 == str);
}
}
3.3深入理解字面量和new创建的内存示意图
package h09.String类;
public class StringTest2 {
public static void main(String[] args) {
String tmp1 = new String("1");
String tmp2 = "1";
System.out.println(tmp1 == tmp2);//false
}
}
上面代码tmp2是字面量创建的字符串对象实现,最终“1“这个常量会被放置常量池
当中,而不经过内存堆。而通过new关键字创建的字符串对象实例,则一定会过内存堆,那么内存堆的对象整整保存的是”1“常量池地址也就是地址引用
。String内存参考文献
3.4 String常用方法
4、包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
剖析:
1:需要明确的是这些包装类都是一个java类,所以这些类的对象实例都因存放在堆中
2.所有的包装类都是final修饰的,也就是它们都是无法被继承和重载
3.包装类实例化Integer i = new Integer(1);
,new Integer(1)
得到的对象是直接放在堆中并返回存放引用(地址),然后再把这个引用(地址)复制给变量i
。
4.1 基本数据类型和包装类的区别
-
作为类变量或是类成员变量的默认值不同,如Integer默认值为null,int的默认值为0
-
在JVM的内存位置不同,包装类的对象实例在堆上分配,基本数值类型则有如下3中情况:
1.在方法方法中时,存放在虚拟机栈的栈帧中的局部变量表中
2.作为类的成员变量时,存放在栈中
3.作为类的静态变量/常量,存在方法区中
-
包装类型可用于泛型,而基本类型不可以。因为泛型在编译时会进行类型擦除,最后只保留原始类型,而原始类型只能是
Object
类及其子类——基本数据类型是个特例。 -
包装类必须实例化之后才能是使用(java 1.5会自动的进行装箱),基础类型则不用。
4.2 装箱和拆箱
把基本类型转换成包装类型的过程叫做装箱(boxing)
。反之,把包装类型转换成基本类型叫做拆箱(unboxing).java SE5
以后提供了自动装箱与自动拆箱的功能。
Integer integeVal = 10;//自动装箱
int intVal = integerVal;//自动拆箱
分析:
- 地洞装箱是通过
Integer.valueOf()
完成的 - 自动拆箱是通过
Integer.intValue()
完成的
package h09.packages;
public class Demo1 {
public static void main(String[] args) {
//分别对下面两行代码进行装箱处理
//Integer intone1 = Integer.valueOf(1);//自动装箱
//Integer intone2 = Integer.valueOf(1);//自动装箱
//new Integer(1) -> 这个就是手动进行装箱处理
Integer intOne1 = 1;
Integer intOne2 = 1;
Integer intOne3 = new Integer(1);
Integer two = 2;
Integer three = 2;
Integer intNum1 = 321;
Integer intNum2 = 321;
int intNum3 = 321;
Long longTwo = 2l;
long ltwo = 21;
//== 比较包装类实例化对象地址,IntegerCache缓存Integer.valueOf()入口的 -128 ~ 127
System.out.println(intOne1 == intOne2);//true
System.out.println(intOne1 == intOne3);//false
//因为自动装箱会经过IntegerCache缓存装箱对象,但是做大只能是127
System.out.println(intNum1 == intNum2);//false
//值是一样的,1.保证b是和啊a一样的包装类 2.比较数值
System.out.println(intOne1.equals(intOne3));//true
System.out.println(intOne1.equals(intOne2));//true
//==一边有表达式或者基本数据类型是,会先进行拆箱,然后比较具体数值
System.out.println(three == (intOne1+two));//true
System.out.println(intNum1 == intNum3);//true
//intNum3进行自动装箱了
System.out.println(intNum1.equals(intNum3));//true
//类型不一致
System.out.println(two.equals(longTwo));//false
//自动装箱,类型不一致
System.out.println(two.equals(ltwo));//false
//自动拆箱,然后比较具体数值
System.out.println(longTwo == intOne1 + intOne1);//true
//long longTwo拆箱成int类型就是2
System.out.println(longTwo.longValue()+"===="+longTwo.intValue());//手动拆箱
System.out.println(intOne1.intValue());//手动拆箱
//自动拆箱.类型数值不一致
System.out.println(longTwo.equals(intOne1 + intOne1));//false
//手动装箱
System.out.println(Long.valueOf(intOne1.longValue()+intOne1.longValue()));
//容量小的类型可自动(隐式)转换为容量大的数据类型,byte,short,char → int → long → Float → double
System.out.println(2 == 2l);//true
System.out.println(2 == 2d);//true
System.out.println((short)2 == 2f);//true,(int) 2 先强转成(short)2,然后再自动转成float
}
}