Collection集合习题
练习:Collection集合统计元素出现次数
给定以下代码,请定义方法listTest()统计集合中指定元素出现的次数,如”a”: 2,”b”: 2,”c” :1, “xxx”:0
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("a");
list.add("b");
list.add("b");
list.add("c");
System.out.println("a:"+listTest(list, "a"));
System.out.println("b:"+listTest(list, "b"));
System.out.println("c:"+listTest(list, "c"));
System.out.println("xxx:"+listTest(list, "xxx"));
}
private static int listTest(Collection<String> list, String s){
int count = 0;
for (String string : list){
if (s.equals(string)){
count++;
}
}
return count;
}
练习:Collection集合数组转集合
定义一个方法,要求此方法把int数组转成存有相同元素的集合(集合里面的元素是Integer),并返回。
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
ArrayList<Integer> arrayList = listTest(arr);
System.out.println(arrayList);
}
public static ArrayList<Integer> listTest(int[] arr){
ArrayList<Integer> list = new ArrayList<Integer>();
for (Integer a : arr){
list.add(a);
}
return list;
}
练习:Collection集合集合转数组
定义一个集合,并把集合(集合里面的元素是Integer)转成存有相同元素的数组,并将结果输出在控制台。(可以使用Object[]数组类型接收转换的数组)
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
Object[] obj = list.toArray();
for (int i = 0; i < obj.length; i++) {
System.out.println(obj[i]);
}
}
public Object[] toArray()
以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。返回的数组将是“安全的”,因为该列表不保留对它的引用。 (换句话说,这个方法必须分配一个新的数组)。 因此,调用者可以自由地修改返回的数组。
练习:Collection集合contains()方法使用
定义一个方法listTest(ArrayList < String > a1, String s),要求使用contains()方法判断a1集合里面是否包含s。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("itcast");
list.add("itheima");
list.add("java");
System.out.println(listTest(list,"Java"));
}
private static boolean listTest(ArrayList<String> a1, String s){
if (a1.contains(s)){
return true;
}
return false;
}
练习:Collection集合isEmpty()方法的使用
定义一个方法listTest(ArrayList< String > a1), 要求使用isEmpty()判断a1里面是否有元素。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("1");
System.out.println(listTest(list));
}
public static boolean listTest(ArrayList<String>a1){
if (a1.isEmpty()){
return true;
}
return false;
}
练习:简述迭代器的实现原理
当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。
练习:Collection集合返回首次出现索引
定义一个方法listTest(ArrayList< Integer > a1, Integer s),要求返回s在a1里面第一次出现的索引,如果s没出现过返回-1。
public static void main(String[] args) {
//定义集合,添加数据
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(listTest(list,5));
}
private static int listTest(ArrayList<Integer>a1, Integer s){
for (int i = 0; i < a1.size(); i++) {
if (a1.get(i).equals(s)){
return i;
}
}
return -1;
}
File类&递归&FileFilter习题
练习:检查文件是否存在,文件的创建
描述:检查D盘下是否存在文件a.txt,如果不存在则创建该文件。
操作步骤:
1.使用绝对路径创建对象关联到D盘的a.txt。
2.通过文件对象方法判断文件是否存在。
3.不存在则调用创建文件的方法创建文件。
public static void main(String[] args) throws IOException {
File f = new File("D:\\Clash\\aaa.txt");
if (!f.exists()){
f.createNewFile();
}
}
练习:单极文件夹的创建
描述:在D盘下创建一个名为bbb的文件夹。
操作步骤:
1.创建文件对象指定路径为d:/bbb
2.调用文件对象创建文件夹的方法
public static void main(String[] args) throws IOException {
File f = new File("D:\\Clash\\aaa");
// File f = new File("D:\\Clash\\aaa\\bbb");
f.mkdir();
// f.mkdirs(); 创建多级文件夹
}
练习:删除文件和文件夹
描述:将D盘下a.txt文件删除。将D盘下aaa文件夹删除,要求文件夹aaa是一个空文件夹。
操作步骤:
1.创建文件对象关联路径:d:/a.txt
2.调用文件对象删除文件的方法
3.创建文件对象关联路径:d:/aaa
4 调用文件对象删除文件夹的方法.
public static void main(String[] args) {
// 创建文件对象
File f = new File("d:/a.txt");
// 删除文件
f.delete();
// 创建文件夹对象
File dir = new File("d:/aaa");
// 删除文件夹
dir.delete();
}
获取文件信息:文件名,文件大小,文件的绝对路径,文件的父路径
描述:获取D盘aaa文件夹中b.txt文件的文件名,文件大小,文件的绝对路径和父路径等信息,并将信息输出在控制台。
操作步骤:
public static void main(String[] args) {
// 创建文件对象
File f = new File("D:\\Clash\\a.txt");
// 获得文件名
String filename = f.getName();
// 获得文件大小
long filesize = f.length();
// 获得文件的绝对路径
String path = f.getAbsolutePath();
// 获得父文件夹路径,返回字符串
String parentPath = f.getParent();
// 获得父文件夹路径,返回文件对象
File parentFile = f.getParentFile();
// 输出信息
System.out.println("文件名:" + filename);
System.out.println("文件大小:" + filesize);
System.out.println("文件路径:" + path);
System.out.println("文件父路径:" + parentPath);
System.out.println("文件父路径:" + parentFile);
}
练习:文件夹或文件的判断
描述:
1.判断File对象是否是文件,是文件则输出:xxx是一个文件,否则输出:xxx不是一个文件。
2.判断File对象是否是文件夹,是文件夹则输出:xxx是一个文件夹,否则输出:xxx不是一个文件夹。(xxx是文件名或文件夹名)
操作步骤:
1.创建两个文件对象分别关联到不同的文件,比如:d:/a.txt,d:/aaa
2.调用文件对象的判断是否是文件或是否是文件夹的方法
3.获得文件名,根据判断结果输出信息。
public static void main(String[] args) {
File f = new File("D:\\Clash\\a.txt");
if (f.isFile()){
System.out.println(f.getName() + "是文件");
}else {
System.out.println(f.getName() + "不是文件");
}
File f2 = new File("D:\\Clash");
if (f2.isDirectory()){
System.out.println(f2.getName() + "是文件夹");
}else{
System.out.println(f2.getName() + "不是文件夹");
}
}
练习:文件夹的获取方式
描述:
获取指定文件夹下所有的文件,并将所有文件的名字输出到控制台。
注意:不包含子文件夹下的文件
操作步骤:
1.创建文件对象关联到指定文件夹,比如:c:/aaa
2.调用文件对象的listFiles方法获得文件数组
3.遍历文件数组将每一个文件的名字输出到控制台
public static void main(String[] args) {
File f = new File("D:\\Clash");
File[] files = f.listFiles();
for (File file : files){
System.out.println(file.getName());
}
}
List集合&Set集合习题
练习:List接口的特点
简述List接口的特点
★ 它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的读取顺序按照11、22、33的顺序完成的
★ 它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)
★ 集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素
练习:hashCode和equals方法
请简述HashSet去除重复元素的原理
★ 调用被添加元素的hashCode(), 和HashSet中已有元素的hasCode比较是否相同
★ 如果不同,直接存储
★ 如果相同,调用equals方法比较是否相同
★ 不相同,直接存储元素
★ 相同,认为是同一元素,不存储
练习:数据结构
简述常见的数据结构中元素的存储特点
★ 栈:stack,又称堆栈,对元素的存取特点是先进后出。即,存进去的元素,要在后它后面的元素一次取出后,才能取出该元素
★ 队列:queue,简称队,对元素的存取特点是先进先出。即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素
★ 数组:Array,是有序的元素序列,对元素的存储特点是:
1,查找元素快:通过索引,可以快速访问指定位置的元素
2.增删元素慢
(1).指定索引位置增加元素:需要创建一个新数组,将指定元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置
(2).指定索引位置删除元素:需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中
★ 链表:linkedlist 对元素的存取有如下的特点:
**(1).**多个结点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的 右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
**(2).**查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素。
(3).增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可。
练习:Comparable和Comparator比较器
简述 Comparable
和 Comparator
两个接口的区别
Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo
方法被称为它的自然比较方法。只能再类中实现compareTo()
一次,不能经常修改的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort
或 Arrays.sort
从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
练习:LinkedList方法的使用
根据要求练习LinkedList方法:
(1).基本方法:add, set, get, remove, clear, size等方法;
(2).特有方法:addFirst, addLast, getFirst, getLast, removeFirst, removeLast, push, pop, clear等方法。
(1).基本方法
public static void main(String[] args) {
// 1.创建LinkedList
LinkedList<String> arr = new LinkedList<String>();
// 2.使用add方法添加元素
arr.add("西门吹雪");
arr.add("西门吹雪");
arr.add("西门吹雪");
arr.add("西门吹风");
arr.add("西门吹水");
// 3.使用add方法在指定索引添加元素
arr.add(2, "西门吹雨");
// 4.使用set方法修改指定位置索引
arr.set(0, "东门");
for (String str : arr) {
System.out.println(str);
}
System.out.println("--------------");
// 5.使用get方法获取指定索引的元素
System.out.println(arr.get(1));
// 6.使用size方法获取集合大小
System.out.println(arr.size());
// 7.使用remove方法删除指定索引的元素
arr.remove(3);
// 8.使用clear清空集合中的元素
arr.clear();
System.out.println(arr);
}
}
(2).特有方法
public static void main(String[] args) {
// 1.创建LinkedList
LinkedList<String> linked = new LinkedList<String>();
// 2.使用add方法添加元素
linked.add("周杰伦");
linked.add("周星驰");
linked.add("周华健");
linked.add("周润发");
// 3.使用addFirst添加元素到集合最前面
linked.addFirst("周传雄");
// 4.使用addLast添加元素到集合最后面
linked.addLast("周渝民");
System.out.println(linked);
// 5.使用getFirst获取集合第一个元素
System.out.println(linked.getFirst());
// 6.使用getLast获取集合最后一个元素
System.out.println(linked.getLast());
// 7.使用removeLast删除集合第一个元素
String first = linked.removeFirst();
System.out.println(first);
// 8.使用removeLast删除集合最后一个元素
String last = linked.removeLast();
System.out.println(last);
System.out.println(linked);
// 9.使用pop弹出第一个元素
String p = linked.pop();
System.out.println(p);
// 10.使用push在集合开头插入元素
linked.push("周立波");
System.out.println(linked);
// 11.使用clear清空集合
linked.clear();
System.out.println(linked);
}
}
练习:HashSet存储自定义类型
定义人类,包含姓名和年龄属性。创建4个人存储到HashSet中,姓名和年龄相同的人看做同一人不存储。
// 1.定义Person类.包好姓名年龄属性,重写hashCode()和equals()方法
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name != null ? name.equals(person.name) : person.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
ublic class HashSetTest01 {
public static void main(String[] args) {
// 2.创建HashSet用于存储Person类型
HashSet<Person> hashSet = new HashSet<Person>();
// 3.添加多个Person到HashSet中
hashSet.add(new Person("王昭君", 21));
hashSet.add(new Person("西施", 21));
hashSet.add(new Person("杨玉环", 20));
hashSet.add(new Person("貂蝉", 19));
hashSet.add(new Person("杨玉环", 20));
hashSet.add(new Person("貂蝉", 19));
// 4.遍历获取HashSet中的内容
for (Person p : hashSet) {
System.out.println(p);
}
}
}
练习:List集合元素替换
向list集合添加姓名{张三,李四,王五,二丫,钱六,孙七}, 将二丫替换为王小丫
public class ListTest01 {
public static void main(String[] args) {
//1.创建List集合对象
List<String> list = new ArrayList<>();
//2.存入数据
list.add("张三");
list.add("李四");
list.add("王五");
list.add("二丫");
list.add("钱六");
list.add("孙七");
//3.遍历集合,找到"二丫",便将其替换为"王小丫"
//利用普通for循环遍历List集合
for(int i = 0;i<list.size();i++) {
//获取当前元素
String thisName = list.get(i);
//如果当前元素是"二丫"
if("二丫".equals(thisName)) {
//将其改为"王小丫"
list.set(i, "王小丫");
}
}
System.out.println(list);
}
}
// 使用增强for获取LinkedHashSet中的元素
for (String str : list){
if ("二丫".equals(str)){
System.out.println(list);
}
}
练习:LinkedHashSet基本使用
使用LinkedHashSet存储以下元素:”王昭君”,”王昭君”,”西施”,”杨玉环”,”貂蝉”。使用迭代器和增强for循环遍历LinkedHashSet。
public class LinkedHashSetTest01 {
public static void main(String[] args) {
// 1.创建LinkedHashSet
LinkedHashSet<String> lhSet = new LinkedHashSet<String>();
// 2.使用add方法添加元素到LinkedHashSet
lhSet.add("王昭君");
lhSet.add("王昭君");
lhSet.add("王昭君");
lhSet.add("西施");
lhSet.add("杨玉环");
lhSet.add("貂蝉");
// 3.使用迭代器获取LinkedHashSet中的元素
Iterator<String> iterator = lhSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 4.使用增强for获取LinkedHashSet中的元素
System.out.println("---------------------");
for (String string : lhSet) {
System.out.println(string);
}
}
}
练习:Collections工具类使用
ArrayList集合中有如下内容: {33,11,77,55},使用Collections.sort()对ArrayList集合中的数据进行排序,并打印出排序后的结果
public class CollectionsTest01 {
public static void main(String[] args) {
// 1.创建ArrayList
ArrayList<Integer> arr = new ArrayList<Integer>();
// 2.使用add方法添加{33,11,77,55}四个元素
arr.add(33);
arr.add(11);
arr.add(77);
arr.add(55);
// 3.调用Collections的sort方法,对集合排序
Collections.sort(arr);
// 4.使用增强for遍历ArrayList集合
for (Integer integer : arr) {
System.out.println(integer);
}
}
}
Map集合习题
练习:Map接口的特点
请简述Map 的特点
★ Map每个元素由键与值两部分组成
★ Map键不能重复,每个键对应一个值
★ 键和值可以为null
练习:Entry键值对对象
说出Entry键值对对象遍历Map集合的原理
Map中存放的是两种对象,一种称为Key(键),一种称为value(值),它们在Map中是一一对应关系,这一种对象又称做Map中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每个键值对(Entry)对象中获取对应的键与对应的值。
练习:Map接口中的常用方法
请使用Map集合的方法完成添加元素,根据键删除,以及根据键获取值操作。
public static void main(String[] args) {
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("黄晓明", "Baby");
hm.put("邓超", "孙俪");
hm.put("李晨", "范冰冰");
hm.put("大黑牛", "范冰冰");
String v1 = hm.put("李晨", "白百合");
String string = hm.get("大黑牛");
String v2 = hm.remove("大黑牛");
System.out.println(v2);
System.out.println(hm);
}
// 范冰冰 {邓超=孙俪, 李晨=白百合, 黄晓明=Baby}
练习:Map接口中的方法
往一个Map集合中添加若干元素。获取Map中的所有value,并使用增强for和迭代器遍历输出每个value。
public static void main(String[] args) {
// 1.创建HashMap
HashMap<String, String> hm = new HashMap<String, String>();
// 2.使用put添加元素
hm.put("黄晓明", "Baby");
hm.put("邓超", "孙俪");
hm.put("李晨", "范冰冰");
hm.put("大黑牛", "范冰冰");
// 3.使用Map的values方法获取到所有的value
Collection<String> values = hm.values();
// 4.使用增强for获取每个value
for (String value : values) {
System.out.println(value);
}
System.out.println("----------------");
// 5.使用迭代器获取每个value
Iterator<String> itr = values.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
练习:HashMap存储键是自定义对象是String
请使用Map集合存储自定义数据类型Car做键,对应的价格做值。并使用keySet和entrySet两种方式遍历Map集合。
// 1.定义汽车类.包含名称和价格属性,重写hashCode和equals方法
public class Car {
private String name;
private String color;
...
}
---------------------------------------------------
public static void main(String[] args) {
// 2.创建HashMapkey保存汽车对象,value是汽车价格
HashMap<Car, Integer> hm = new HashMap<>();
// 3.添加汽车到HashMap中
Car c1 = new Car("长安奔奔", "黄色");
Car c3 = new Car("奇瑞QQ", "黑色");
Car c2 = new Car("铃木奥拓", "白色");
hm.put(c1, 10000);
hm.put(c2, 20000);
hm.put(c3, 30000);
// 4.使用keySet方式遍历Map
Set<Car> keySet = hm.keySet();
for (Car c : keySet) {
// 根据key获取value
Integer value = hm.get(c);
System.out.println(c.getName() + "," + c.getColor() + " - " + value);
}
System.out.println("-------------");
// 5.使用entrySet方式遍历Map
Set<Map.Entry<Car, Integer>> entrySet = hm.entrySet();
for (Map.Entry<Car, Integer> entry : entrySet) {
Car key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key.getName() + "," + key.getColor() + " - " + value);
}
}
public Set<Map.Entry<K,V>> entrySet()
返回此地图中包含的映射的Set
视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改映射(除了通过迭代器自己的remove
操作,或者通过迭代器返回的映射条目上的setValue
操作),迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove
,Set.remove
,removeAll
,retainAll
和clear
操作。 它不支持add
或addAll
操作。
练习:Map集合的使用(一)
现在有一个map集合如下:
Map<Integer,String> map = new HashMap<Integer, String>();
map.put(1, "张三丰");
map.put(2, "周芷若");
map.put(3, "汪峰");
map.put(4, "灭绝师太");
要求:
1.遍历集合,并将序号与对应人名打印。
2.向该map集合中插入一个编码为5姓名为李晓红的信息
3.移除该map中的编号为1的信息
4.将map集合中编号为2的姓名信息修改为”周林”
public static void main(String[] args) {
// 1.定义HashMap,编号作为key,姓名作为value
Map<Integer, String> map = new HashMap<Integer, String>();
// 2.使用put方法添加元素
map.put(1, "张三丰");
map.put(2, "周芷若");
map.put(3, "汪峰");
map.put(4, "灭绝师太");
// 3.使用keySet+增强for迭代map中的元素,并打印
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
String value = map.get(key);
System.out.println(key + " -- " + value);
}
// 4.使用put向该map集合中插入一个编码为5姓名为李晓红的信息
map.put(5, "李晓红");
// 5.使用remove移除该map中的编号为1的信息
map.remove(1);
// 6.使用put将map集合中编号为2的姓名信息修改为"周林"
map.put(2, "周林");
System.out.println(map);
}
练习:Map集合的使用(二)
有2个数组
第一个数组内容为:[黑龙江省,浙江省,江西省,广东省,福建省],
第二个数组为:[哈尔滨,杭州,南昌,广州,福州],将第一个数组元素作为key,
第二个数组元素作为value存储到Map集合中。如{黑龙江省=哈尔滨, 浙江省=杭州, …}
public static void main(String[] args) {
// 1.定义第一个数组arr1
String[] arr1 = {"黑龙江省", "浙江省", "江西省", "广东省", "福建省"};
// 2.定义第二个数组arr2
String[] arr2 = {"哈尔滨", "杭州", "南昌", "广州", "福州"};
// 3.创建HashMap,key存放省,value存放市
HashMap<String, String> hm = new HashMap<>();
// 4.使用普通for循环遍历arr1
for (int i = 0; i < arr1.length; i++) {
// 5.根据索引到arr1中获取到省
String key = arr1[i];
// 6.根据索引到arr2中获取到省会城市
String value = arr2[i];
// 7.将省和省会城市添加到HashMap中
hm.put(key, value);
}
// 8.输出HashMap中的内容
System.out.println(hm);
}
Math类习题
练习:实现字符串123反转
使用字符数组保存原始字符,利用Random类生成随机索引。
public class Test1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
System.out.println("录入的字符串:" + next);
String s = reverseStr(next);
System.out.println("反转的字符串:"+ s);
}
public static String reverseStr(String str){
String s = "";
char[] chars = str.toCharArray();
for (int i = chars.length - 1; i >= 0; i--) {
s +=chars[i] ;
}
return s;
}
}
toCharArray() 方法将字符串转换为字符数组
练习:键盘录入QQ号判断正确性
必须是5-12位数字,0不能开头
public class Test1 {
public static void main(String[] args) {
//1.键盘输入一个qq号码字符串
Scanner sc = new Scanner(System.in);
String qq = sc.next();
//2.调用checkQQ (String qq)方法内实现验证。
boolean isOK = checkQQ(qq);
//3.打印验证的结果
System.out.println("这个QQ号码是否正确:" + isOK);
}
/*
* 定义方法:checkQQ (String qq)方法内实现验证
* 指定方法的名称:checkQQ
* 指定方法的参数:String qq
* 指定方法的返回值:boolean
*/
public static boolean checkQQ(String qq) {
//1.验证字符串的长度5-12位之间;
if (qq.length() < 5 || qq.length() > 12) {
return false; //说明qq号码的长度不正确
}
//2.验证首位字符不能是字符0;只能是字符'1'--'9'
if (qq.charAt(0) == '0') {
return false;
}
//3.验证字符串中的每个字符都必须是数字字符‘0’-‘9’之间的字符
for (int i = 0; i < qq.length(); i++) {
char ch = qq.charAt(i);
//判断字符是否在 数字字符‘0’-‘9’之间的字符
if (ch < '0' || ch > '9') {
return false;//说明qq号码中含有非数字字符
}
}
//4.上述验证都通过了,说明qq号码是正确的
return true;
}
}
练习:大小写字符转换并统计次数
键盘录入一个大字符串,再录入一个小字符串。统计小字符串在大字符串中出现的次数。
/*
* 分析以下需求,并用代码实现
1.键盘录入一个大字符串,再录入一个小字符串
2.统计小字符串在大字符串中出现的次数
3.代码运行打印格式:
请输入大字符串:woaiheima,heimabutongyubaima,wulunheimahaishibaima,zhaodaogongzuojiushihaoma
请输入小字符串:heima
控制台输出:小字符串heima,在大字符串woaiheima,heimabutongyubaima,wulunheimahaishibaima,zhaodaogongzuojiushihaoma中共出现3次
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 1.键盘录入一个大字符串,再录入一个小字符串
System.out.print("请输入大字符串:");
String big = sc.nextLine();
System.out.print("请输入小字符串:");
String small = sc.nextLine();
// 2.统计小字符串在大字符串中出现的次数
int count = getCount(big, small);
// 3.代码运行打印格式:
System.out.println("小字符串" + small + ",在大字符串中共出现" + count + "次");
}
/*
* 方法功能:统计小字符串在大字符串中出现的次数
* 参数:big 代表大字符串
* 参数:small 代表小字符串
* 返回值:小字符串在大字符串中出现的次数
*/
public static int getCount(String big, String small) {
int index = 0;
int count = 0;
/*
* indexOf(String str, int fromIndex)
* 该方法作用:从fromIndex位置开始查找,字符串str第一次出现的位置;若没找到,放回-1
*/
while ((index = big.indexOf(small, index)) != -1) {
index++;
count++;
}
return count;
}
练习:随机小数保留两位
生成一个随机100内小数,转换为保留两位小数的字符串,不考虑四舍五入的问题。
public static void main(String[] args) {
double random = Math.random()*100;
System.out.println("随机数为:");
System.out.println(random);
String str = random + " ";
int index = str.indexOf(".");
String substring = str.substring(0, index + 3);
System.out.println("转换为");
System.out.println(substring);
}
// substring(int strat, int end)中第一个参数是开始位置,第二个参数是结束位置.
练习:筛选字符串
定义ArrayList集合,存入多个字符串。长度大于5的字符串,打印删除后的集合。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("bca");
list.add("dadfa");
list.add("dddaaa");
list.add("你好啊");
list.add("我来啦,你干嘛呢");
list.add("别跑啊");
System.out.println("源字符串:");
System.out.println(list);
delStrsFromList01(list);
}
private static void delStrsFromList01(ArrayList<String> list){
ArrayList<String> list2 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
if (str.length() > 3){
list2.add(str);
}
}
for (Object str : list2){
list.remove(str);
}
System.out.println("新字符:" + list);
}
练习:回文字符串
判断回文字符串。如果一个字符串,从前向后读和从后向前读,都是一个字符串,称为回文串,比如mom,dad,noon。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
boolean p = isP(next);
System.out.println(
"回文数:" + p
);
}
public static boolean isP(String str) {
int start = 0;
int end = str.length() - 1;
while (start < end) {
if (str.charAt(start) != str.charAt(end)) {
return false;
}
start++;
end--;
}
return true;
}
charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。
练习:模拟简单计算器
模拟简单计算器,可以运算+,—,*,/,%。
- 接收三个参数,一个整数,一个运算符,另一个整数。( ‘5’ ‘+’ ‘7’ )
- 计算出运算结果。
- 无法运算时,返回null。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
String next = scanner.next();
int b = scanner.nextInt();
String count = count(a, next, b);
System.out.println(a +next +b +"="+count);
}
public static String count(int a, String op , int b ){
int r=0;
if ("+".equals(op)){
r = a+b;
}else if ("-".equals(op)){
r = a-b;
}else if ("*".equals(op)){
r = a*b;
}else if ("/".equals(op)){
r = a/b;
}else if ("%".equals(op)){
r = a%b;
}else {
return null;
}
return r+"";
}
练习:密码是否合法
校验密码是否合法。合法返回true
- 必须至少8个字符。
- 必须至少2个大写字符。
超越两个就要依次遍历 for循环
- 必须只有字母和数字。
public static void main(String[] args) {
String s = "qweRY123";
System.out.println(s+"密码是否合法"+isTrue(s));
}
private static boolean isTrue(String s){
if (s.length()<8){
return false;
}
int countA = 0;
char[] chars = s.toCharArray();
for (int i = 0; i < s.length(); i++) {
char ch = chars[i];
//2个大写字母
if (ch >= 'A' && ch <= 'Z'){
countA++;
}
//字母数字
if ((ch < '0'|| ch>'9') && (ch < 'A'|| ch>'Z')&&(ch < 'a'|| ch>'z')) {
return false;
}
}
if (countA < 2){
return false;
}
return true;
}
练习:模拟用户登录
模拟用户登录。
- 定义用户类,属性为用户名和密码。
- 使用集合存储多个用户对象。
- 录入用户和密码,对比用户信息,匹配成功登录成功,否则登录失败。
- 登录失败时,当用户名错误,提示没有该用户。
- 登录失败时,当密码错误时,提示密码有误。
jack-1234 rose-5678 tom-0000
请输入用户名:rose
请输入密码:5678
登录结果:登录成功
public class User {
private String username;
private String pwd;
}
------------------------------------------
public class Test {
static ArrayList<User> list = new ArrayList<>();
static {
list.add(new User("jack", "1234"));
list.add(new User("rose", "5678"));
list.add(new User("tom", "0000"));
for (int i = 0; i < list.size(); i++) {
list.get(i).show();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
User u = new User(username, password);
String login = login(u);
System.out.println("登录结果:" + login);
}
public static String login(User user) {
String msg = "";
String n = user.getUsername();
String p = user.getPwd();
for (int i = 0; i < list.size(); i++) {
User u = list.get(i);
String name = u.getUsername();
String pwd = u.getPwd();
if (name.equals(n)){
if (pwd.equals(p)){
return "登录成功";
}else {
return "密码错误";
}
}else {
msg = "用户名不存在";
continue;
}
}
return msg;
}
}
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。[ 在此代码内适用于login方法中的list.size() ]
static代码块只在类加载时执行,类是用类加载器来读取的,类加载器是带有一个缓存区的,
它会把读取到的类缓存起来,所以在一次虚拟机运行期间,一个类只会被加载一次,这样的话静态代码块只会运行一次
Object类&Date类&Calender(日期)类&StringBuilder类
练习:简述String和Object中的equals
简述String类中的equals方法 与 Object类中的equals方法的不同点
String类中的equals方法是用来判断两个对象的内容是否相同,而Object 类中的equals方法是用来判断两个对象是否是同一个对象,所谓同一个对象指的是内存中的同一块存储空间。
练习:Object类的toString方法
public class ToStringTest{
static int i = 1;
public static void main(String args[]){
System.out.println("love " + new ToStringTest());//love java
ToStringTest a = new ToStringTest();
a.i++;
System.out.println("me " + a.i);//me 2
}
public String toString(){
System.out.print("I ");//I
return "java ";
}
}
运行结果:I love java me 2
原因:当执行代码的时候,首先加载静态变量,然后执行main方法,由于main方法内部第一行代码为输出语句,里面new了此类对象,当执行此行代码时会先创建了本类的对象,由于此类重写了toString方法,会先执行toString方法的打印输出,然后返回“java ”,再执行main方法第一行打印输出。在Java中“System.out.println(类对象名);”实际输出的是该对象的toString()方法返回的字符串,即括号中的内容等价于类对象名.toString(),toString方法的好处是在碰到println方法的时候会被自动调用,不用显示的写出来。
练习:Object类equals方法
看下列程序,不运行说结果,写出答案后,并在IntelliJ IDEA中运行看看自己给的答案与运行结果是否正确,并分析原因。
(1)
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2); //false
System.out.println(s1.equals(s2)); //true
(2)
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
(3)
String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
(4)
String s1 = "ab";
String s2 = "abc";
String s3 = s1 + "c";
System.out.println(s3 == s2); //false
System.out.println(s3.equals(s2)); //true
练习:StringBuilder类与String类的区别
简述StringBuilder类与String类的区别
String类的对象内容不可改变,所以每当进行字符串拼接时,总是会在内存中创建一个新的对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响。
StringBuilder又称为可变字符序列,是JDK5.0中新增加的一个类,它是一个类似于String的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。即它是一个容器,容器中可以装很多字符串,并且能够对其中的字符串进行各种操作。它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容,StringBuilder会自动维护数组的扩容。
练习:Date类的使用
获取当前的日期, 并把这个日期转换为指定格式的字符串, 如2088-08-08 08:08:08
public static void main(String[] args) {
//获取当前日期对象 now;
Date now = new Date();
//创建SimpleDateFormat对象 df,并制定日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//调用df的format(Date date) 方法,传入now; 接收返回的字符串
String datestr = df.format(now);
//打印这个字符串
System.out.println(datestr);
}
练习:DateFormat类方法的使用
使用SimpleDateFormat类,把2018-03-04转换为2018年03月04日
public static void main(String[] args) throws ParseException {
//创建SimpleDateFormat对象df1,指定日期模式为yyyy-MM-dd
SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
//调用df1的parse(String str)方法传入2018-03-04,得到对应日期类型
Date date = df1.parse("2018-03-04");
//创建日期格式化对象df2,在获取格式化对象时可以指定风格
DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日");
//调用df2的format(Date date) 传入刚才转换的日期
String str = df2.format(date);
System.out.println(str);
}
public Date parse(String text, ParsePosition pos)
从字符串中解析文本,产生一个Date
。
练习:Calendar类方法的使用
用程序判断2018年2月14日是星期几。
public static void main(String[] args) {
//创建Calendar对象
Calendar c = Calendar.getInstance();
//将给定的日历字段设置到Calendar对象中
c.set(Calendar.YEAR, 2018);
c.set(Calendar.MONTH, 1);
c.set(Calendar.DATE, 14);
//设置年
int year = c.get(Calendar.YEAR);
//设置月
int month = c.get(Calendar.MONTH)+1;
//设置日
int date = c.get(Calendar.DATE);
//设置星期
char week = getWeek(c.get(Calendar.DAY_OF_WEEK));
//输出结果
System.out.println(year+"年"+month+"月"+date+"日是星期"+week);
}
//定义方法,获取星期汉字
public static char getWeek(int a){
char[] c = {' ','日','一','二','三','四','五','六'};
return c[a];
}
}
Random类&ArrayList集合习题
练习:随机验证码
- 随机生成十组六位字符组成的验证码。
- 验证码由大小写字母、数字字符组成。
开发提示:使用字符数组保存原始字符,利用Random类生成随机索引。
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
String s = verifyCode();
System.out.println("随机验证码:" + s);
}
}
public static String verifyCode(){
char[] arr = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
Random random = new Random();
String code = "";
for (int i = 0; i < 6; i++) {
int index = random.nextInt(arr.length);
code += arr[index];
}
return code;
}
练习:输入学生信息保存到集合
键盘录入学生信息,保存到集合中。
- 循环录入的方式,1:表示继续录入,0:表示结束录入。
- 定义学生类,属性为姓名,年龄,使用学生对象保存录入数据。
- 使用ArrayList集合,保存学生对象,录入结束后,遍历集合。
public class Student {
private String name;
private int age;
public void show(){
System.out.println("姓名: "+ name + " " + "年龄: " + age);
}
}
----------------------------------
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Student> list = new ArrayList<>();
while (true) {
System.out.println("1.录入信息 0.退出");
int i = scanner.nextInt();
switch (i) {
case 1:
inputStu(list , scanner);
break;
case 0:
System.out.println("录入完毕");
}
if (i == 0){
break;
}
}
for (int i = 0; i < list.size(); i++) {
Student student = list.get(i);
student.show();
}
}
private static void inputStu(ArrayList<Student> list , Scanner sc) {
System.out.println("请输入姓名:");
String name = sc.next();
System.out.println("请输入年龄:");
int age = sc.nextInt();
Student student = new Student(name, age);
list.add(student);
}
}
练习:随机数 次数打印
统计数字出现次数。
- 定义getNumList方法,随机生成100个数字,数字范围从1到10。
- 定义printCount方法,统计每个数字出现的次数并打印到控制台。
public class Test4 {
public static void main(String[] args) {
ArrayList<Integer> numList = getNumList();
// 统计字符数组中字母出现次数
printCount(numList);
}
public static void printCount(ArrayList<Integer> list) {
int[] count = new int[10];
// 对应保存数字出现的次数
for (int i = 0; i < list.size(); i++) {
int c = list.get(i);
count[c-1]++;
}
// 打印数字和次数
for (int i = 0 ; i < count.length; i++) {
System.out.println("数字:"+(i+1) + "--" + count[i]+"次");
}
}
public static ArrayList<Integer> getNumList() {
ArrayList<Integer> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 100; i++) {
int x = r.nextInt(10) + 1;
list.add(x);
}
return list;
}
}
练习:需求实现
模拟统计班级考试分数分布情况,分别统计100-80,79-60,59-40,39-0各个阶段的人数。
- 定义getScoreList方法,随机生成50个数字,数字范围从0到100。
- 定义countScore方法,统计各个阶段的分数个数。
- 定义printCount方法,打印各个阶段的统计结果。
public static void main(String[] args) {
ArrayList<Integer> scoreList = getScoreList(); //获取随机分数
ArrayList<Integer> countList = countScore(scoreList); //定义计数的变量
printCount(countList);
}
public static ArrayList<Integer> countScore(ArrayList<Integer> scoreList) {
ArrayList<Integer> countList = new ArrayList<>();
int count100 = 0;
int count79 = 0;
int count59 = 0;
int count39 = 0;
for (int i = 0; i < scoreList.size(); i++) {
Integer score = scoreList.get(i);
if (score <= 100 && score >= 80) {
count100++;
} else if (score <= 79 && score >= 60) {
count79++;
} else if (score <= 59 && score >= 40) {
count59++;
} else {
count39++;
}
}
countList.add(count100);
countList.add(count79);
countList.add(count59);
countList.add(count39);
return countList;
}
private static ArrayList<Integer> getScoreList(){
ArrayList<Integer> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 50; i++) {
int x = r.nextInt(100);
list.add(x);
}
return list;
}
private static void printCount(ArrayList<Integer> countList) {
int start = 100;
int end = 80;
for (int i = 0; i < countList.size(); i++) {
Integer integer = countList.get(i);
System.out.println(start + "\t分 --" + end + " \t分:" + integer+"人");
if (i == 0){
start-=21;
end -=20;
}else if (i == countList.size()-2){
start-=20;
end-=40;
}else {
start -= 20;
end -= 20;
}
}
}
练习:添加移除展示元素
自定义MyList类,实现存取元素的功能。
- 定义add方法,可以保存元素,添加MyList尾部。
- 定义remove方法,可以获取到最后添加的元素,并从MyList中移除该元素。
- 定义show方法,可以展示MyList中的元素。
public static void main(String[] args) {
MyList myList = new MyList();
for (int i = 0; i < 3; i++) {
myList.add(i);
}
System.out.println("添加元素后:");
myList.show();
Integer remove = myList.remove();
System.out.println("获取元素:");
System.out.println(remove);
System.out.println("获取元素后:");
myList.show();
}
}
class MyList {
ArrayList<Integer> ml = new ArrayList<>();
public void add(Integer i) {
ml.add(i);
}
public Integer remove() {
Integer remove = ml.remove(ml.size() - 1);
return remove;
}
public void show() {
System.out.println(ml);
}
}
线程&同步习题
练习:多线程开启
请描述Thread类中的start()方法与run()方法的区别
线程对象调用run()方法不开启线程,仅是对象调用方法。
线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。
练习:创建多线程
请描述创建线程的两种方法
①.定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。
②.创建Thread子类的实例,即创建了线程对象
③.调用线程对象的start()方法来启动该线程
①.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
②,创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象
③.调用线程对象的start()方法来启动线程
练习:多线程
请编写程序,分别打印主线程的名称和子线程的名称
要求使用两种方式实现:
第一种方式:继承Thread类。
第二种方法:实现Runnable接口。
操作步骤描述:
①.定义一个子线程的类,继承Thread类
②.在子线程类中重写run方法,在run方法中打印子线程的名称
③.定义一个测试类
④.在main方法中打印主线程的名称
⑤.在main方法中创建子线程对象
⑥.调用子线程对象的start方法,开启子线程
// 1.定义一个子线程的类,继承Thread类;
public class SubThread extends Thread{
// 2.在子线程类中重写run方法,在run方法中打印子线程的名称;
public void run(){
// 打印子线程的名称
System.out.println("subThread:" + Thread.currentThread().getName());
}
}
// 3.定义一个测试类
public class ThreadDemo{
public static void main(String[] args){
// 4.在main方法中打印主线程的名称;
System.out.println("main:" + Thread.currentThread().getName());
// 5.在main方法中创建子线程对象;
SubThread st = new SubThread();
// 6.调用子线程对象的start方法,开启子线程。
st.start();
}
}
①.定义一个子任务类,实现Runnable接口
②.在子任务中重写run方法,在run方法中打印子线程的名称
③.定义一个测试类
④.在main方法中打印主线程的名称;
⑤.在main方法中创建一个子任务对象;
⑥.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的构造方法;
⑦.调用Thread类对象的start方法开启子线程;
// 1.定义一个子任务类,实现Runnable接口。
public class SubRunnable implements Runnable{
@Override
public void run() {
// 2.在子任务类中重写run方法,在run方法中打印子线程的名称。
System.out.println("SubRunnable:"+ Thread.currentThread().getName());
// 3.定义一个测试类。
}
}
public class RunnableDemo {
public static void main(String[] args) {
// 4.在main方法中打印主线程的名称。
System.out.println("RunnableDemo:"+ Thread.currentThread().getName());
// 5.在main方法中创建一个子任务对象。
SubRunnable r = new SubRunnable();
// 6.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的 构造方法。
Thread t = new Thread(r);
// 7.调用Thread类对象的start方法开启子线程。
t.start();
}
}
练习:实现Runnable接口的优势
请描述实现Runnable接口比继承Thread类所具有的优势:
①.适合多个相同的程序代码的线程去共享同一个资源
②.可以避免java中的单继承的局限性
③.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
④.线程池只能放入实现Runnable或callable类线程,不能直接放入继承Thread的类
练习:多线程
创建多线程对象,开启多线程。在子线程中输出1-100之间的偶数,主线程输出1-100之间的奇数
自定义线程类:
public class MyThread extends Thread {
/**
* 重写run方法,完成该线程执行的逻辑
*/
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println("子线程打印输出偶数:" + i);
}
}
}
public class Test11 {
public static void main(String[] args) {
//创建自定义线程对象
MyThread mt = new MyThread();
//开启线程
mt.start();
//在主方法中执行for循环
for (int i = 1; i <= 100; i++) {
if (i % 2 == 1) {
System.out.println("主线程打印输出奇数:" + i);
}
}
}
}
练习:线程状态
请描述在线程的生命周期中, 有几种状态呢 ?
1.NEW(新建) 线程刚被创建,但是并未启动。
2.Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
3.Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
4.Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
5.Timed Waiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
6.Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
线程池&lambda表达式习题
练习:线程池概念
请描述什么是线程池
线程池:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复用户创建线程而消耗过多的资源
练习:线程池优点
请描述合理利用线程池能够带来的三个好处
1,降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可以执行多个任务
2.提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行
3.提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
练习:Lambda表达式
请列举Lambda语法的省略规则
在Lambda标准格式的基础上,使用省略句写法的规则为:
1.小括号内参数的类型可以省略
2.如果小括号内有且只有一个参数,则小括号可以省略
3.如果大括号内有且只有一个语句,则无论是否有返回值,都可以省略大括号、return、关键字以及语句分号
练习:Lambda表达式
请列举Lambda表达式的3个组成部分,并解释说明
Lambda标准格式Lambda省去面向对象的条条框框,格式由3个部分组成:一些参数、一个箭头、一段代码
Lambda表达式的标准格式:
1.小括号内的语法与传统方法参数列表一致:无参数则留空,多个参数则用逗号分割
2.”—>”是新引入的语法格式,代表指向动作
3.大括号内的语法与传统方法体要求基本一致
练习:Lambda表达式
请描述Lambda的使用前提
Lambda的语法非常简介,完全没有面向对象复杂的束缚。但是使用时有几个问题需要特别注意:
1.使用Lambda必须具有接口,且要求接口中有且只有一个抽象方法。无论是JDK内置的Runnable、Comparator
接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才能使用Lambda。
2.使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例
练习:多线程
代码实现打印输出1-99
public class Test06 {
public int start = 1;
public int end = 99;
public static void main(String[] args) {
new Test06().method();
}
public void method() {
//插入代码处
Runnable a = () -> {
for (int i = start; i <end; i++) {
System.out.println(i);
}
};
Thread t = new Thread(a);
t.start();
}
}
练习:多线程
请问该程序的运行结果是什么? 如有问题,请说明原因。
public class Test07implements Runnable {
public static void main(String[] args) {
Thread t = new Thread(new Test07());
t.start();
}
public void run(int num) {
for (int i = 0; i < num; i++) {
System.out.println(i);
}
}
}
在编译时期就会报错
Test类没有重写Runnable接口中的run()方法
public void run(int num)不是Runnable接口中的run()方法。
注意:Runnable接口中的run()方法,参数列表为空,不带参数。
练习:线程池练习
使用线程池创建多线程。模拟同学找老师学习Java。
1.创建线程池对象,包含2个线程。从线程池中获取线程对象,然后调用MyRunnable中的run()。
2.在MyRunnable实现类中,首先在控制台打印需求,“我需要一个老师”。模拟需要2秒钟时间老师可以过来指导学生,并在控制台打印老师的姓名。最后,在控制台打印“教我java,教完后,老师回到了办公室”;
class Test implements Runnable{
@Override
public void run() {
System.out.println("我要一个老师");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("老师来了" + Thread.currentThread().getName());
System.out.println("教我Java,教完后,老师回到了办公室");
}
}
class ThreadPoolDemo{
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
Test r = new Test();
service.submit(r);//线程1
service.submit(r);//线程2
service.submit(r);//线程3
}
}
练习:Lambda(无参无返回)
给定一个导演 Director接口,内含唯一的抽象方法makeMovie,且无参数、无返回值,使用lambda表达式在Test中完成调用。
interface Director{
void makeMovie();
}
public class Test {
public static void main(String[] args) {
// TODO 请使用Lambda【省略格式】调用invokeDirect方法
invokeDirect(()-> System.out.println("拍电影啦"));
}
private static void invokeDirect(Director director){
director.makeMovie();
}
}
练习:Lambda(有参有返回)
给定一个计算器 Calculator 接口,内含抽象方法 calc (减法),其功能是可以将两个数字进行相减,并返回差值。使用Lambda表达式在Test中完成调用
interface Calculator{
int calc(int a, int b);
}
public class Test {
public static void main(String[] args) {
// TODO 请分别使用Lambda【标准格式】及【省略格式】调用invokeCalc方法来计算130-120的结果ß
invokeCalc(130, 120, (int a, int b) -> {
return a - b;
}); //标准格式
invokeCalc(130,120,(a,b)-> a-b); //省略模式
}
private static void invokeCalc(int a, int b, Calculator calculator){
int result = calculator.calc(a,b);
System.out.println("结果是:" + result);
}
}
Stream流
练习一:Pedicate接口使用
请在测试类main方法中完成以下需求
已知有Integer[] arr = {-12345, 9999, 520, 0,-38,-7758520,941213}
a) 使用lambda表达式创建Predicate对象p1,p1能判断整数是否是自然数(大于等于0)
b) 使用lambda表达式创建Predicate对象p2,p2能判断整数的绝对值是否大于100
c) 使用lambda表达式创建Predicate对象p3,p3能判断整数是否是偶数
遍历arr,仅利用已创建的Predicate对象(不使用任何逻辑运算符),完成以下需求
i. 打印自然数的个数
ii. 打印负整数的个数
iii. 打印绝对值大于100的偶数的个数
iv. 打印是负整数或偶数的数的个数
public static void main(String[] args) {
Integer[] arr = {-12345, 9999, 520, 0,-38,-7758520,941213};
//a) 使用lambda表达式创建Predicate对象p1,p1能判断整数是否是自然数
Predicate<Integer> p1 = (s) -> s>=0;
//b) 使用lambda表达式创建Predicate对象p2,p2能判断整数的绝对值是否大于100
Predicate<Integer> p2 = (s) -> Math.abs(s)>100;
//c) 使用lambda表达式创建Predicate对象p3,p3能判断整数是否是偶数
Predicate<Integer> p3 = (s) -> s%2==0;
//e) 遍历arr,仅利用已创建的Predicate对象(不使用任何逻辑运算符),完成以下需求
int count1 = 0;
int count2 = 0;
int count3 = 0;
int count4 = 0;
for (Integer i : arr) {
//统计自然数个数
if (p1.test(i)){
count1++;
}
//统计负整数个数
if (p1.negate().test(i)){
count2++;
}
//统计绝对值大于100的偶数个数
if (p2.and(p3).test(i)){
count3++;
}
//统计是负整数或偶数的数的个数
if (p1.negate().or(p3).test(i)){
count4++;
}
}
//分别打印结果
System.out.println("自然数的个数为:"+count1);
System.out.println("负整数的个数为:"+count2);
System.out.println("绝对值大于100的偶数的个数为:"+count3);
System.out.println("是负整数或偶数的数的个数为:"+count4);
}
练习:Function接口使用
[这是一个功能界面,因此可以用Lambda表达式或方法引用的赋值对象]
Interface Function<T,R>
T:函数输入的类型
R:函数结果的类型Interface Map<K,V>
K:由此地图维护的键的类型
V:映射值的类型
1.使用lambda表达式分别将以下功能封装到Function对象中
a) 求Integer类型ArrayList中所有元素的平均数
b) 将Map < String,Integer > 中value存到ArrayList < Integer >中
2.已知学生成绩如下
姓名 | 成绩 |
---|---|
岑小村 | 59 |
谷天洛 | 82 |
渣渣辉 | 98 |
蓝小月 | 65 |
皮几万 | 70 |
3.以学生姓名为key成绩为value创建集合并存储数据,使用刚刚创建的Function对象求学生的平均成绩
public static void main(String[] args) {
//1. 使用lambda表达式分别将以下功能封装到Function对象中
//a) 求Integer类型ArrayList中所有元素的平均数
Function<ArrayList<Integer>,Integer> f1 = (list)->{
Integer sum = 0;
for (Integer i : list) {
sum+=i;
}
return sum/list.size();
};
//b) 将Map<String,Integer>中value存到ArrayList<Integer>中
Function<Map<String,Integer>,ArrayList<Integer>> f2 = (map)->{
/*ArrayList<Integer> list = new ArrayList<>();
for (String s : map.keySet()) {
Integer i = map.get(s);
list.add(i);
}*/
Collection<Integer> values = map.values();
ArrayList<Integer> list = new ArrayList<>();
list.addAll(values);
return list;
};
//2 将学生姓名和成绩封装到map中
Map<String,Integer> map = new HashMap<String, Integer>();
map.put("岑小村", 59);
map.put("谷天洛", 82);
map.put("渣渣辉", 98);
map.put("蓝小月", 65);
map.put("皮几万", 70);
//利用Function求平均成绩
Integer avg = f2.andThen(f1).apply(map);
System.out.println("学生平均成绩为:"+avg);
}
练习:获取流
简述单列集合、双列集合、数组分别如何获取Stream流对象,并进行演示
1.java.util.Collection接口中加入了default方法 stream()获取流对象,因此其所有实现类均可通过此方式获取流
2.java.util.Map接口想要获取流,先通过KeySet()、values()或entrySet()方法获取键、值或键值对的单列集合,再通过stream()获取流对象
3.数组获取流,使用Stream接口中的静态方法of(T...values)获取流
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Map<String, String> map = new HashMap<>();
Stream<String> stream2 = set.stream();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.values().stream();
Stream<Map.Entry<String,String>>entryStream = map.entrySet().stream();
String[] array = {"东邪", "西毒", "南帝", "北丐", "中神通"};
Stream<String> stream = Stream.of(array);
}
练习:过滤[filter]、结果收集(数组)
有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新数组
public class Test {
public static void main(String[] args) {
Stream<String> stream = Stream.of("黄药师", "冯蘅", "郭靖", "黄蓉", "郭芙", "郭襄", "郭破虏");
String[] guos = stream.filter(s -> s.startsWith("郭")).toArray(String[]::new);
}
}
// filter 返回由与此给定谓词匹配的此流的元素组成的流。
// toArray 返回一个包含此流的元素的数组 结果: 一个包含此流的元素的数组
练习:n 取用前几个[limit]、跳过前几个[skip]
已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},使用Stream
1,取出前2个元素并在控制台打印输出。
2.取出后2个元素并在控制台打印输出。
import java.util.ArrayList;
public class Test04 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("陈玄风");
list.add("梅超风");
list.add("陆乘风");
list.add("曲灵风");
list.add("武眠风");
list.add("冯默风");
list.add("罗玉风");
list.stream().limit(2).forEach(System.out::println);
list.stream().skip(list.size() - 2).forEach(System.out::println);
}
}
练习:n 映射[map]、逐一消费[forEach]
有如下整数1,-2,-3,4,-5
使用Stream取元素绝对值并打印
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, -2, -3, 4,-5);
stream.map(Math::abs).forEach(System.out::println);
}
}
练习:组合[concat]、结果收集[list]
已知数组arr1中有如下元素{郭靖,杨康},arr2中有如下元素{黄蓉,穆念慈},使用Stream将二者合并到List集合
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
Stream<String> streamA = Stream.of("郭靖", "杨康");
Stream<String> streamB = Stream.of("黄蓉", "穆念慈");
List<String> strList = Stream.concat(streamA, streamB).collect(Collectors.toList());
}
}
练习:获取并发流
请分别写出获取并发流的两种方式。
public class Test {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
Stream<String> parallelStream1 = coll.parallelStream();
Stream<Integer> parallelStream2 = Stream.of(100, 200, 300, 400).parallel();
}
}
函数式接口习题
练习:函数式接口
①. 定义一个函数式接口CurrentTimePrinter,其中抽象方法void printCurrentTime(),使用注解@FunctionalInterface
②. 在测试类中定义static void showLongTime(CurrentTimePrinter timePrinter),该方法的预期行为是使用timePrinter打印系统当前毫秒值
③. 测试showLongTime(),通过lambda表达式完成需求
@FunctionalInterface
public interface CurrentTimePrinter
{
void printCurrenTime();
}
public class Test01 {
public static void main(String[] args) {
showLongTime(()->System.out.println(System.currentTimeMillis()));
}
public static void showLongTime(CurrentTimePrinter timePrinter){
timePrinter.printCurrentTime();
}
}
练习:函数式接口
①. 定义一个函数式接口IntCalc,其中抽象方法int calc(int a , int b),使用注解@FunctionalInterface
②. 在测试类中定义static void getProduct(int a , int b ,IntCalc calc), 该方法的预期行为是使用calc得到a和b的乘积并打印结果
③. 测试getProduct(),通过lambda表达式完成需求
IntCalc接口:
@FunctionalInterface
public interface IntCalc {
int calc(int a, int b);
}
测试类:
public class Test02 {
public static void main(String[] args) {
getProduct(2,3,(a,b)->a*b);
}
public static void getProduct(int a, int b, IntCalc intCalc){
int product = intCalc.calc(a,b);
System.out.println(product);
}
}
练习:静态方法引用
①. 定义一个函数式接口NumberToString,其中抽象方法String convert(int num),使用注解@FunctionalInterface
②. 在测试类中定义static void decToHex(int num ,NumberToString nts), 该方法的预期行为是使用nts将一个十进制整数转换成十六进制表示的字符串,**tips:已知该行为与Integer类中的toHexString方法一致**
③. 测试decToHex (),使用方法引用完成需求
interface NumberToString{
String convert(int num);
}
public class Test {
public static void main(String[] args) {
decToHex(999, Integer::toHexString);
}
public static void decToHex(int num ,NumberToString nts){
String convert = nts.convert(num);
System.out.println(convert);
}
}
字节流&字符流&Properties集合习题
练习:字节输出流写出字节数据
利用字节输出流一次写一个字节的方式,向D盘的a.txt文件输出字符‘a’
操作步骤:
1.创建字节输出流FileOutputStream对象并指定文件路径。
2.调用字节输出流的write(int byte)方法写出数据
public class Test01_01 {
public static void main(String[] args) throws IOException {
// 1.创建字节输出流FileOutputStream对象并指定文件路径。
FileOutputStream fos = new FileOutputStream("d:/a.txt");
// 2.调用字节输出流的write(byte[] buf)方法写出数据。
byte[] buf = "i love java".getBytes();
// 2.调用字节输出流的write(int byte)方法写出数据
fos.write(97);
// 3.关闭流
fos.close();
}
}
练习:文件的续写和换行输出
在D盘下,有一c.txt 文件中内容为:HelloWorld
在c.txt文件原内容基础上,添加五句 I love java,而且要实现一句一行操作(注:原文不可覆盖)。利用字节输出流对象往C盘下c.txt文件输出5句:”i love java”
操作步骤:
1.利用两个参数的构造方法创建字节输出流对象,参数一指定文件路径,参数二指定为true
2.调用字节输出流的write()方法写入数据,在每一行后面加上换行符:”\r\n”
public class Test01_03 {
public static void main(String[] args) throws IOException{
// 1.创建字节输出流FileOutputStream对象并指定文件路径,并追加方式
FileOutputStream fos = new FileOutputStream("c:/c.txt",true);
// 2.调用字节输出流的write方法写出数据
// 2.1 要输出的字符串
String content = "i love java \r\n";
for (int i = 0; i< 5; i++) {
fos.write(content.getBytes());
}
// 3.关闭流
fos.close();
}
}
/*
定义变量接收读取的字节
int len = -1;
// 循环从流中读取数据
while((len = fis.read()) != -1) {
System.out.print(new String(buffer,0,len));
}
*/
练习:字节流复制文件
描述: 利用字节流将E盘下的a.png图片复制到D盘下(文件名保存一致)
要求:一次读写一个字节的方式
操作步骤:
1.创建字节输入流对象关联文件路径:E盘下的a.png
2.创建字节输出流对象关联文件路径:D盘下的a.png
3.使用循环不断从字节输入流读取一个字节,每读取一个字节就利用输出流写出一个字节。
4.关闭流,释放资源
public class Test01_06 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象并关联文件
FileInputStream fis = new FileInputStream("e:/a.png");
// 创建字节输出流对象并关联文件
FileOutputStream fos = new FileOutputStream("d:/a.png");
// 定义变量接收读取的字节数
int len = -1;
// 循环读取图片数据
while((len = fis.read()) != -1) {
// 每读取一个字节的数据就写出到目标文件中
fos.write(len);
}
// 关闭流
fis.close();
fos.close();
}
练习:IO对象Properties结合使用,设置properties文件
我有一个文本文件score.txt,我知道数据是键值对形式的,但是不知道内容是什么。
请写一个程序判断是否有”lisi”这样的键存在,如果有就改变其实为”100”
score.txt文件内容如下:
zhangsan = 90 lisi = 80 wangwu = 85
操作步骤:
1.创建一个空的Properties集合
2.读取数据到集合中
3.遍历集合,获取到每一个key
4.判断当前的key 是否为 “lisi”,如果是就把”lisi”的值设置为100
5.把集合中所有的信息,重新存储到文件中
void | store(OutputStream out, String comments) 此适合使用load(InputStream)方法加载到Properties表中的格式,将此Propeirties表中的属性列表(键和元素对写入输出流) |
---|
public class Test02_06 {
public static void main(String[] args) throws IOException {
//1:创建一个空的集合
Properties prop = new Properties();
//2:读取数据到集合中
prop.load(new FileInputStream("score.txt"));
//3:遍历集合,获取到每一个key
Set<String> keys = prop.stringPropertyNames();
//获取到每一个key
for (String key : keys) {
//4:判断当前的key 是否为 "lisi"
if ("lisi".equals(key)) {
//把"lisi"的值设置为100
prop.setProperty(key, "100");
}
}
//把集合中所有的信息,重新存储到文件中
prop.store(new FileOutputStream("score.txt"), "haha");
}
}
缓冲流&转换流习题
练习:高效字节输出流写出字节数据
描述: 利用高效字节输出流往C盘下的d.txt文件输出一个字节数。
操作步骤:
1.创建字节输出流对象关联文件路径
2.利用字节输出流对象创建高效字节输出流对象
3.调用高效字节输出流对象的write方法写出一个字节
4.关闭高效流,释放资源。
public class Test01_01 {
public static void main(String[] args) throws IOException {
// 创建字节输出流FileOutputStream对象并指定文件路径。
FileOutputStream fos = new FileOutputStream("c:\\d.txt");
// 利用字节输出流创建高效字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 调用高效字节输出流对象的write(int byte)方法写出一个字节数据
bos.write(97);
// 关闭流
bos.close();
}
}
练习:高效字节输出流写出字节数组数据
描述: 利用高效字节输出流往C盘下的e.txt文件写出一个字节数组数据,如写出:”i love java”
操作步骤:
1.创建字节输出流对象关联文件路径
2.利用字节输出流对象创建高效字节输出流对象
3.定义字符串存放要输出的数据,然后将字符串转换为字节数组。
4.调用高效字节输出流对象的write方法将字节数组输出。
5.关闭高效流。
public class Test01_02 {
public static void main(String[] args) throws IOException {
// 创建字节输出流FileOutputStream对象并指定文件路径。
FileOutputStream fos = new FileOutputStream("c:\\e.txt");
// 利用字节输出流创建高效字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 调用高效字节输出流对象的write(byte[] buff)方法写出一个字节数据
bos.write("i love java".getBytes());
// 关闭流
bos.close();
}
}
练习:高效流文件复制
描述: 利用高效字节输入流和高效字节输出流完成文件的复制。
要求:
1.将C盘下的c.png文件复制到D盘下
2.一次读写一个字节数组方式复制
操作步骤:
①.创建字节输入流对象并关联文件路径
②.利用字节输入流对象创建高效字节输入流对象
③.创建字节输出流对象并关联文件路径
④.利用字节输出流对象创建高效字节输出流对象
⑤.创建字节数组用来存放读取的字节数
⑥.利用高效字节输入流循环读取文件数据,每读取一个字节数组,利用高效字节输出流对象将字节数组的内容输出到目标文件中。直到读取到文件末尾。
⑦.关闭高效流对象
public class Test01_03 {
public static void main(String[] args) throws IOException{
// 创建字节输入流对象并关联文件路径
FileInputStream fis = new FileInputStream("c:\\c.png");
// 利用字节输出流对象创建高效字节输出流对象
BufferedInputStream bis = new BufferedInputStream(fis);
// 创建字节输出流对象并指定文件路径。
FileOutputStream fos = new FileOutputStream("d:\\c.png");
// 利用字节输出流创建高效字节输出流对象
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 定义字节数组接收读取的字节
byte[] buffer = new byte[1024];
// 定义变量接收读取的字节数
int len = -1;
// 循环读取图片数据
while((len = bis.read(buffer)) != -1) {
// 每读取一个字节的数据就写出到目标文件中
bos.write(buffer,0,len);
}
// 关闭流
bis.close();
bos.close();
}
}
练习:高效字符流和集合的综合使用
描述:
分析以下需求,并用代码实现
实现一个验证码小程序,要求如下:
① 在项目根目录下新建一个文件:data.txt,键盘录入3个字符串验证码,并存入data.txt中,要求一个验证码占一行;
② 键盘录入一个需要被校验的验证码,如果输入的验证码在data.txt中存在:在控制台提示验证成功,如果不存在控制台提示验证失败
public class Test {
public static void main(String[] args) throws IOException {
writeString2File();
verifyCode();
}
private static void writeString2File() throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("D:\\Clash\\a.txt")));
String line = null;
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入第"+(i+1)+"个字符串验证码");
line = sc.nextLine();
bw.write(line);
bw.newLine();
}
bw.close();
}
private static void verifyCode() throws IOException {
ArrayList<String> list = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader(new File("D:\\Clash\\a.txt")));
String line = null;
while(null!=(line = br.readLine())){
list.add(line);
}
br.close();
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个验证码");
String code = sc.nextLine();
if (list.contains(code)){
System.out.println("验证成功");
}else {
System.out.println("验证失败");
}
}
}
练习:转换输出流的使用
描述: 现有一字符串:”我爱Java”。将该字符串保存到当前项目根目录下的a.txt文件中。
要求:使用gbk编码保存。
注意:idea的默认编码是utf-8,所以可以通过fileàsettingsàfile encodings设置为gbk格式,否则打开a.txt文件看到的将会是乱码。
操作步骤:
1.创建文件字节输出流关联目标文件
2.根据文件字节输出流创建转换输出流对象,并指定编码字符集为:gbk
3.调用流对象的方法将字符串写出到文件中。
4.关闭流并释放资源。
public class Test01_05 {
public static void main(String[] args) throws IOException{
// 要保存的字符串
String content = "我爱Java";
// 创建字节输出流对象
FileOutputStream fos = new FileOutputStream("a.txt");
// 创建转换输出流对象
OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
// 调用方法写出数据
osw.write(content);
// 关闭流释放资源
osw.close();
}
}
练习:转换输入流的使用
描述: 利用转换输入流将当前项目根目录下使用gbk编码的a.txt文件的内容读取出来,并打印在控制台上。
要求:不能出现乱码的情况。
操作步骤:
1.创建字节输入流对象指定文件路径。
2.根据字节输入流对象创建转换输入流对象并指定字符集编码为:gbk
3.调用转换输入流对象的读取方法读取内容
4.关闭流释放资源
public class Test01_06 {
public static void main(String[] args) throws IOException{
// 创建字节输入流对象并关联文件
FileInputStream fis = new FileInputStream("a.txt");
// 创建转换输入流对象
InputStreamReader isr = new InputStreamReader(fis,"gbk");
// 定义字符数组存放读取的内容
char[] buffer = newchar[1024];
// 定义变量接收读取的字符个数
intlen = -1;
while((len = isr.read(buffer)) != -1) {
System.out.print(new String(buffer,0,len));
}
// 关闭流
isr.close();
}
}
继承&抽象类习题
概念
什么叫做类与类的继承,作用是什么?
就是子类继承父类的属性和行为,使得子类对象具有与父亲相同的属性、相同的行为;
作用是子类复用父类的内容
继承后,父类与子类之间,各成员有什么样的影响?
成员变量:
不重名,就没有影响;重名,就近使用,使用super分区父类变量
构造方法:
无影响,但是子类构造方法默认调用父类构造方法
成员方法:
不重名,没有影响;重名,子类重写父类方法
子类中,如何调用父类的成员?如何使用本类的成员?
父类成员方法:super.方法名
父类非私有成员变量:super.变量名
子类成员方法:this.方法名
子类成员变量:this.变量名
抽象方法与普通成员方法有什么区别?
抽象方法使用abstract关键字修饰,没有方法体;成员方法有方法体
抽象类与普通类有什么区别?
方法:
抽象类可以包含抽象方法和成员方法;普通类不可以包含抽象方法,只有成员方法
对象:
抽象类不可以创建对象;普通类可以创建对象
练习:语法练习
语法点:继承,抽象类
输出
A类中numa:10、B类中numb:20、C类中numc:30
abstract class A{
int numa = 10;
public abstract void showA();
}
abstract class B extends A{
int numb = 20;
public abstract void showB();
}
class C extends B{
int numc = 30;
@Override
public void showA() {
System.out.println("A类中numa:"+numa);
}
@Override
public void showB() {
System.out.println("B类中numb:"+numb);
}
public void showC(){
System.out.println("C类中numc:"+numc);
}
}
public class Test {
public static void main(String[] args) {
C c = new C();
c.showA();
c.showB();
c.showC();
}
}
练习:语法练习
- 语法点:继承,抽象类
- 输出
动物种类:鸭子,年龄:2岁、 入院原因:感冒、 症状为:发烧
编写步骤:
- 模拟农学院动物医疗系统信息。
- 定义抽象家禽类(Poultry)
- 私有成员变量:动物种类(name),症状(symptom),年龄(age), 病因(illness)
- 提供空参和带参构造方法
- 成员方法:
- 抽象方法症状(showSymptom)
- 普通方法基本信息(showMsg)
- 提供setXxx和getXxx方法
- 定义普通鸭子类(Duck)
- 提供空参和带参构造方法
- 重写showSymptom方法,打印症状信息。
public class Test3 {
public static void main(String[] args) {
Duck duck = new Duck("鸭子", "感冒", "发烧", 2);
duck.showMsg();
duck.showSymptom();
}
}
/*
1.定义抽象家禽类(Poultry)
*/
abstract class Poultry {
// i.成员变量(私有):
private String name;
private String illness;
// 症状(symptom)
private String symptom;
// 年龄(age)
private int age;
// ii.成员方法: showSymptom
public abstract void showSymptom();
// 成员方法: showMsg
public void showMsg() {
System.out.print("动物种类:" + name);
System.out.println(",年龄:" + age + "岁");
System.out.println("入院原因:" + illness);
}
// iii.提供空参和带参构造方法
public Poultry() {
super();
}
public Poultry(String name, String illness, String symptom, int age) {
this.name = name;
this.illness = illness;
this.symptom = symptom;
this.age = age;
}
// iv.提供setXxx和getXxx方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIllness() {
return illness;
}
public void setIllness(String illness) {
this.illness = illness;
}
public String getSymptom() {
return symptom;
}
public void setSymptom(String symptom) {
this.symptom = symptom;
}
}
// Duck 类
class Duck extends Poultry {
public Duck() {
}
public Duck(String name, String illness, String symptom, int age) {
super(name, illness, symptom, age);
}
@Override
public void showSymptom() {
System.out.println("症状为:" + getSymptom());
}
}
练习:语法练习
语法点:继承
输出:
王小平老师,讲授Java课、 李小乐同学,考试得了90分
编写步骤:
- 模拟教学管理系统师生信息。
- 定义Person类。
- 属性:姓名、年龄
- 构造方法:无参构造方法,有参构造方法
- 成员方法:getXxx方法,setXxx方法,显示基本信息showMsg方法
- 定义Teacher类,继承Person
- 属性:学科
- 构造方法:无参构造方法,有参构造方法
- 成员方法:getXxx方法,setXxx方法,讲课方法
- 定义Student类,继承Person
- 属性:分数
- 构造方法:无参构造方法,有参构造方法
- 成员方法:getXxx方法,setXxx方法,考试方法
public class Test {
public static void main(String[] args) {
// i.创建老师对象t,并把名称赋值为”王小平”,年龄赋值为30,工资赋值为8000
Teacher t = new Teacher("王小平", 30, "Java");
// iii.调用老师对象t的讲解方法
t.teach();
// iv.创建学生对象 s,并把名称赋值为”李小乐”,年龄赋值为14,成绩赋值为90分.
Student s = new Student("李小乐", 14, 90);
// vi.调用学生对象 s 的考试方法
s.exam();
}
}
class Person {
// 名称(name)
private String name;
// 年龄(age)
private int age;
// 空参构造
public Person() {
}
// 带参构造
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// setXxx和getXxx方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
2.定义老师类(Teacher),继承Person类
*/
class Teacher extends Person {
// course(科目)
private String course;
// 空参构造
public Teacher() {
}
// 带参构造方法
public Teacher(String name,int age, String course) {
super(name,age);
this.course = course;
}
// 提供setXxx和getXxx方法
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public void teach() {
System.out.println(getName() +"老师,讲授"+course +"课");
}
}
/*
3.定义学生类(Student),继承Person类
*/
class Student extends Person {
// score(成绩)
private int score;
// 无参构造
public Student() {
super();
}
// 带参构造
public Student(String name, int age,int score) {
super(name, age);
this.score = score;
}
// 提供setXxx和getXxx方法
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public void exam(){
System.out.println(getName()+"同学,考试得了:"+ score +"分");
}
}
练习:语法练习
语法点:继承
编写步骤
- 模拟汽车网站信息。
- 定义汽车Auto类
- 属性:品牌,车长,价格
- 定义SUV继承Auto类
- 属性:小型车车长标准值:4295,中型车车长标准值:5070。
- 定义判断车型方法
- 判断小型车:小于小型车车长标准值
- 判断大型车:大于中型车车长标准值
- 判断中型车:大于小型车车长标准值并且小于等于中型车车长标准值
- 测试类中,创建若干SUV对象,保存到集合,遍历集合,输出中型SUV。
public class Test5 {
public static void main(String[] args) {
// 创建SUV对象
SUV suv1 = new SUV(5079, 750000);
SUV suv2 = new SUV(4813, 760000);
SUV suv3 = new SUV(4270, 127800);
SUV suv4 = new SUV(4545, 188800);
//添加到集合中
ArrayList<SUV> list = new ArrayList<>();
list.add(suv1);
list.add(suv2);
list.add(suv3);
list.add(suv4);
// 遍历集合,查询中型SUV
for (int i = 0; i < list.size(); i++) {
SUV suv = list.get(i);
if (suv.midSUV()){
suv.showMsg();
}
}
}
}
// 定义汽车类
class Auto {
private String type;
private double length;
private double price;
public Auto() {
}
public Auto(String type, double length, double price) {
this.type = type;
this.length = length;
this.price = price;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public void showMsg() {
System.out.println("车型:" + type);
System.out.println("\t价格:" + price);
System.out.println("\t车长:" + length);
}
}
// 定义SUV类
class SUV extends Auto {
// 车长标准
private int miniLength = 4295;
private int midLength = 5070;
public SUV(double length, double price) {
super("SUV", length, price);
}
// 判断 小型车
public boolean miniSUV() {
return getLength() <= miniLength;
}
// 判断 大型车
public boolean largeSUV() {
return getLength() > midLength;
}
// 判断 中型车
public boolean midSUV() {
return getLength() > miniLength && getLength() <= midLength;
}
}
接口&多态
概念辨析
什么是接口,如何定义接口?
- 接口,是java语言中一种类型,是方法的集合
- 使用interface关键字定义接口,其中可以定义抽象方法,默认方法,私有方法,静态方法等方法
什么叫做多态,条件是什么?
一类事物的行为,具有多种表现形式
条件:
- 继承或实现[二选一]
- 方法的重新
- 父类引用指向子类对象
使用多态特性,带来了什么样的好处?
增强方法的扩展性和复用性
使用多态特性,注意什么样的弊端?
由于类型的提升,导致调用子类对象特有的方法,必须向下转型。
练习:接口
输出AAAA\n BBBB
编写步骤:
- 定义接口A,普通类B实现接口A
- A接口中,定义抽象方法showA。
- A接口中,定义默认方法showB。
- B类中,重写showA方法
- 测试类中,创建B类对象,调用showA方法,showB方法。
interface A{
public abstract void showA(); //抽象方法
public default void showB(){ //默认方法
System.out.println("BBB");
}
}
class B implements A{
@Override
public void showA() {
System.out.println("AAAA");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.showA();
b.showB();
}
}
练习:接口
输出AAA\n BBBB BBBB BBBB BBBB\n CCCC CCCC CCCC CCCC
编写步骤:
- 定义接口A,普通类B实现接口A。
- A接口中,定义抽象方法showA。
- A接口中,定义私有方法show10(String str),循环打印10次str。
- A接口中,定义默认方法showB10,showC10,分别调用show10方法,传入参数。
- 测试类中,创建B对象,调用showA方法,showB10方法,showC10方法
interface AA{
public abstract void showA();
private void show10(String str){
for (int i = 0; i < 10; i++) {
System.out.print(str + " ");
}
System.out.println();
}
public default void show10B(){
show10("BBBB");
}
public default void show10C(){
show10("CCCC");
}
}
class BB implements AA{
@Override
public void showA() {
System.out.println("AAAA");
}
}
public class Test {
public static void main(String[] args) {
BB b = new BB();
b.showA();
b.show10B();
b.show10C();
}
}
练习:接口,静态
- 编写步骤
- 定义接口A,普通类B实现接口A。
- A接口中,定义抽象方法showA。
- A接口中,定义私有静态方法show10(String str),循环打印10次str。
- A接口中,定义静态方法showB(),showC(),分别调用show10方法,传入参数。
- B类中,定义静态方法showD
- 测试类中,使用A接口,调用静态showB()方法,showC()方法,
- 测试类中,使用B类,调用showA方法,showD方法。
interface AAA{
public abstract void showA();
public static void showB() {
System.out.println("static BBBB");
show10("BBBB");
}
public static void showC(){
System.out.println("static CCCC");
show10("CCCC");
}
private static void show10(String str){
for (int i = 0; i < 10; i++) {
System.out.println(str + " ");
}
System.out.println();
}
}
class BBB implements AAA{
@Override
public void showA() {
System.out.println("AAA");
}
public void showD(){
System.out.println("DDDD");
}
}
public class Test {
public static void main(String[] args) {
AAA.showB();
AAA.showC();
BBB bbb = new BBB();
bbb.showA();
bbb.showD();
}
}
练习:接口,多态
输出:star:星星一闪一闪亮晶晶\n =======\n sun:太阳引着9大行星旋转\n sun:光照八分钟,到达地球
编写步骤
- 定义接口Universe,提供抽象方法doAnything。
- 定义普通类Star,提供成员发光shine方法
- 定义普通类Sun,继承Star类,实现Universe接口
- 测试类中,创建Star对象,调用shine方法
- 测试类中,多态的方式创建Sun对象,调用doAnything方法,向下转型,调用shine方法。
interface Universe{
public abstract void doAnything();
}
class Star{
public void shine(){
System.out.println("star:星星一闪一闪亮晶晶");
}
}
class Sun extends Star implements Universe{
@Override
public void doAnything() {
System.out.println("sun:太阳吸引着9大行星旋转");
}
@Override
public void shine() {
System.out.println("sun:光照八分钟,到达地球");
}
}
public class Test {
public static void main(String[] args) {
Star s = new Star();
s.shine();
System.out.println("====================");
Universe universe = new Sun();
universe.doAnything();
Sun sun = (Sun)universe;
sun.shine();
}
}
内部类
练习:需求实现
定义HandleAble接口,具备一个处理字符串数字的抽象方法方法HandleString(String num)。
- 处理方式1:取整数部分。
- 处理方式2:保留指定位小数,四舍五入。
开发提示:
- 匿名内部类[接口不能带方法体可以匿名内部类]的方式,调用所有抽象方法
interface HandleAble{
String handleString(String str);
}
public class Test {
public static void main(String[] args) {
String str = "23.23456789";
System.out.println("原字符串是:" + str);
HandleAble s1 = new HandleAble() {
@Override
public String handleString(String str) {
return str.substring(0,str.indexOf("."));
}
};
System.out.println("取整后:" + s1.handleString(str));
int num = 4;
HandleAble s2 = new HandleAble() {
@Override
public String handleString(String str) {
int i = str.indexOf(".") + num + 1;
char c = str.charAt(i);
//System.out.println(c);
if (c <= '4') {
return str.substring(0, i).toString();
} else {
char c1 = (char) (str.charAt(str.indexOf(".") + num) + 1);
return str.substring(0, i - 1) + c1;
}
}
};
String sss = s2.handleString(str);
System.out.println("保留" + num + "位小数后:" + sss);
}
}
练习:需求实现
- 模拟上课出勤情况。
定义学生类:
- 属性:姓名,出勤。
- 提供基本的构造方法和get方法,set方法。
定义讲师类:
- 属性:姓名。
- 提供基本的构造方法和get方法,set方法
- 成员方法:点名方法,设置每一位的学生出勤情况。假设,小明今日未出勤。
定义课程类:
- 属性:课程名称,讲师,学生集合。
- 提供基本的构造方法和get方法,set方法
- 成员方法:show方法,打印课程信息,老师姓名,学生是否上课情况。
课程名称:Java
授课老师:张老师
上课:小红
上课:小亮
旷课:小明
public class Test {
public static void main(String[] args) {
Student s = new Student("小红");
Student s1 = new Student("小亮");
Student s2 = new Student("小明");
ArrayList<Student> arr = new ArrayList<>();
arr.add(s);
arr.add(s1);
arr.add(s2);
Teacher t = new Teacher("张老师");
Course course = new Course("java",t,arr);
t.dianming(arr);
course.show();
}
}
class Student{
private String name;
private boolean come;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isCome() {
return come;
}
public void setCome(boolean come) {
this.come = come;
}
}
class Teacher{
private String name;
// 点名方法,设置每一位的学生出勤情况。假设,小明今日未出勤
public void dianming(ArrayList<Student> arr){
for (int i = 0; i < arr.size(); i++) {
Student student = arr.get(i);
if (!student.getName().equals("小明")){
student.setCome(true);
}
}
}
public Teacher() {
}
public Teacher(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Course{
private String name;
private Teacher t;
private ArrayList<Student> arr;
public Course() {
}
public Course(String name, Teacher t, ArrayList<Student> arr) {
this.name = name;
this.t = t;
this.arr = arr;
}
public void show(){
System.out.println("课程名称:" + name);
System.out.println("授课老师:" + t.getName());
for (int i = 0; i < arr.size(); i++) {
Student student = arr.get(i);
String name = student.getName();
if (student.isCome()) {
System.out.println("上课: " + name);
} else {
System.out.println("旷课: " + name);
}
}
}
}
练习:需求实现
- 模拟接待员接待用户,根据用户id,给用户分组。
- 定义接口Filter:
- 提供抽象方法filterUser(User u)
- 定义用户类:
- 属性:用户类型,用户id
- 提供基本的构造方法和get方法,set方法
- 定义接待员类:
- 属性:接口Filter
- 提供基本的构造方法和get方法,set方法
- 成员方法:接待用户方法,设置用户类型。
- 测试类:
- 初始化50个User对象,id为1-50。
- 创建三个接待员对象。
- 第一个接待员,设置接待规则,将10-19号用户类型设置为v1。
- 第二个接待员,设置接待规则,将20-29号用户类型设置为v2。
- 遍历用户集合,给用户分区。
public class Test {
public static void main(String[] args) {
ArrayList<User> ulist = new ArrayList<>();
for (int i = 1; i <= 50; i++) {
ulist.add(new User(i));
}
System.out.println("未分组:");
System.out.println(ulist);
Reception r1 = new Reception();
Reception r2 = new Reception();
Reception r3 = new Reception();
r1.setF(new Filter() {
@Override
public void filterUser(User u) {
if (u.getId() >= 10 && u.getId() < 20)
u.setType("v1");
}
});
r2.setF(new Filter() {
@Override
public void filterUser(User u) {
if (u.getId() >= 20 && u.getId() < 30)
u.setType("v2");
}
});
for (int i = 0; i < ulist.size(); i++) {
User user = ulist.get(i);
r1.recept(user);
r2.recept(user);
r3.recept(user);
}
System.out.println("已分组:");
for (int i = 0; i < ulist.size(); i++) {
User user = ulist.get(i);
if (i % 9 == 0) {
System.out.println();
}
System.out.print(user + " ");
}
}
}
class Reception {
Filter f;
public Filter getF() {
return f;
}
public void setF(Filter f) {
this.f = f;
}
public void recept(User u) {
if (u.getType() != null)
return;
if (f != null) {
f.filterUser(u);
return;
} else {
u.setType("A");
}
}
}
class User {
private String type;
private int id;
public User(int id) {
this.id = id;
}
public int getId() {
return id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return id + "-" + type;
}
}
interface Filter {
public abstract void filterUser(User u);
}
练习:需求实现
模拟工人挑苹果。
定义苹果类:
- 属性:大小,颜色。
- 提供基本的构造方法和get方法,set方法
定义接口CompareAble:
- 定义默认方法compare,挑选较大苹果。
定义接口实现类Compare。
定义工人类:
- 成员方法:挑选苹果Apple pickApple(CompareAble,Apple a1,Apple a2)。
测试类:
- 创建Worker对象。
- 创建两个Apple对象,一个Apple(5,”青色”),一个Apple(3,”红色”)
- 默认挑选大的苹果,打印苹果信息。
- 指定颜色挑选,通过匿名内部类实现。
代码实现,效果所示:
默认挑大的:
5.0 - 青色
挑红的:
3.0 - 红色
interface CompareAble{
default Apple compare(Apple a1, Apple a2){
return a1.getSize() > a2.getSize() ? a1 : a2;
}
}
class Apple{
private double size;
private String color;
public Apple() {
}
public Apple(double size, String color) {
this.size = size;
this.color = color;
}
public double getSize() {
return size;
}
public void setSize(double size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Apple{" +
"size=" + size +
", color='" + color + '\'' +
'}';
}
}
class Worker{
public Apple pickApple(CompareAble c, Apple a1, Apple a2){
Apple compare = c.compare(a1,a2);
return compare;
}
public class Test {
public static void main(String[] args) {
Worker worker = new Worker();
Apple apple1 = new Apple(5, "青色");
Apple apple2 = new Apple(3, "红色");
System.out.println("默认挑大的:");
Apple apple = worker.pickApple(new Com(), apple1, apple2);
System.out.println(apple);
System.out.println("挑红的:");
Apple apple3 = worker.pickApple(new Com(){
@Override
public Apple compare(Apple a1, Apple a2) {
return "红色".equals(a1.getColor()) ? a1 : a2;
}
},apple1,apple2);
System.out.println(apple3);
}
}
}
class Com implements CompareAble {
}
数组习题
练习:需求实现
模拟在一副牌中,抽取第1张,第5张,第50张扑克牌。
输出:黑桃A 黑桃5 方片J
public class Test {
public static void main(String[] args) {
String[] poker = getPoker();
// 抽取指定的三种扑克牌
int num1 = 1;
int num2 = 5;
int num3 = 50;
String[] pk3 = get3(poker , num1 ,num2,num3);
// 打印抽取的牌
for (int i = 0; i < pk3.length; i++) {
System.out.print(pk3[i] + " ");
}
}
private static String[] get3(String[] poker, int i, int i2, int i3){
String[] pk3 = new String[3];
pk3[0] = poker[i - 1];
pk3[1] = poker[i2 - 1];
pk3[2] = poker[i3 - 1];
return pk3;
}
private static String[] getPoker(){
String[] colors={"黑色","红桃","梅花","方块"};
String[] nums={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] poker = new String[54];
int index = 0;
for (int i = 0; i < colors.length; i++) {
for (int j = 0; j < nums.length; j++) {
poker[index] = colors[i] + nums[j];
index++;
}
}
poker[52] = "小王";
poker[53] = "大王";
return poker;
}
}
练习:需求实现
定义equals方法,比较数组内容是否完全一致。
开发提示:
- 长度一致,内容一致,定义为完全一致。
public class Test {
public static void main(String[] args) {
int[] arr = {1,2,3,4,3,2,1};
int[] arr2 = {1,2,3,4,3,2,1};
System.out.println(" 是否一致:" +equals(arr ,arr2));
}
// 比较数组的内容
public static boolean equals(int[] arr1, int[] arr2) {
// 长度不同,返回false
if (arr1.length != arr2.length) {
return false;
}
//
for (int i = 0; i < arr1.length; i++) {
// arr1[i] 和 arr2[i]比较
/*
* 所有元素都相同才相同,也就是只要有一个不同,这两个数组就是不同
*/
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
}
异常&线程习题
练习:异常的体系
1.请描述异常的继承体系
异常继承体系:异常的根类是java.lang.Throwable。其下有两个子类:java.lang.Error
与 java.util.Exception
。
Exception又分为编译时期异常:checked异常
与运行时期异常:runtime异常
2.请描述你对错误(Error)的理解
Error:表示不可修复的恶性的错误,只能通过修改菜吗规避错误的产生,通常是系统级别的,所以很严重。
3.描述你对异常(Expection的理解)
Exception:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且通过代码的方式修正,使程序继续运行,是必须要处理的。
4.描述你对运行时异常(RuntimeException)的理解
运行时期异常:runtime异常。在运行时期,检查异常. 在编译时期,运行异常不会编译器检测(不报错)
练习:throw与throws的区别
1.请描述throw的使用位置,作用是什么?
throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,后面语句都不执行
2.请描述throws的使用位置,作用是什么?
throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处
练习:异常的处理方式
1.异常处理方式有几种,分别是什么
异常的处理方式有两种,分别是使用 throws
和 try...catch...finally
2.详细阐述每种方式对异常是如何处理的
throws用在方法的声明上后接异常类名,是把异常抛给调用者进行处助理
try…catch…finally是捕获异常,自己处理,处理完毕后面的程序可以继续运行
try代码块中是可能出现异常的代码
catch代码块,是遇到异常,对异常进行处理的代码
finally代码块无论是否发生异常,都必须执行的代码,用于释放资源
练习:常见异常,及产生原因
请列举常见异常,并说明产生原因
NullPointerException:空指针异常
当应用试图在要求使用对象的方法使用了null时,抛出该异常;譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度
ArrayIndaexOutOfBoundsException:数组索引越界异常
当对数组的索引值为负数或大于等于数组大小时抛出此异常。
ArithmeticException:算术运算异常
程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了
NumberFormatException:数字格式异常
当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常
练习:并行、并发概念
请简单描述什么是并行,什么是并发?
并行:指两个或多个事件在同一时刻发生(同时发生)。
并发:指两个或多个事件在同一个时间段内发生。
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不 支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
它们最关键的点就是:是否是『同时』
练习:进程概念、线程概念、线程与进程联系
请描述什么是进程,什么是线程,进程与线程之间的关系,并举例说明
进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
一个程序运行后至少有一个进程,一个进程中可以包含多个线程, 但一个进程中至少包含一个线程。比如使用迅雷软件下载网络文件时,同时下载多个文件,就使用到了多线程下载。
练习:自定义异常类
请使用代码实现
每一个学生(Student)都有学号,姓名和分数,分数永远不能为负数
如果老师给学生赋值一个负数,抛出一个自定异常
// 1.定义异常类NoScoreException,继承RuntimeException 提供空参和有参构造方法
public class NoScoreException extends RuntimeException {
// 空参构造
public NoScoreException() {
super();
}
// 有参构造
public NoScoreException(String message) {
super(message);
}
/* 2.定义学生类(Student)
a)属性:name,score
b)提供空参构造
c)提供有参构造;
i.使用setXxx方法给名称和score赋值
d)提供setter和getter方法
ii.在setScore(int score)方法中
1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
2.然后在给成员score赋值.*/
public class Student {
private String name;
private int score;
// 空参构造
public Student() {
super();
}
// c)提供有参构造;
// i.使用setXxx方法给名称和score赋值
public Student(String name,int score){
setName(name);
setScore(score);
}
// d)提供setter和getter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
// i.在setScore(int score)方法中
public void setScore(int score) {
// 1.首先判断,如果score为负数,就抛出NoScoreException,异常信息为:分数不能为负数:xxx.
if(score <0){
throw new NoScoreException(":分数不能为负数:"+score);
}
// 2.然后在给成员score赋值.
this.score = score;
}
}
/*
3.定义测试类Test9
a)提供main方法,在main方法中
i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码
iii.使用空参构造创建Student对象
iv.调用setScore(int score)方法,传入一个正数,运行程序
v.调用setScore(int score)方法,传入一个负数,运行程序
*/
public class Test9 {
public static void main(String[] args) {
// i.使用满参构造方法创建Student对象,分数传入一个负数,运行程序
// Student s = new Student("景甜", -10);
// ii.由于一旦遇到异常,后面的代码的将不在执行,所以需要注释掉上面的代码
// iii.使用空参构造创建Student对象
Student s = new Student();
// iv.调用setScore(int score)方法,传入一个正数,运行程序
s.setScore(100);
// v.调用setScore(int score)方法,传入一个负数,运行程序
s.setScore(-5);
}
}
网络通信概述&TCP协议习题
练习:ip地址和端口号概念
描述:
一、请写出IP地址的概念:
IP地址:互联网协议地址(Internet Protocol Address), 俗称IP.IP地址用来给一个网络中的计算机设备做唯一的编号.
二、请写出端口号的概念:
端口号: 端口号用来给计算机里的应用程序(进程)做唯一的标识,用2个字节表示的整数,取值范围0~65535.
练习:UDP协议
判断下列说法是否正确:( X )
由于UDP面向无连接的协议,可以保证数据完整性,因此在传输重要数据时采用UDP协议.
判断错误, 因为面向无连接,容易丢失包,所以不能保证数据完整.
练习:TCP协议
TCP协议中”三次握手”,第一次握手指的是什么:
第一次握手:客户端向服务器发送请求,等待服务器确认
练习:TCP网络协议
需求说明:创建新项目,按以下要求编写代码:
在项目下创建TCP 服务器端 端口号为8888
1: 等待客户端连接 如果有客户端连接 获取到客户端对象
2: 获取到客户端对象之后 当前在服务器读取数据客户端传送数据
public class TCPServer {
public static void main(String[] args) throws Exception {
//1创建服务器对象
ServerSocket ss = new ServerSocket(8888);
//2等待客户端连接 如果有客户端连接 获取到客户端对象
Socket socket = ss.accept();
//3当前在服务器中 要读取数据 需要输入流 流由谁提供 客户端
InputStream in = socket.getInputStream();//获取输入流
//4:读数据
int len;
byte[] buffer = new byte[1024];
while((len=in.read(buffer))!=-1){
System.out.println(new String(buffer, 0, len));
}
//释放资源
in.close();
// ss.close();服务器一般不会关闭
}
}
需求说明:创建新项目,按以下要求编写代码:
在项目下创建TCP 客户端
访问之前创建的服务器端,服务器端ip127.0.0.1 端口号8888
1: 客户端连接服务器,并发送 hello.服务器,我是客户端.
2: 开启上一题服务器,等待客户端连接,客户端连接并发送数据
public class TCPClient {
public static void main(String[] args) throws Exception {
//创建 Socket客户端对象
Socket socket = new Socket("127.0.0.1", 8888);
//写数据 需要输出流 谁提供 客户端
OutputStream out = socket.getOutputStream();
//写数据
out.write("hello.服务器,我是客户端.".getBytes());
//释放资源
out.close();
socket.close();
}
}