基础知识漏洞
1.==和equals()的区别2.枚举类型3. java 堆栈内存4. 基本类型和引用类型参数传递 改变值5. 成员变量和局部变量6.集合基础7. 继承(extends)
1.继承中子类成员方法变量的访问特点2.继承中构造方法的访问特点3.方法重写注意事项(Override) 8.四种访问控制权限9.final修饰局部变量10.static关键字11.多态
1.成员变量,成员方法2.多态的应用及好处和弊端3.向上转型和向下转型 12.抽象13.接口
1.接口的成员特点2.接口和类的关系3.抽象类和接口的区别 14.内部类
1.内部类实例2.内部类对象的创建及访问(公共内部类)3.内部类对象的创建及访问(私有修饰内部类)4.匿名内部类(开发中的实际应用) 15.Math类方法16.System类方法17.Object类18.异常
1.异常简介2.Throwable的成员方法3.throws和throw的区别 19.冒泡排序20.包装类
1. 自动装箱和拆箱 21.时间日期类的常用方法
1.Date 类、SimpleDateFormat 类2. Calendar 日历类 22.集合
1.集合概述图2.Collection 集合概述和使用3.集合的遍历--迭代器4.List集合
1.List集合概述2.List集合的特有方法3.List列表的并发修改异常4.ListLterator列表迭代器 5.List集合子类特点(ArrayList and linkedList)
linkedList类的特有功能 6.Set集合
1. Set集合特点:2. 哈希(Hash)值3.HashSet集合概述和特点4.linkedHashSet集合5.TreeSet集合概述和特点
1.自然排序Comparable2。TreeSet不同随机数 23.泛型
1.泛型类2.泛型方法3.泛型接口4.类型通配符5.可变参数 24.IO流
1.IO流概述和分类2.字节流写数据 25.多线程
1.1进程1.2线程1.3多线程的实现方式1.4设置和获取线程名称1.5线程调度1.6线程控制2.线程同步
基础知识漏洞 1.==和equals()的区别2.枚举类型== 和 equals 的区别对于 == ,如果作用于基本数据类型的变量,则直接比较存储的 ‘值’ 是否相等,如果作用于引用类型的变量,则比较的是所指向对象的地址对于 equals() 方法,注意:equals() 方法不能作用于基本数据类型的变量
如果没有对 equals 方法进行重写,则比较的是引用类型的变量所指向的对象的地址;如:String、Date、等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
定义:
- 枚举可以单独定义在一个文件中,也可以嵌在其他 Java 类中。通过本例可以看到 enum 提供的 values()方法可以用于遍历所有枚举值, oridinal()方法可以用于返回枚举值在枚举类中的顺序。
package cn.itcast; //枚举可以定义在类文件中 enum Season{春,夏,秋,冬}; public class Test{ //枚举也可以定义在这里 enum Season{春,夏,秋,冬}; public static void main(String[] args){ //枚举定义在main方法中会报错 //enum Season{春,夏,秋,冬}; -- 这是错误的 for(Season s:Season){ //输出枚举每个元素 System.out.print(s+",");//春,夏,秋,冬, //输出枚举每个元素下标 System.out.print(s.ordinal()+",");//0,1,2,3, } } }
注意:
- 枚举类型不能有 public 的构造方法,但是可以定义 private 的构造方法在 enum 内部使用,这样做可以确保不能新建一个 enum 的实例。所有枚举值都是 public,static,final 类型。枚举可以实现一个或者多个接口(interface)。枚举可以定义新的变量与方法。
3. java 堆栈内存匿名内部类 – 常规写法
package com.company; public class Main { public static void main(String[] args) { new Main(){ void sound(){ System.out.println("匿名内部类"); } }.sound(); } }
–控制台输出–:
匿名内部类
4. 基本类型和引用类型参数传递 改变值int[] arr = new int[3]; 左边是堆内存 右边是栈内存 栈内存:存放局部变量 定义在方法中的变量 例如 arr 使用完毕,立即消失 堆内存:存储new出来的实体(实体,对象),数组初始化时,会为存储空间添加默认值 整数:0 浮点数:0.0 布尔:false 字符:空字符 引用数据类型:null 每new出来的东西都有一个地址值,会在垃圾回收器空闲时被回收[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcYAqAOo-1642749515446)(C:UserslwxAppDataRoamingTyporatypora-user-imagesimage-20211019115009065.png)]
5. 成员变量和局部变量public class TestDemo { public static void main(String [] args){ //定义引用类型参数变量 int[] arr = {10,20,30}; //定义基本类型参数变量 int a = 20; //基本类型形参传递 System.out.println("基本参数类型传递前:"+a);//20 change0(a); System.out.println("基本参数类型传递后:"+a);//20 //引用类型形参传递 System.out.println("调用前:"+arr[1]);//20 change(arr); System.out.println("调用后:"+arr[1]);//200 } //基本类型的参数传递 public static void change0(int a){ a=200; } //引用类型的参数传递 public static void change(int[] arr){ arr[1]=200; } }–控制台输出–
基本参数类型传递前:20
基本参数类型传递后:20
调用前:20
调用后:200
7. 继承(extends) 1.继承中子类成员方法变量的访问特点创建集合,集合增删改查,输出集合
package cn.itcast; import java.util.ArrayList; import java.util.Scanner; public class Test { public static void main(String[] args) { //创建一个集合 ArrayListarray = new ArrayList<>(); //添加三个元素 array.add("hello"); array.add("world"); array.add("java"); //指定位置添加元素 1 array.add(1,"javase"); System.out.println("array:"+array); //删除元素 array.remove("hello"); array.remove("2"); //修改元素 array.set(1,"hello1"); //返回指定索引处的元素 array.get(0); //集合长度 array.size(); } } 控制台输出:
array:[hello, javase, world, javaee, javae, java]
2.继承中构造方法的访问特点在子类方法中访问一个变量 (就近原则)
子类局部范围找子类成员范围找父类成员范围找如果都没有就报错(不考虑父亲的父亲)
3.方法重写注意事项(Override)子类中所有的构造方法默认都会访问父类中无参的构造方法为什么呢:
因为子类会继承父类中的数据,可能还会使用父类的数据,所以,子类初始化之前,一定要完成父类数据的初始化每一个子类构造方法的第一条语句默认是:super() 如果父类中没有无参构造方法,只有带参构造方法,该怎么办通过使用super关键词去显示的调用父类的带参构造方法在父类中自己提供一个无参构造方法(推荐)
8.四种访问控制权限私有方法不能被重写(父类private私有化的成员子类是无法继承的)子类方法访问权限修饰不能比父类低(public > 默认 > 私有)
变量是基本类型:final修饰指的是基本类型的 数据值 不能发生改变。变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的。 10.static关键字
static 修饰的特点
被类的所有对象共享
这也是我们判断是否使用静态关键字的条件 可以通过类名调用(推荐使用类名调用)
当然,也可以通过对象名调用
static 访问特点(总结一句话:就是静态成员方法只能访问静态成员)
非静态的成员方法
能访问静态的成员变量,能访问非静态的成员变量,能访问静态的成员方法,能访问非静态的成员方法。 静态的成员方法
能访问静态的成员方法,能访问静态的成员方法。 11.多态
1.成员变量,成员方法多态的形式:具体类多态,抽象类多态,接口多态
多态的前提:有继承或者实现的关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
2.多态的应用及好处和弊端//父类 public class Animal { public int age = 40; public void eat(){ System.out.println("动物吃东西"); } } //子类 public class Cat extends Animal{ public int age = 20; public int weight = 10; @Override public void eat() { System.out.println("猫吃鱼"); } public void palyGame(){ System.out.println("猫捉迷藏"); } } //执行类 public class Test { public static void main(String[] args) { Animal an = new Cat(); System.out.println(an.age);//这个可以输出,输出子类的20,而不是父类中的40。 System.out.println(an.weight);//这里会出现编译时期异常,因为多态情况下,对于成员变量:编译看左边(Animal an),运行也看左边。 an.eat();//输出子类中的 猫吃鱼 因为多态情况下:对于成员方法,编译看左边,运行看右边,也可以输,这是子类重写了父类的eat方法,所以最后运行子类的eat an.playGame();//编译异常,因为多态对于成员方法,编译看左边(Animal an),父类中没有playGame,那么就会报编译异常 } } 总结:多态中成员访问特点 成员变量:编译看左边,运行看左边 成员方法:编译看左边,执行看右边 为什么成员变量和成员方法的访问不一样呢? 因为成员方法有重写,而成员变量没有。
3.向上转型和向下转型//父类 public class Animal { public void eat(){ System.out.println("动物吃东西"); } } //动物 *** 作类 public class AnimalOperator { //可以通过这个方法创建多个子类,然后继承父类,重写父类的方法,调用此函数传递不同的子类对象即可输出不同子类对应的成员方法 public void useAnimal(Animal a){ a.eat(); //调用子类特有的方法(狗类的特有方法,父类中不存在),报编译时期异常 a.lookDoor(); } } //子类(子类猫类) public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } //子类(子类狗类) public class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃肉"); } public void lookDoor(){ System.out.println("狗看门"); } } //执行类 public class Test { public static void main(String[] args) { //创建动物 *** 作类的对象,调用方法 AnimalOperator al = new AnimalOperator(); Cat c = new Cat();//创建动物的子类 猫类 Dog d = new Dog();//创建动物的子类 狗类 al.useAnimal(d);//调用动物 *** 作类的 *** 作方法 将狗实例化对象传入 最终输出:狗看门 al.useAnimal(c);//调用动物 *** 作类的 *** 作方法 将猫实例化对象传入 最终输出:猫吃鱼 } } 总结: 多态的好处:可以从最后的执行类中看到,传递给动物 *** 作类不同的子类对象,可以输出不同子类对象重写父类的成员方法 (提高了程序的扩展性,具体实现;定义方法的时候,使用父类作为参数,将来在使用的时候,使用具体的子类型参与 *** 作) 多态的弊端:不能使用子类的特有功能。例如上面第32行的方法(lookDoor)定义,15行对子类特有方法调用,那么15行就会出现编译时期异常,因为父类中没有这个方法,对于成员方法在多态中,编译看左边,执行看右边,这里编译左边没有,就报错了。
12.抽象//父类 public class Animal { public void eat(){ System.out.println("动物吃东西"); } } //子类 public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } //子类的特有方法 public void playGame(){ System.out.println("猫玩球儿"); } } //执行类 public class Test { public static void main(String[] args) { //向上转型:子类实例化用父类接收 Animal a = new Cat(); a.eat();//猫吃鱼 a.playGame();//编译异常这里,编译看左边,运行看右边。 //向下转型,先创建一个向上转型,然后把父类对象强制转换成子类对象的类型 Animal a2 = new Cat(); Cat c = (Cat)a2;//向上转型 c.playGame();// } }
13.接口特点:
抽象类中可以没有抽象方法,有抽象方法的类必须是抽象类
抽象类的子类要么也是抽象类(需要实现),要么重写父类中所有的抽象方法
抽象类无法直接实例化 但是可以通过多态的方式进行实例化
//抽象类 public abstract class Animal { public abstract void eat(); public void sleep(){ System.out.println("睡觉"); } } //继承抽象类的子类 public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } //执行类 public class Test { public static void main(String[] args) { Animal a = new Cat(); a.eat();//猫吃鱼 a.sleep();//睡觉 } }
1.接口的成员特点接口使用interface修饰,类实现接口需要用implements表示
接口不能实例化,但是可以参照多态的方式,通过实现类对象实例化,这就是接口多态。
接口的实现类:1.要么重写接口中的所有抽象方法 2.要么是抽象类
2.接口和类的关系成员变量只能是常量(默认也是常量,子类无法修改)默认修饰符:public static final构造方法接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在一个类如果没有父类,默认继承Object类成员方法只能是抽象方法,jdk1.8之后可以通过default修饰用来定义普通方法默认修饰符 public abstract
3.抽象类和接口的区别
类和类的关系
继承关系,只能单继承,但是可以多层继承
public class Animal {}//爷爷类 public class Cat extends Animal{}//父类 public class catSon extends Cat{}//子类类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
public class InterImpl extends InterOne implements Inter1,Inter2,Inter3{}接口和接口的关系
继承关系,可以单继承,也可以多继承
public interface Inter1 extends Inter2,Inter3{}
14.内部类 1.内部类实例成员区别抽象类 变量,常量;有构造方法;有抽象方法,也有非抽象方法接口 常量,抽象方法关系区别类鱼类 继承,单继承类与接口 实现,可以单实现,也可以多实现接口与接口 继承,单继承,多继承设计理念区别抽象类 对类抽象,包括属性、行为接口 对行为抽象,主要是行为
抽象类是对事物的抽象,接口是对行为的抽象
2.内部类对象的创建及访问(公共内部类)public class Outer{ public class Inner{ } }内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有外部类要访问内部类的成员,必须创建对象
3.内部类对象的创建及访问(私有修饰内部类)//创建一个包含内部类的类 public class Animal { public int age = 10; //定义内部类 public class wyk{ public void show(){ System.out.println(age); } } } //执行类 public class Test { public static void main(String[] args) { //创建内部类对象 Animal.wyk w = new Animal().new wyk(); w.show(); } }
4.匿名内部类(开发中的实际应用)//创建一个包含private内部类的类 public class Animal { public int age = 10; public class wyk{ public void show(){ System.out.println(age); } } public void method(){ wyk w = new wyk(); w.show(); } } //测试类 public class Test { public static void main(String[] args) { Animal a = new Animal(); a.method();//10 } }
15.Math类方法//接口 public interface Jumpping { void jump(); } //接口 *** 作类 public class JumppingOperator { public void method(Jumpping j){ j.jump(); } } //执行类 public class JumppingDemo { public static void main(String[] args) { //需求:创建接口 *** 作类的对象,调用method方法 JumppingOperator j = new JumppingOperator(); j.method(new Jumpping() { @Override public void jump() { System.out.println("可以调高了"); } }); } }常规写法
public class Main { public static void main(String[] args) { new Main(){ void sound(){ System.out.println("匿名内部类"); } }.sound(); } }
16.System类方法public class Test { public static void main(String[] args) { //public static int abs (int a):返回参数的绝对值 System.out.println(Math.abs(88)); System.out.println(Math.abs(-88)); System.out.println("----------"); //public static double ceil (double a):返回大于或等于参数的最小double值,等于一个整数 System.out.println(Math.ceil(12.34)); System.out.println(Math.ceil(12.56)); System.out.println("----------"); //public static double floor (double a):返回小于或等于参数的最大double值,等于一个证书 System.out.println(Math.floor(12.34)); System.out.println(Math.floor(12.56)); System.out.println("----------"); //public static int round(float a):按照四舍五入返回最接近参数的int System.out.println(12.34F); System.out.println(12.56F); System.out.println("----------"); //public static int max(int a,int b):返回两个int值中的较大值 System.out.println(Math.max(66,88)); System.out.println("----------"); //public static int min(int a,int b):返回两个int值中的较小值 System.out.println(Math.min(3,4)); System.out.println("----------"); //public static double pow(double a, double b):返回a的b次幂的值 System.out.println(Math.pow(2.0,3.0)); System.out.println("----------"); //public static double random():返回值为double的正值 [0.0,1.0) System.out.println(Math.random()); } }
17.Object类public class Test { public static void main(String[] args) { long start = System.currentTimeMillis();//返回当前系统时间(以毫秒值为单位) for(int i=0; i<10000; i++){ System.out.println(i); } long end = System.currentTimeMillis();//返回当前系统时间 System.out.println("共耗时"+(end-start)+"毫秒"); System.exit(0);//终止jvm虚拟机 } }
18.异常 1.异常简介Ovject是类层次结构的根,每个类都可以将Object作为超类,所有类都可以直接或者间接的继承自该类。疑问:回想面向对象中,为什么子类的构造方法默认访问的是父类的无参构造方法呢?因为他们的顶级父类(Object)只有无参构造方法
2.Throwable的成员方法如果程序出现了问题,我们需要自己来处理,有两种方案
try … catch …
try{ 可能出现异常的代码; } catch(异常类名 变量名){ 异常的处理代码; }
3.throws和throw的区别方法名 说明 public String getMessage()返回此 throwable 的详细消息字符串 public String toString()返回此可抛出的简短描述 public void printStackTrace()把异常的错误信息输出在控制台
19.冒泡排序throws throw 用在方法声明之后,跟的是异常类名用在方法体内,跟的是异常对象名 表示抛出异常,由该方法的调用者来处理表示抛出异常,由方法体内的语句处理 表示出现异常的一种可能性,并不一定会发生这些异常执行 throw 一定抛出了某种异常
20.包装类public class Test { public static void main(String[] args) { int[] arr = {163,130,81,168,171,192,12,32,425,11}; int temp; for(int i=1;iarr[i]){ temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; } } } for(int i:arr){ System.out.print(i+" ");//11 12 32 81 130 163 168 171 192 425 } } }
1. 自动装箱和拆箱public class Test { public static void main(String[] args) { //创建包装类对象 Integer i = Integer.valueOf(123); System.out.println(i);//123 //String 转成 int String s = "100"; int a = Integer.parseInt(s); System.out.println(a);//100 //int 转成 String Integer i = Integer.valueOf(123); String s2 = String.valueOf(i); System.out.println(s2);//123 } }
21.时间日期类的常用方法 1.Date 类、SimpleDateFormat 类
装箱:把基本数据类型转换为对应的包装类类型
拆箱:把包装类类型转换为对应的基本数据类型
Integer i = 100; //自动装箱 i += 200; //i = i +200; i+200 自动拆箱; i = i + 200; 是自动装箱注意:在使用包装类类型的时候,如果做 *** 作,最好先判断是否为null,只要是对象,在使用前就必须进行不为null的判断
2. Calendar 日历类方法名 说明 public long getTime()获取的是日期对象从1970年1月1日到现在的毫秒值 public void setTime(long time)设定时间,给的是毫秒值 //方法类 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateUtils { private DateUtils(){} public static String dateToString(Date date, String format){ SimpleDateFormat sdf = new SimpleDateFormat(format); String s = sdf.format(date); return s; } public static Date stringToDate(String s,String format) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(format); Date d = sdf.parse(s); return d; } } //执行类 import java.util.Date; public class Test { public static void main(String[] args){ Date d = new Date(); String s1 = DateUtils.dateToString(d,"yyyy年HH月dd日 HH:mm:ss"); String s2 = DateUtils.dateToString(d, "HH:mm:ss"); System.out.println("年月日时分秒:"+s1);//年月日时分秒:2021年17月13日 17:39:44 System.out.println("只有时分秒:"+s2);//只有时分秒:17:39:44 String str1 = "yyyy-HH-dd HH:mm:ss"; String str2 = "HH:mm:ss"; String s3 = DateUtils.dateToString(d, str1); String s4 = DateUtils.dateToString(d, str2); System.out.println(s3);//2021-17-13 17:39:44 System.out.println(s4);//17:39:44 } }
22.集合 1.集合概述图 2.Collection 集合概述和使用常用方法:
方法名 说明 public final void set(int year,int month,int date)设置当前日历的年月日 public int get(int field)返回给定日历字段的值 public abstract void add(int field, int amount)根据日历的规则,将指定的时间量添加或减去 import java.util.Calendar; public class Test { public static void main(String[] args){ //获取对象 Calendar c = Calendar.getInstance();//多态的形式 //public int get(int field) int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH)+1;//月份从0开始,需要加1 int date = c.get(Calendar.DATE); System.out.println(year+"年"+month+"月"+date+"日");//2021年11月14日 //3年前的今天 c.add(Calendar.YEAR,-3); int year2 = c.get(Calendar.YEAR); System.out.println("3年前:"+year2+"年");//3年前:2018年 c.set(2048,11,11); int year3 = c.get(Calendar.YEAR); int month3 = c.get(Calendar.MONTH); int date3 = c.get(Calendar.DATE); System.out.println("指定的日期:"+year3+"年"+month3+"月"+date3+"日");//指定的日期:2048年11月11日 } }import java.util.Calendar; public class Test { public static void main(String[] args){ //获取对象 Calendar c = Calendar.getInstance();//多态的形式 //public int get(int field) int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int date = c.get(Calendar.DATE); System.out.println(year+"年"+month+"月"+date+"日");//2021年10月14日 } }
3.集合的遍历–迭代器是单例集合的顶层接口,他表示一组对象,这些对象也被称为Collection的元素JDK不提供此接口的任何直接实现,他提供更具体的子接口,例如:Set和List
创建Collection集合的对象
多态的方式具体的实现类ArrayList
import java.util.ArrayList; import java.util.Collection; public class DateUtils { public static void main(String[] args) { //创建Collection集合的对象 Collectionc = new ArrayList<>(); //添加元素:boolean add(E e) c.add("hello"); c.add("world"); c.add("java"); //输出集合 System.out.println(c); } } Collection集合常用方法
方法名 说明 boolean add(E e)添加元素 boolean remove(Object o)从集合中移除指定的元素 void clear()清空集合中的元素 boolean contains(Object o)判断集合中是否存在指定的元素 boolean isEmpty()判断集合是否为空 int size()集合的长度,也就是集合中元素的个数 public class DateUtils { public static void main(String[] args) { //创建Collection集合的对象 Collectionc = new ArrayList<>(); //添加元素:boolean add(E e) c.add("hello"); c.add("world"); c.add("java"); //输出集合: System.out.println(c);//[hello, world, java] //移除指定元素:boolean remove(Object o) c.remove("hello"); System.out.println(c);//[world, java] //清空集合中的元素:void clear() c.clear(); System.out.println(c);//[] //判断集合中是否存在指定的元素:boolean contains(Object o) boolean aa = c.contains("java"); System.out.println(aa);//false //判断集合是否为空:boolean isEmpty() boolean empty = c.isEmpty(); System.out.println(empty);//true //集合的长度,也就是集合中元素的个数:int size() System.out.println(c.size());//0 } }
//创建集合添加元素遍历 public class DateUtils { public static void main(String[] args) { //创建Collection集合的对象 Collection4.List集合 1.List集合概述c = new ArrayList<>(); //添加元素:boolean add(E e) c.add("hello"); c.add("world"); c.add("java"); //创建迭代器 Iterator it = c.iterator(); while(it.hasNext()){ String next = it.next(); System.out.print(next+" ");//hello world java } } } //存储学生对象并遍历 public class Test { public static void main(String[] args){ Student st1 = new Student("学生1",22); Student st2 = new Student("学生2",23); Student st3 = new Student("学生3",24); //创建Collection集合的对象 Collection c = new ArrayList<>(); c.add(st1); c.add(st2); c.add(st3); Iterator it1 = c.iterator(); while(it1.hasNext()){ Student next = it1.next(); System.out.println("学生姓名:"+next.getName()+"学生年龄:"+next.getAge()); } } } ---控制台输出--- 学生姓名:学生1学生年龄:22 学生姓名:学生2学生年龄:23 学生姓名:学生3学生年龄:24
2.List集合的特有方法有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素与Set集合不同,列表通常允许重复的元素
List集合特点
有序: 存储和取出的元素顺序一致可重复:存储的元素可以重复
public class Test { public static void main(String[] args){ //创建集合对象 Listlist = new ArrayList<>(); //添加元素 list.add("hello"); list.add("world"); list.add("java"); //添加重复的元素 list.add("world"); //迭代器遍历 Iterator it = list.iterator(); System.out.print("List集合(有序,可重复): "); while(it.hasNext()){ String next = it.next(); System.out.print(next+" ");//List集合(有序,可重复): hello world java world } } }
3.List列表的并发修改异常方法名 说明 void add(int index, E element)在此集合中的指定位置插入指定的元素 E remove(int index)删除指定索引处的元素,返回被删除的元素 E set(int index, E element)修改指定索引处的元素,返回被修改的元素 E get(int index)返回指定索引处的元素 public class Test { public static void main(String[] args){ //创建集合对象 Listlist = new ArrayList<>(); //添加元素 list.add("hello"); list.add("world"); list.add("java"); //指定位置添加元素 list.add(1,"javase"); //下面这个会出现索引越界异常 IndexOutOfBoundsException,因为没有11这个索引位置 //list.add(11,"javase"); //E remove(int index):删除指定索引处的元素,返回被修改的元素 System.out.println(list.remove(1));//返回字符串 javase //E set(int index, E element): 修改指定索引处的元素,返回被修改的元素 System.out.println(list.set(1,"one"));//返回字符串 javase //E get(int index):返回指定索引处的元素 System.out.println(list.get(1));//one //输出集合所有元素 System.out.println(list);//[hello, one, java] //遍历集合 for(String str:list){ System.out.println(str); } } }
4.ListLterator列表迭代器import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class Test { public static void main(String[] args) { Listlist = new ArrayList (); list.add("hello"); list.add("world"); list.add("java"); //解决方案一:通过for循环解决解决 Iterator iterator = list.iterator(); for (int i = 0; i < list.size(); i++) { String str = list.get(i); if (str.equals("world")) { list.add("javaee"); } } System.out.println(list);//[hello, world, java, javaee] //解决方案二:通过列表迭代器(ListLterator) ListIterator iterator2 = list.listIterator(); while (iterator2.hasNext()) { String ss = iterator2.next(); if (ss.equals("world")) { iterator2.add("javaee"); } } System.out.println(list);//[hello, world, javaee, java, javaee] } }
(例子在上面的解决方案二)
5.List集合子类特点(ArrayList and linkedList)ListLterator:列表迭代器
通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代的当前位置
ListLterator中的常用方法
方法 说明 E next()返回迭代中的下一个元素 boolean hasNext()如果迭代具有更多元素,则返回true E previous()返回列表中的上一个元素 boolean hasPrevious()如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true void add(E e)将指定的元素插入列表
linkedList类的特有功能List集合常用子类:ArrayList,linkedList,这两个子类都可以使用父类(List)的方法
ArrayList:底层数据结构是数组,查询快,增删慢linkedList:底层数据结构是链表,查询慢,增删快
6.Set集合 1. Set集合特点:方法名 说明 public void addFirst(E e)在该列表开头插入指定的元素 public void addLast(E e)将指定的元素追加到此列表的末尾 public E getFirst()返回此列表中的第一个元素 public E getLast()返回此列表中的最后一个元素 public E removeFirst()从此列表中删除并返回第一个元素 public E removeLast()从此列表中删除并返回最后一个元素 import java.util.linkedList; public class Test { public static void main(String[] args) { linkedListlist = new linkedList<>(); list.add("java"); list.add("hello"); list.add("world"); System.out.println(list);//[java, hello, world] list.addFirst("first"); System.out.println(list);//[first, java, hello, world] list.addLast("end"); System.out.println(list);//[first, java, hello, world, end] String str1 = list.getFirst(); System.out.println(str1);//first String str2 = list.getLast(); System.out.println(str2);//end list.removeFirst(); System.out.println(list);//[java, hello, world, end] list.removeLast(); System.out.println(list);//[java, hello, world] } }
2. 哈希(Hash)值Set包含 HashSet和TreeSet
不包含重复元素的集合没有带索引的方法,所以不能使用普通for循环遍历
public class Test { public static void main(String[] args) { Setset = new HashSet (); //添加元素 set.add("hello"); set.add("world"); set.add("java"); //不包含重复元素 set.add("java"); for(String str : set){ System.out.print(str+" ");//world java hello } } }
3.HashSet集合概述和特点哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
public int hashCode(): 返回对象的哈希码值
对象的哈希值特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
public class Test { public static void main(String[] args) { Student st1 = new Student(); Student st2 = new Student("林青霞", 22); //同一个对象多次调用hashcode() 方法返回值哈希值是相同的 这是调用object的hashcode System.out.println(st1.hashCode());//460141958 System.out.println(st1.hashCode());//460141958 //默认情况下 如果在student类中对object的hashcode重写 那么值就成了重写方法体的内容了 System.out.println(st2.hashCode());//1163157884 System.out.println("=========="); System.out.println("hello".hashCode());//99162322 System.out.println("world".hashCode());//113318802 //字符串调用hashcode() 一样 是因为String重写了object的方法 System.out.println("java".hashCode());//3254818 System.out.println("java".hashCode());//3254818 System.out.println("重地".hashCode());//1179395 System.out.println("童话".hashCode());//1011096 } }
4.linkedHashSet集合HashSet集合特点
底层数据结构是哈希表对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致没有带索引的方法,所以不能使用普通for循环遍历由于是Set集合,所以是不包含重复元素的集合
public class Test { public static void main(String[] args) { HashSeths = new HashSet<>(); hs.add("你好"); hs.add("java"); hs.add("world"); hs.add("world"); for(String i:hs){ //元素输出不一致 System.out.print(i+" ");//java world 你好 } } } HashSet要保证元素唯一性,需要重写hashCode()和equals() 方法,如下
//学生实体类 public class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name != null ? name.equals(student.name) : student.name == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } } //测试类 import java.util.HashSet; public class Test { public static void main(String[] args) { HashSeths = new HashSet<>(); Student st1 = new Student("学生1",19); Student st2 = new Student("学生2",23); Student st3 = new Student("学生3",25); //创建重复元素对象 Student st4 = new Student("学生3",25); hs.add(st1); hs.add(st2); hs.add(st3); //添加重复元素对象 hs.add(st4); for(Student i:hs){ System.out.println(i.getName()+","+i.getAge()); } } } -----控制台输出----- 学生1,19 学生3,25 学生2,23
5.TreeSet集合概述和特点linkedHashSet集合特点
哈希表和链表实现的Set接口,具有可预测的迭代次序由链表保证元素有序,也就是说元素的存储和取出的顺序是一致的由哈希表保证元素唯一,也就是说没有重复的元素
import java.util.linkedHashSet; public class Test { public static void main(String[] args) { linkedHashSetlist = new linkedHashSet<>(); list.add("你好"); list.add("java"); list.add("world"); //插入重复的元素 list.add("world"); for(String str:list){ System.out.print(str+" ");//你好 java world } } }
1.自然排序Comparable元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet(): 根据其元素的自然排序进行排序TreeSet(Comparator comparator): 根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以不包含重复元素的集合
import java.util.TreeSet; public class Test { public static void main(String[] args) { //创建集合对象 TreeSetts = new TreeSet<>(); ts.add(10); ts.add(40); ts.add(30); ts.add(50); ts.add(20); //添加重复元素 添加不进去,因为TreeSet存储的数据由唯一性 ts.add(30); for(Integer i:ts){ System.out.println(i); } } } -----控制台输出-----(此输出按照自然排序输出,与添加时候的顺序无关,并且没有重复值) 10 20 30 40 50
2。TreeSet不同随机数public class Student implements Comparable{ String name; int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } 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; } @Override public int compareTo(Student st) { // return 0;//零那么会认为是相同的元素,只会存储相同中第一个元素 // return 1;//升序排列 // return -1;//降序排列 int num = this.age - st.age; // return num; return num==0?this.name.compareTo(st.name):num; } } //执行类 import java.util.TreeSet; public class Test { public static void main(String[] args) { //创建集合对象 TreeSet ts = new TreeSet<>(); Student st1 = new Student("学生1",22); Student st2 = new Student("学生2",22); Student st3 = new Student("学生3",24); Student st4 = new Student("学生4",25); Student st5 = new Student("学生5",26); ts.add(st1); ts.add(st2); ts.add(st3); ts.add(st4); ts.add(st5); for(Student st:ts){ System.out.println(st.getName()); System.out.println(st.getAge()); } } }
public class Test2 { public static void main(String[] args) { Set23.泛型set = new TreeSet ();// Random r = new Random(); while(set.size()<10){ set.add(r.nextInt(20)+1); } System.out.println(set);//[1, 2, 3, 4, 9, 11, 13, 14, 16, 20] } }
1.泛型类泛型:是JDK5引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,简而言之就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法、接口中,分别被称为泛型类、泛型方法、泛型接口。
泛型定义格式:
<类型>:指定一种类型的格式。这里的类型可以看成是形参<类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型.
泛型的好处
把运行时期的问题提前到了编译期间避免了强制类型转换
2.泛型方法//泛型类 public class Generic{ private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } } //测试类 public class Test { public static void main(String[] args) { Generic g1 = new Generic (); g1.setT("林青霞"); System.out.println(g1.getT());//林青霞 Generic g2 = new Generic (); g2.setT(30); System.out.println(g2.getT());//30 } }
3.泛型接口泛型方法的定义格式
publicvoid show(T t){} //泛型方法 public class Generic{ public void getT2(T str){ System.out.println(str); } } //测试类 public class Test { public static void main(String[] args) { Generic g2 = new Generic (); g2.getT2("你好");//你好 g2.getT2(123);//123 } }
//接口 public interface Generice4.类型通配符{ void show(T t); } //接口实现类 public class GenericImpl implements Generice { @Override public void show(T t) { System.out.println(t); } } //测试类 public class Test { public static void main(String[] args) { Generice g1 = new GenericImpl (); g1.show("林青霞");//林青霞 Generice g2 = new GenericImpl (); g2.show(30);//30 } }
5.可变参数为了表示各种泛型List的父类,可以使用类型通配符
类型通配符:>List>:表示元素类型位置的List,它的元素可以匹配任何的类型这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
类型通配符上限:List extends Number>:他表示的类型是 Number或者其子类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
类型通配符下限: super 类型>List super Number>:他表示的类型是 Number或者其父类型
import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { //类型通配符:> List> list1 = new ArrayList
24.IO流 1.IO流概述和分类可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
格式:修饰符 返回值类型 方法名(数据类型… 变量名){}范例:public static int sum(int… a){}
可变参数注意事项
这里的变量其实就是一个数组如果一个方法有多个参数,包含可变参数,可变参数要放在最后
public class Test { public static void main(String[] args) { System.out.println(sum(10)); System.out.println(sum(10,20)); System.out.println(sum(10,20,30)); System.out.println(sum(10,20,30,40)); System.out.println(sum(10,20,30,40,50)); } public static int sum(int... a){ int sum = 0; for(int i : a){ sum += i; } return sum; } }257-279
2.字节流写数据IO流概述:
IO:输入/输出(input/Output)流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输IO流就是用来处理设备间数据传输问题的常见的应用:文件复制、文件上传、文件下载
IO流的分类:
按照数据的流量划分输入流:读数据输出流:写数据按照数据类型划分字节流
字节输入流、字节输出流 字符流
字符输入流,字符输出流
一般来说,我们说IO流的分类是按照数据类型来分的,两种流如何都在什么情况下使用呢?
如果右键记事本打开能读懂,用字符流读不懂,用字节流,不知道用哪种,就用字节流(万能的流)
25.多线程 1.1进程字节流抽象基类
InputStream:这个抽象类是字节输入流的所有类的超类OutputStream:这个抽象类是表示字节输出流的所有类的超类子类名特点:子类名称都是以其父类名作为子类名的后缀
FileOutputStream:文件输出流用于将数据写入文件
FileOutputStream(String name):创建文件输出流以指定的名称写入文件
import java.io.FileOutputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { //创建字节输出流对象 FileOutputStream fos = new FileOutputStream("E:\StudyProject\IdeaJavaProject\TestOne.txt"); //void write (int b): 将指定的字节写入此文件输出流 fos.write(97); fos.write(57); fos.write(55); fos.write(58); //文本内容:a97: //最后都要释放资源 fos.close(); } }字节流写数据的三种方式
方法名 说明 void write(int b)将指定的字节写入此文件输出流,一次写一个字节数据 void write(byte[] b)将 b.length 字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 void write(byte[] b, int off, int len)将 len 字节从指定的字节数组开始,从偏移量 off 开始写入此文件输出流,一次写一个字节数组的部分数据
1.2线程进程:正在运行的程序
是系统进行资源分配和调用的独立单位每一个进程都有它自己的内存空间和系统资源
1.3多线程的实现方式线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序多线程:一个进程如果有多条执行路径,则称为多线程程序
1.4设置和获取线程名称方式1:继承Thread类
定义一个类 MyThread 继承 Thread 类在 MyThread 类中重写 run() 类创建 MyThread 类的对象启动线程
//继承Thread类 public class MyRunnable extends Thread{ @Override public void run() { for(int i=0;i<100;i++){ System.out.println(MyRunnable.currentThread().getName()+":"+i); } } } //执行类 public class MyThreadDemo { public static void main(String[] args) { MyRunnable m1 = new MyRunnable(); MyRunnable m2 = new MyRunnable(); m1.setName("高铁"); m2.setName("飞机"); m1.start(); m2.start(); } }两个小问题:
为什么要重写run()方法?因为 run() 是用来封装被线程执行的代码run() 方法和 start() 方法的区别?run():封装线程执行的代码,直接调用,相当于普通方法的调用start():启动线程;然后由JVM调用此线程的run()方法
方式2:实现Rannable接口
定义一个类MyRunnable实现Rannable接口在MyRunnable类中重写run()方法创建MyRunnable类的对象创建Thread类的对象,把MyRunnable对象作为构造方法的参数启动线程
//实现接口类 public class MyRunnable implements Runnable{ @Override public void run() { for(int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } } //执行类 public class MyThreadDemo { public static void main(String[] args) { //创建MyRunnable类的对象 MyRunnable m1 = new MyRunnable(); //创建Thread类的对象,把MyRunnable对象作为构造方法的参数 Thread t1 = new Thread(m1,"高铁"); Thread t2 = new Thread(m1,"飞机"); //启动线程 t1.start(); t2.start(); } }
1.5线程调度Thread 类中设置和获取线程名称的方法
void setName(String name):将此线程的名称更改为等于参数 nameString getName():返回此线程的名称通过构造方法也可以设置线程名称
如何获取 main() 方法所在的线程名称?
public static Thread currentThread():返回对当前正在执行的线程对象的引用
1.6线程控制线程有两种调度模型
分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些(Java使用的是抢占式调度模型)
假如计算机只有一个CPU,那么CPU在某一个时刻智能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的
Thread类中设置和获取线程优先级的方法
public final int getPriority():返回此线程的优先级
public final void setPriority(int newPriority):更改此线程的优先级
线程默认优先级是5;线程优先级的范围是:1-10
线程优先级高仅仅表示线程获取的CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果
需求:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
思路:
定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100;在SellTicket类中重写run()方法实现买票,代码步骤如下A:判断票数大于0,就卖票,并告知是哪个窗口卖的B:卖了票,总票数要减1C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下A:创建SellTicket类的对象B:创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称C:启动线程
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)