关于最近学习的分享
咳咳,无敌靓仔又来了哈哈,我来给你们分享一下我最近学习的状况。嗯。。。怎么说呢,有点迷,最近学习了集合还有线程。方法很好,很实用,但是记得太多了,有很多很多方法,前面一段时间学习感觉还可以,但是最近感觉学习的不怎么样,很迷。
但是,每个人都有自己的学习方式,我下来做总结复习,然后我觉得还可以,就是不管怎么说,学习什么东西都得靠自己,拼不了父母就拼自己的命,我相信终有一天,我会出人头地。不畏过去,不畏将来.奥力给!!!
下面由靓仔同学为大家分享学习的成果
1.接口和抽象类的区别
三个:
抽象类:
成员变量:可以是变量也可以是常量
成员方法:可以 是抽象方法也可以是非抽象方法
构造方法:存在,继承关系(无参构造/有参构造),对数据进行初始化
接口:
只能是常量:
存在默认修饰符:public static final
成员方法:只能是抽象方法,默认修饰符:public abstract
构造方法:不存在构造方法
2)关系的区别
类与类之间:单继承,并不能多继承,可以多层继承
类与接口:实现关系,继承一个类的同时,也可以实现多个接口
接口与接口:继承关系,也可以但继承,可以多继承
3)设计理念的区别
抽象类---->继承关系----体现的一种"is a"关系
接口----->提供额外的功能----体现的一种"like a"的关系
2.Object类中的toString方法的含义是什么
object代表任意的Java类型,直接输出对象名称相当于调式这个对象的toString()方法,默认的打印出来是一个包名.类名@十6进制数据(地址值)
Object类的任意子类都需要重写toString(),能够描述当前对象的简易并且易于读懂的信息表达式
atl+shift+s--s
3.equals和==的区别
==:如果连接的两个基本数据类型(整数默认:int) 比较的是两个数据值是否相等
如果连接的是两个引用数据类型:比较的是两个对象的地址值是否相等
equals方法:属于Object类的一个方法
如果不重写Object类中eqauls方法,默认比较的是地址值是否相等;重写Object
类中的equals方法,比较的是两个对象的内容(成员变量..)是否相等
public boolean equals(Object obj){
return (this==obj);
}
4.final关键字的特点
final关键字:
状态修饰符:最终的,无法更改的
可以修饰类,该类不能继承
修饰成员变量,此时变量是一个常量 : public static final 基本数据类型:int num = 100 ;(编译时期常量:不需要通过Jvm加载)
public static final Integer num = 100 ; 运行时期常量(需要加载这个类型)
可以修饰成员方法:此时方法不能重写!
finally
finalize()
5.多态的前提条件以及成员访问特点
1)继承关系
2)存在方法重写
3)父类引用指向子类对象(向上转型)
成员访问特点:
Fu f = new Zi() ;
成员变量:编译看左边,运行看左边
成员方法:编译看左边,运行看右边:存在方法重写
静态的方法:编译看左,运行看左
构造方法:继承关系--->分层对数据进行初始化
6.匿名内部类的格式以及本质是什么?
new 类名(抽象类)/接口名(){
重写方法(){...}
};
本质:继承了该抽象类或者实现了接口的子类对象!
www.jd.com 门户网站---- 服务器 ip地址 张三,登录了
shouji.jd.com ----- 服务器
item.jd.com
cart.jd.com
protected Object clone() throws CloneNotSupportedException
克隆方法:创建并返回此对象的一个副本
//Object 类的 clone 方法执行特定的复制操作。
首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
import java.io.InputStream;/字节输入流
import java.io.PrintStrem;//字节打印流
Scanner类中提供了一些判断功能:
public boolean hasNextXXX():判断当前是否是执行XXX类型
(xxx)int,short,float,double...
public XXX nextXXX() :接收指定XXX类型
举例:
public boolean haxNextInt() :判断接收的类型是否是int类型
public int nextInt() : 接收指定的int类型的数据
Scanenr:键盘录入的细节问题
先录入int类型,在录入String类型 (nextLine())
问题:
当前字符串录入数据:值就被漏掉了,原因就是回车符号(本身字符串)
在下一次录入String类型前,再次创建一个Scanner类型对象
所以; 先录入int数据,在录入String类型数据
7.String类型的判断功能
public boolean equals(Object anObject):比较两个字符串内容是否相同
public boolean equalsIgnoreCase(String anotherString):不区分大小写比较
public boolean startsWith(String prefix):判断是否以指定的子串开头
public boolean endsWith(String suffix):判断是否以指定的子串结尾
public boolean isEmpty():判断字符串是否为空
开发中:
equals()
equalsIgnoreCase()
startsWith()..
8.String类的获取功能:
int length():获取字符串长度
public char charAt(int index):获取指定索引处的字符
public String concat(String str):字符串拼接功能:使用当前字符串和指定str字符串进行拼接
public int indexOf(int ch):获取指定字符在此字符串中第一次出现索引值
public int indexOf(String str):获取指定字符串在此字符串中第一次出现索引值
9.String类 的分割功能
public String[] split(String regex):通过指定的字符串进行分割,返回值字符串数组
10.String类转换功能:
public char[] toCharArray():将字符串转换成字符数组
public byte[] getBytes() :将字符串----变成字节数组 (过程:编码)
public static String valueOf(XXX xx):可以将任何类型的数据转换成String
举例:
int i = 100 ;---->int --- String
String.valueOf(i) ;---->"100"
public String toUpperCase():将此字符串转换成大写
public String toLowerCase():将此字符串转换成小写
public class StringDemo2 {
public static void main(String[] args) {
String s = "helloJavaEE" ;
//public char[] toCharArray():将字符串转换成字符数组
char[] chs = s.toCharArray() ;
for(int x = 0 ; x < chs.length ;x ++) {
System.out.print(chs[x]+" ");
}
System.out.println();
System.out.println("--------------------------------");
// public byte[] getBytes() :将字符串----变成字节数组 (过程:编码)
byte[] bytes = s.getBytes() ;
for (int i = 0; i < bytes.length; i++) {
System.out.print(bytes[i]+" "); //字符的内容在ASCII码表中寻找对应的整数值
}
System.out.println();
System.out.println("---------------------------------");
//public static String valueOf(XXX xx):可以将任何类型的数据转换成String
int i = 100 ;
String s2 = String.valueOf(i) ;
System.out.println("s2:"+s2);//"100"
System.out.println("---------------------------------");
//public String toUpperCase():将此字符串转换成大写
System.out.println("toUppcase():"+s.toUpperCase());
//public String toLowerCase():将此字符串转换成小写
System.out.println("toLowerCase():"+s.toLowerCase());
}
}
1.String类的特点,以及String类作为参数有什么特点
String是一个常量,一旦被赋值,其值不能被改变!
作为形参的特点:形参的改变不会影响实际参数!效果和基本类型作为形参
2.写出String 类的常用方法列出10个
获取功能:
int length():获取字符串长度
public String concat(String str):拼接功能
public String[] split(String str):通过特点字符串内容将字符串拆分成字符串数组
char charAt(int index):获取指定索引处的字符
转换的:
public char[] toCharArray():将字符串转换成字符数组
public byte[] getBytes():平台默认编码集:将字符串转换成字节数组
public static String valueOf(int/double/float..../Object):
可以将任何类型的数据转换成String类型
public String toUppCase():将字符串内容转换成大写.....toLowerCase():转换成小写
判断功能;
public boolean isEmpty():判断字符串是否为空
public boolean equals(String anotherString):比较字符串的内容是否相同
....
4.static关键字的特点
1)随着类的加载而加载
2)优先于对象存在,不存在this关键字
3)可以被多个对象共用
4)可以被类名直接访问
类名.变量名;
类名.方法名();
5.成员变量和局部变量的区别
书写位置
成员变量:类中,方法外
局部变量:方法定义中或者方法声明上
内存位置:
成员变量:堆内存中
局部变量:栈内存中
生命周期:
成员变量:随着对象的创建而存在,随着的对象创建完毕而消失(不会立即被回收,等待GC空闲时回收)
局部变量:随着方法调用而存在,随着方法调用完毕而消失
初始化
成员变量:存在系统默认初始化
局部变量:在使用之前必须赋值,否则"可能尚未初始化"
6.String类的截取功能
public String substring(int beginIndex):从指定位置开始截取,默认截取末尾
public String substring(int beginIndex,int endIndex):从指定位置开始截取,到指定位置结束,但是包含beginIndex,不包含endIndex索引(包前不包后)
7.替换功能
public String replace(char oldChar,char newChar):将以前的字符用心的字符替换掉
public String replace(String oldStr,char newStr):将以前的字符用心的字符替换掉
public String trim():去除两端空格
public int compareTo(String anotherString);两个字符串按照字典顺序比较的结果(相同就进行下一位直到不相等,如果的一个不相等直接相减)
eg
给定一个int类型数组,将它拼接为字符串格式
int[] arr = {11,22,33,44,55} ;
"[11, 22 ,33, 44, 55]"
方式1:
使用"" + 任何数据= 字符串数据
方式2:
使用String类的concat()拼接功能
8.反转功能
StringBuffer里面reverse(),可以直接将缓冲区中字符串内容反转!
字符串反转一步走
return new StringBuffer(s).reverse().toString();
9.类型转换
1)String <----> StringBuffer类型的相互转换
StringBuffer sb = new StringBuffer(s) ;
2)其它类型转换
String----->int :Inerget.parseInt(String str)
String----->long :Long.parseLong(String str)
String----->double:Double.parseDouble(String str)
int------>String: Integer.toString(int i)
10.StringBuffer删除功能
public StringBuffer deleteCharAt(int index):删除指定位置处的字符,返回缓冲区本身
public StringBuffer delete(int start,int end):删除从指定位置到指定位置结束(包前不包后,end-1位置)
11.面试题
1)StringBuffer和数组的区别?
不同点:
他们两者都属于引用类型,而且都是"容器"
StringBuffer: 可变的字符序列 (长度可变的)
里面可以存储任何数据类型----->都是以"字符"进行拼接 通过append追加length()
数组: 长度固定,只能存储同一种类型的元素
相同点:
两者之间互相兼容的,功能是相同(添加,构造方法,替换,删除,截取..)
2)StringBuffer与StringBuilder的区别
StringBuffer:可变的字符序列
线程角度:线程安全的--->同步的---->执行效率低
在单线程程序中,StringBuilder去替换StringBuffer,因为效率高!
StringBuilder:可变的字符序列
线程角度:线程不安全的---->不同步的---->执行效率高
13.每一个基本类型提供了对应的引用类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
Integer类:包含了int类型的值
public static String toBinaryString(int i):将整数值以"二进制"文本形式体现..
public static String toOctalString(int i)
public static String toHexString(int i)
成员变量(字段)
public static final int MIN_VALUE:最小值
public static final int MAX_VALUE:最大值
Integer类的构造方法
Integer(int value) :将int类型包装了Integer类型
Integer(String s) :将字符串内容包装Integer类型
注意事项:
String是一个数字字符串,否则出现异常!
14.Jdk5提供一些特性
Jdk5提供一些特性:自动拆装箱功能,后面: 静态导入(导入到方法的级别:前提方式静态的),可变参数(public static 返回值类型 方法名(int ...))
,增强for循环(集合),泛型:类名/接口名<引用类型>
举例:
基本类型----引用类型: 自动装箱 int---->Integer
引用类型---基本数据类型 : 自动拆箱 :Integer --int
15.构造方法
Character:char类型的包装类类型,包含一个char类型的值
构造方法
public Character(char value)
判断功能:
public static boolean isDigit(char ch):判断当前字符是否是数字字符
public static boolean isLowerCase(char ch):判断当前字符是否是小写字母字符
public static boolean isUpperCase(char ch):判断当前字符是否是大写字母字符
StringBuffer,StringBuilder和数组的区别
前两个都是字符串缓冲区,都支持可变的字符序列,有相同的api
前者:它是一个线程安的,-----同步的----->执行效率低(线程安全的类)
后者:它是一个线程不安全的---不同步的---->执行效率高
单线程程序---->考虑效率问题---->后者会将前者替换掉!
多线程程序--->最重要的安全问题---->StringBuffer了
他们和数组:
都容器,都可以存储数据的!
字符串缓冲区:存储数据最终以"字符序列"存储的(StringBuffer/StringBuilder)
长度可变,可以不断追加:append(xxx)
字符串遍历:length()+charAt(int index)
数组:只能存储同一种类的元素
长度是固定的,(也是数组的弊端)
数组的遍历:length属性:获取数组长度
StringBuffer列举出几个常用的方法
public StringBuffer append(int/String/char/double/float.../Object)
public String substring(int beginIndex)
public String substring(int beginIndex,int endIndex)
构造:
StringBuffer()
StringBuffer(String str)
public StringBuffer deleteCharAt(int index)...
String类列举出5个常用方法
String char[] toCharArray()
public char chaAt(int index)
public boolean equals(String otherStr)
public String substring(int beginIndex)
public String substring(int beginIndex,int endIndex)
public int indexOf(char ch/String):查询当前字符或者子串第一次出现的索引值!
Integer i = 128 ;
Integer i2 = 128 ;
i==i2 结果是什么.为什么
false, 将常量直接赋值给Integer类型的变量:执行Integer.valueOf(i)
判断i的值是否在IntegerCache(内部类中)的缓存区 low= -128 high = 127范围之内,
在范围内,直接从缓存区中取数据;如果超出了范围,它会执行new Integer(i),地址值不一样,就是false
选择排序和冒泡排序的思想区别,核心代码体现
使用0角标对应的元素依次和后面角标对应的进行比较,小的往前放,第一次比较完毕,最小值
出现在最小索引处,依次这样比较.1,2,3....角标对应的元素比较....
冒泡排序:
两两比较,将教大的值往后放,第一次比较完毕,最大值出现在最大索引处,依次比较,就可以得到排序的数组
规律:
第一次:有0个不比
第二次:有1个不比
比较的次数:数组长度-1次
```java
Object类:
toString()
equals()
getClass()----对象名.getClass()----class 包名.类名
String类:
构造方法: 无参/有参
String()/String(byte[] bytes):解码
String(StringBuffer buffer)
转换功能:
public byte[] getBytes() :编码
public char[] toCharArray()
public String valueOf(任何类型数据)
截取功能:
public String substring(int beginIndex)
public String substring(int beginIndex,int endIndex)
获取功能
public int indexOf(char ch/String):查询当前字符或者子串第一次出现的索引值!
public String[] split(String str):分割/拆分
public String concat(String str):拼接
public int length()
判断功能:
public boolean equals(String otherStr)
StringBuffer:
反转功能:
public StringBuffer reverse()
截取
替换...
添加/删除
构造方法:
StringBuffer() /StringBuffer(String str)
Integer :
Integer(int value)
Integer(String str):数字字符串,否则出异常
jdk5自动拆装箱:
基本类型---引用类型:装箱
引用类型---基本类型:拆箱
int---String类型的相互转换
String---->int : Integer类的静态功能:public static int parserInt(String s)(重点)
int----->String:Integer类的静态功能
public static String toString(int i)
1)java.lang.Math:
```java
Math类包含用于执行基本数学运算的方法,如初等指数,对数,平方根和三角函数.
public static double abs(double a...);求某个数据的绝对值
public static double ceil(double a...);向上取整
public static double floor(double a...);向下取整
public static int min(int a,int b);求两个int数据的最小值
public static int max(int a,int b);求两个int数据的最大值
public sattic double random();随机数---------> Java提供随机数生成器:Random类 nextInt(int n)
public static int round(float a):四舍五入...
public static long round(double a);
public static double sqrt(double a):开根(一个正整数的平方根) 4---2
public static double pow(double a,double b):返回结果:a的b次幂
2)静态导入----jdk5新特性:导入到方法的级别!
动态导入:
import 包名.类名;
import java.util.Date/Scanner/List/ArrayList....
静态导入的格式:
import static 包名.类名.方法名;
前提这些方法是静态 的
使用静态导入的注意事项:
如果当前类中出现了和导入的静态方法名一样,冲突了,在使用静态导入的这个的方法的时候
就必须带上限定(包名.类名)
3)java.util.Calendar类:日历类
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,
Calendar不能直接实例化!
首先里面会存在一些静态功能,静态功能的返回值就是该类本身
public static Calendar getInstance()
public int get(int field):获取的日历字段的值!
参数:传递日历字段
Calendard的成员方法:
给日历字段添加或减去时间偏移量:public abstract void add(int field,int amount)
日历对象.add(Calender.DATE,-5);当前日历时间的五天前
设置当前年月日,日历时间
public final void set(int year,int month,int date)
public class CalendarDemo2 {
public static void main(String[] args) {
//创建日历类对象
Calendar c = Calendar.getInstance() ;
int year = c.get(Calendar.YEAR) ;
int month = c.get(Calendar.MONTH) ;
int date = c.get(Calendar.DATE) ;
System.out.println(year+"-"+(month+1)+"-"+date);//2020-10-21当前日期时间
System.out.println("--------------------------");
//3年前的今天
//public abstract void add(int field,int amount)
/*
c.add(Calendar.YEAR, -3);
int year2 = c.get(Calendar.YEAR) ;
System.out.println(year2+"-"+(month+1)+"-"+date);
*/
//5年后的10天前
//对年设置偏移量,DATE设置偏移量
c.add(Calendar.YEAR, 5);
c.add(Calendar.DATE, -10);
int year2 = c.get(Calendar.YEAR) ;
int date2 = c.get(Calendar.DATE) ;
System.out.println(year2+"-"+(month+1)+"-"+date2);
System.out.println("----------------------------------");
//public final void set(int year,int month, int date)
c.set(2018, 4,12);
int year3 = c.get(Calendar.YEAR) ;
int month3 = c.get(Calendar.MONTH) ;
int date3 = c.get(Calendar.DATE) ;
System.out.println(year3+"-"+(month3+1)+"-"+date3);
}
}
/*
* 键盘录入年份,求出年份的2月份有多少天!
*
* 分析:
* 1)创建键盘录入对象,录入年份 int
* 2)创建日历类对象 getInstance(): Calendar
* 3)通过set(int year,int month,int date) :设置一个时间
* year:键盘录入的 2 1
*
* Calendar对象.set(year,2,1) ;---->实际应该当前年份的3月1日 (month:从0-11)
* 给月中某一天设置偏移量
* add(Calendar.DATE,-1)
*
* 输出:Calendar对象.get(Calendar.DATE);
* */
public class Test {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请您输入年份值:");
int year = sc.nextInt() ;
//创建日历类对象
Calendar c = Calendar.getInstance() ;
//设置日历时间
c.set(year, 2,1); //实际应该3月1日 month+1
//再次设置对DATE字段(月中某一天)设置偏移量
c.add(Calendar.DATE, -1); //算出:2月份的最后一天(得到具体的天数)
System.out.println("当前年份有:"+c.get(Calendar.DATE)+"天");
}
}
java.util.Date类
特定的瞬间,精确到毫秒
改造方法:
public long getTime():返回1970年1月1日所表示的时间毫秒
public class DateDemo {
public static void main(String[] args) {
//创建Date对象
Date date = new Date() ;
System.out.println(date);//date格式: //Wed Oct 21 11:44:48 CST 2020
System.out.println("--------------------");
long time = date.getTime() ;
System.out.println(time);//1603252011219
关于String文本格式和Date日期格式相互转换
*
*
关于
* String文本格式 和Date日期格式相互转换
*
* Date---------------->String 日期文本格式 "格式化"操作
*
* java.text.DateFormat:可以将日期和文本相互转换
*
* DateFormat继承自Format类:都是抽象类,不能直接实例化!,提供更具体的子类
* java.text.SimpleDateFormat extends DateFormat
* 它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)
* SimpleDateFormat的构造方法
*
* public SimpleDateFormat(String pattern):
* 创建一个SimpleDateFormat对象
* 参数:指定一个模式 要遵循一定的规则(jdk对它规定了)
*
* y:年 ------2020 "yyyy"
* M:年中月份----10/03 "MM"
* d;月中的天数----05/21 'dd'
* h:表示上午/下午的小时数 hh
* H:一天中的小时数 HH
* m:分钟数 mm
* s:秒数 ss
* 模式
* "yyyy-MM-dd HH:mm:ss"
* "yyyy年MM月dd日 HH时mm分ss秒"
* Date---->String
* 格式化的步骤:
* 1)存在Date对象
* 2)创建SimpleDateFormat(String pattern)
* 3)public final String format(Date date):格式化方法
*
* 解析
* String----->Date
* 步骤:
* 1)存在String "日期文本" "2020-10-21"
* 2)创建SimpleDateFormat(String pattern)
* 3)public Date parse(String source) throws ParseException
* 解析:
* SimpleDateFormat中的参数模式:必须和String 日期文本格式一致,否则出现解析异常(ParseException)
* */
public class DateDemo2 {
public static void main(String[] args) throws ParseException {
//创建一个日期对象
Date date = new Date() ;
System.out.println(date);//Wed Oct 21 14:10:48 CST 2020 Date格式
//2)创建SimpleDateFormat:格式化的桥梁
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;//年-月-日
//3)格式化操作
String dateStr = sdf.format(date) ;
System.out.println(dateStr);
System.out.println("------------------------");
//日期文本
String source = "2022-6-30 20:00:30" ;
//String---->Date
//创建SimpleDateFormat对象
//必须和String 日期文本格式一致
//SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日") ;
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
//解析:抛出一个异常
Date d = sdf2.parse(source) ;
System.out.println(d);//Thu Jun 30 20:00:30 CST 2022
}
}
public class DateUtils {
private DateUtils() {
}
/**
* 这个方法是将Date日期格式转换成日期文本格式
* @param date 当前日期对象
* @param pattern 指定模式 yyyy-MM-dd(年月日)
* @return 返回的结果表示是当前日期文本
*/
public static String date2String(Date date,String pattern) {
//分步走
//创建SipleDateFormat对象
/*
SimpleDateFormat sdf = new SimpleDateFormat(pattern) ;
//格式化
String dateStr = sdf.format(date) ;
return dateStr ;
*/
return new SimpleDateFormat(pattern).format(date) ;
}
/**
* 这个方法是将日期文本转换成日期格式
* @param source 已知存在的日期文本
* @param pattern 指定模式 yyyy-MM-dd(年月日)
* @return 返回的结果是日期格式Date
* @throws ParseException
*/
public static Date string2Date(String source,String pattern)
throws ParseException {
//创建SimpleDateFormat对象
/*
SimpleDateFormat sdf = new SimpleDateFormat(pattern) ;
Date date = sdf.parse(source) ;
return date ;
*/
return new SimpleDateFormat(pattern).parse(source) ;
}
}
System类
```java
包含一些有用的类字段和方法,它不能被实例化
public static final InputStream in:标准的"输入流"
public static final PrintStream out:标准的"输出流"
键盘录入:
* Scanner(InputStream in) ---->Scanner(System.in)
*
* 输出语句:
* System.out.println("xxx")----->System.out--->PrintStream ps (字节打印流)
* ps.println("x") : 字节打印流调用方法名println(String str)
import java.util.Arrays;
`
public static void arraycopy(object src,int srcPos,Object dest,int destPos,int length)
从原数组中的指定位置开始进行复制指定length长度复制到目标数组中的某个位置
* 参数1:指定源数组
* 参数2:源数组中的某个位置
* 参数3:目标数组对象
* 参数4:目标数组对象中的某个位置
* 参数5:指定几个元素复制(长度)
int[] arr1 = {11,22,33,44,55} ;
int[] arr2 = {1,2,3,4,5,6} ;
//复制之前
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
System.arraycopy(arr1, 2, arr2, 3, 2);
System.out.println("-----------------------");
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toSt
import java.io.IoException;
public static void exit(int static);参数为零,表示正常终止jvm
public static long currentTimeMillis():获取当前系统时间的毫秒值
public class SystemDemo {
public static void main(String[] args) throws IOException {
System.out.println("程序开始了...");
//System.exit(0); //jvm终止了
System.out.println("程序结束了...");
System.out.println("---------------------------------");
//public static long currentTimeMillis():将当前系统时间---换算成毫秒值
//一般不单独使用
//long time = System.currentTimeMillis() ;
//System.out.println(time);//1603265022062
//计算某个程序的执行速度:耗时多长时间
long start = System.currentTimeMillis() ;
//for循环
for(int x = 0 ; x < 10000; x ++) {
System.out.println("hello"+x);
}
long end = System.currentTimeMillis() ;
System.out.println("for循环共耗时:"+(end-start)+"毫秒") ;//234毫秒
//java提供类:Runtime类:代表每一个Java程序的运行实例(Java设计:单例模式) 和系统运行环境相连接!
Runtime r = Runtime.getRuntime() ;
//获取计算机当前cpu的核数
System.out.println(r.availableProcessors());//8
//exec(String command):参数:输出 指令
r.exec("mspaint") ;
}
}
java.util.Random:随机数生成器
构造方法
public Random():(推荐),产生的随机数是变化的
public Random(long seed):每次产生的随机数是固定的!
成员方法:
public int nextInt():获取的是in挺范围内的随机数
public int nextInt(int n):获取0到n之间的随机数[0,n)
获取随机数两种方式:
Math类的random()方法:返回值double类型Random类空参构造=(int n):获取随机数
public class RandomDemo {
public static void main(String[] args) {
//创建一个随机生成器对象
Random r = new Random() ;
// public Random(long seed)
//Random r = new Random(1111) ;
//获取10个随机数
for(int x = 0 ; x < 10 ; x ++) {
//调用它的成员方法
//public int nextInt():取的int类型范围内
//int num = r.nextInt() ;
//public int nextInt(int n) :0-n之间的随机数
int num = r.nextInt(100)+1;
System.out.println(num);
}
}
}
什么是对象数组?
能够储存对象的数组
使用数组存储引用数据类型是可以实现的,但是它不满足长度可变的需求,Java提供了 ---"集合",支持长度可变的
集合特点:只能存储引用数据类型!
集合和数组的区别?
集合和数组都是"容器",储存元素!
1)长度的区别
数组的长度:固定的
集合的长度:可变的
2)储存数据类型的区别
数组:可以储存基本数据类型,也可以储存引用数据类型
int[] String[] Student[]
集合:只能储存引用数据类型
3)储存元素的区别
数字:只能储存同一种数据的元素
举例:水杯中"纯净水"
集合:可以储存任意类型的元素(类型:引用类型)
Collection:某些集合可以储存从重复元素,某些集合不能重复元素
一些集合有序,一些集合无序(有序/无序:储存元素和取出元素是否一直)
JDK 不提供此接口的任何直接 实现:
它提供更具体的子接口(如 Set 和 List)实现
java.util
Collection接口(单例集合的根接口)
基本功能
添加功能:
boolean add(Object e):将任何数据类型添加道集合中
删除功能:
void clear ();暴力删除
boolean remove(object o):移出指定的元素
判断功能:
boolean contains(Object o):判断是否包含指定的元su
boolean isEmpty();判断集合是否为空,如果为空,则返回true
Collection高级功能
boolean addAll(Collection c):添加所有
boolean containsAll(Collection c);包含所有(包含一个算包含还是包含所有?)
boolean removeAll(Collection c):删除所有 (删除一个还是删除所有算是删除?)
boolean retainAll(Collection c):一个集合对另一个集合取交集
转换功能:
Object[] toArray():将集合转换成对象数组
Iterator iterator():Collection集合的迭代器(集合的遍历方式)
public class CollectionDemo {
public static void main(String[] args) {
//创建一个Collection集合对象
// Collection c = new Collection() ;//接口不能实例化,提供了更具体的子实现类
Collection c = new ArrayList() ; //接口多态!
System.out.println(c);//[]
System.out.println("------------------------------");
//System.out.println(c.add("hello")) ;
//System.out.println(c.add("world")) ;
//System.out.println(c.add("javaee")) ;
/*
* 集合的add源码:只要添加元素,最终的结果是true
* */
c.add("hello") ;
c.add("world") ;
c.add("javaee") ;
System.out.println(c);
System.out.println("------------------------------");
//boolean remove(Object o):移出指定的元素
System.out.println("remove:"+c.remove("hello"));
void clear()
//c.clear();
//boolean contains(Object o)
System.out.println("contains:"+c.contains("ak"));
System.out.println("contains:"+c.contains("javaee"));
//boolean isEmpty()
System.out.println(c.isEmpty());
System.out.println(c);
}
}
Collection集合的高级功能:
Collection集合的高级功能:
boolean addAll(Collection c):添加一个集合中的所有元素
boolean removeAll(Collection c):问题:是删除一个算删除还是删除所有算删除?
boolean containsAll(Collection c):问题:包含一个算包含还是包含所有算包含?
public boolean retainAll(Collection c) 取交集
boolean的真实含义是什么:
@author zhangyang
Collection集合的高级功能:
Object[] toArray()
Iterator iterator():Collection集合的专有遍历方式
iterator()的返回值是接口:需要返回的是该接口的子实现类对象!
Iterator:存在一个方法
Object next():获取下一个元素
boolean hasNext():判断当前迭代器中是否有下一个可以遍历元素,
如果存在,则返回true;
迭代器的注意事项
1)Object next()获取当前集合的元素(),不能使用多次,使用一次即可,
获取所有元素信息
2)能使用for循环,不推荐(因为以后集合中元素可能不知道个数,使用while循环)
//获取迭代器
Iterator it = c.iterator() ;
泛型
什么是泛型
格式
<数据类型:引用数据类型>
特点:
将集合的类型在创建的时候就明确,保证集合操作的安全性1
好处:
1)避免了强制类型转换
2)将运行时期异常提前到了编译时期
3)解决了黄色警告线的问题
4)提高了程序的安全性
泛型可以运用在那些地方
泛型在集合中使用居多,也可以定义类上,也可以放在方法上,也可以放在接口上!
没有加入泛型之前,程序存在安全隐患,出现类型不区配
eg:ClassCastException:属于运行时期异常!
//将泛型定义在类上
//定义一个工具类
public class ObjectTool<T> {
//成员变量:定义Object类型
private T obj ;
//设置一个set方法:赋值
public void set(T obj) {//"高圆圆": Object obj = new String("高圆圆")
this.obj = obj ;
}
//get方法:获取信息
public T get() {
return obj ;
}
}
1)将泛型定义在方法上,方法形式和泛型类型保持一致
2)将泛型定义在方法上
public<T> void show(T t){
//输出
}
3)将泛型可以定义在接口上
public interface Inter<T>{
void inter( T t);
}
1)将泛型定义在接口上,子类实现明确了类型是什么类型
public class InterImpl implements Inter<String>{
@Override
public void inter(String t){
System.out.println("hello"+t);
}
}
2)将泛型定义在接口上:接口的子实现类不明确类型
public class InterImpl<T>implements Inter<T>{
@Override
public void inter(T t){
System.out.println("heloo"+t);
}
}
泛型的高级通配符:<?>
当前Object类型/任意Java类型(自定义?jdk提供...)
<? extends E>:向下限定:E类型以及它的子类
<? extends E>:向上限定:E类型以及它的子类(最起码和前面的类型保持一致)
List集合
extends Collection
有序的集合,可以容许元素重复!
有序性:储存和取出一致
使用List集合存储字符串并遍历
使用List集合存储自定义对象并遍历(自己完成!)
两种方式:
1)Object[] toArray()
2)Collection集合的Iterator
//迭代器
Iterator<String> it = list.iterator() ;
while(it.hasNext()) {//判断是否有下一个数hasNext()
String s = it.next() ;
System.out.println(s+"---"+s.length());
}
List集合的特有功能:
添加功能:
void add(int index,Object element):在指定位置处添加一个新的元素
删除功能:
Object remove(int index):删除角标对应的元素
获取功能:
Object get(int index):获取指定位置处的元素
int size():获取集合的元素数
Object set(int index,Object element):在指定位置处使用当前元素element元素替换
ListIterator<E> listIterator();List集合的专有遍历方式
ListIterator:列表迭代器
ListIterator<E> listIterator():这个方法底层实现:是通过ArrayList里面的成员内部类
ListItr extends Itr:实现的
正向遍历
booean hasNext();判断是否有下一个元素
Object next();获取下一个元素
逆向遍历
boolean hasPrevious();判断是否有上一个元素
Object previous():获取前一个元素
List集合的遍历方式:
1)Collection集合的方法 Object[] toArray
2)Collection集合的迭代器Iterator iterator()
3)size()+Object get(int index):普通for循环
4)列表迭代器:ListIteraotr listiterator()
并发:指的是在一个时间点上同时发生!
并行:指的是在一个时间段内同时发生!
解决方案:
* 1)要么使用迭代器遍历元素,使用迭代器添加元素!
* 2)要么集合遍历遍历元素,使用集合添加
这个学生类中,如果要进行自然排序(测试类中:通过TreeSet()创建对象),这个类必须实现接口:Comparable
TreeSet集合:
* 本质基于TreeMap的底层实现(红黑树结构---->自平衡"的二叉树结构")
* 有两种排序方式:
* 自然排序
* 选择器排序
*
* 取决于创建当前Set集合对象的时候的构造方法
* public TreeSet():默认的自然顺序排序
*
* TreeSet<Integer>
*
* 由于TreeSet属于Set集合(本身保证元素唯一,不重复的元素!),还可以将元素按照自然顺序排序
无参构造方法:自然排序
有参构造方法:选择排序
Map集合
java.util.Map<K,V>:接口
Java提供了集合:双列集合
* 键:K 学号:String "班级+学号id" 键的特点:必须唯一的!
* 值:V 学生Student
Map集合的特点: 一个键值对元素(一个键对应一个值,值是可以重复,但是键必须唯一)
* 只针对键有效,跟值无关! (看成是:夫妻对)
* Map<String,Student>
*
* 学生学号 学生的姓名
* 1 马伊琍
* 2 李四
* 3 王五
* 1 姚笛
Map和Collection集合的区别?
* Map<K key,V value>集合:双列集合,键映射到值的对象 ,键必须保证唯一,可以看成是一个(夫妻对)
* 遍历方式和Collection集合遍历方式不同
* Collection<E>集合:
单列集合:只能存储一种引用类型,里面的set集合依赖于Map集合的实现 (理解为:光棍)
* HashSet---->HashMap里面put方法
* TreeSet---->TreeMap里面的put方法
* Map集合的功能:
* 添加功能
* V put(K key, V value) :添加一个键值对元素
* 问题:返回值是什么意思
* /如果当前键是一次存储的时候,返回的结果null
//如果键是不是第一次存储,后面重复,将当前对应的值把以前的值覆盖掉并保存下来,返回以前的值!
刪除功能:
-
V remove(Object key):刪除指定的键,返回的是跟键关联的值,如果没有映射关系,则返回null
-
void clear():删除全部的键以及值
-
判断功能
-
boolean containsKey(Object key):是否包含指定的键
-
boolean containsValue(Object value):是否包含指定的值
-
boolean isEmpty():判断Map集合是否为空
-
高级功能:
-
Set<K> keySet():获取所有的键的集合
-
V get(Object key):通过键获取对应的值
-
Set<Map.Entry<K,V>> entrySet():获取当前Map集合中所有的键值对对象
-
K getKey() :通过键值对对象获取键
-
V getValue():通过键值对对象获取值
HashMap<K,V>是Map集合的子实现类,里面哈希表结构,保证(键唯一)
-
Map集合只只针对键有效
-
HashMap<Integer,String>键:Integer
-
HashMap<String,Student> :键:String
-
HashMap<Student,String>:键是自定义对象
-
keySet():获取Map集合的所有的键
面试题: * TreeSet集合存储自定义类型,什么情况下自然排序(Comparable),什么情况下是选择器排序(Comparator)? * * 执行无参构造方法:TreeSet<Student>():无参构造----是自然排序: * 要求当前自定义类型需要实现Comparable接口,重写comparesTo方法 * * 执行有参构造方法:TreeSet<Student>(Comparator<Student> com): * 方式1:自定义一个类实现Comparator接口中 的compare(T t1,T t2)方法 * 方式2:通过接口匿名内部类实现
晨写
1.List集合三个子实现类的特点
ArrayList:底层数据结构是数组,查询快,增删慢
从线程角度:线程不安全的,不同步的-----执行效率高!
Vector:
底层数据结构是数组,查询快,增删慢
线程角度:线程安全----同步的------执行效率低(可变因子)
LinkedList
底层数据结构是链接列表,查询慢,增删快
线程角度:线程不安全的----不同步的-----执行效率高!2.HashSet集合存储自定义对象如何去重
不重复的,能够保证元素唯一,不能保证迭代顺序恒久不变!
HashSet
HashSet的添加功能add---->HashMap集合put方法
hashCode()和equals方法对于自定义对象所在的类必须重写hashCode()和equals方法() HashSet<String>
3.List集合存储自定义对象如何去重
本身:可重复的,存储和取出一致
List
使用新集合的思想:使用新集合判断元素是否包含在该集合中!
contains()方法---->底层依赖于equals方法()List<Student>:自定义对象所在类重写equals()方法/重写hashCode()
4.集合和数组,StringBuffer的区别?
三者都是容器
StringBuffer:存储的可变的字符序列(构造字符串缓冲区),最终是以"字符串"展示
线程角度:是一个线程安全的,同步----执行效率低---->单线程程序中,使用StringBuilder替代StringBuffer集合:单例集合(Collection)
长度可变,可以存储任意类型的元素,它只能引用数类型
数组:
长度固定同一种类型的元素,它可以存储基本类型/引用类型应用场景:大部分时候会使用集合去操作!
查询所有/查询一些部分数据----存储到集合中List5.目前集合的遍历方式有几种,列举即可
Collection集合的遍历方式
List5种: Object[] toArray Collection的迭代器:Iterator iterator() List列表迭代器:ListIterator listiterator() size()和get(int index)相结合,普通for循环 增强for循环:替代迭代器,简化书写格式:foreach语句 (推荐)
6.final,finalize的区别?
final:状态修饰符,修饰类,该类不能被继承
修饰变量,此时变量是常量
修饰成员方法,该方法不能被重写
finalize:是Object类中方法,主要用来开启垃圾回收器,会调用finalize()方法,回收没有更多引用
的对象(和GC有关系!)
1.List集合遍历的方式
4种方式:
Object[] toArray()
Collection集合的迭代器:Iterator iterator()
List的特有功能:
Object get(int index)+size() 相结合:for循环
ListIterator listiterator():列表迭代器
2.泛型的好处是什么,以及格式
<引用数据类型>,可以用在类上,方法上,接口上…
好处:
1)避免了强制类型转换
2)将运行时期异常提前到了编译时期
3)解决了黄色警告线问题
4)提高了程序的安全性
3.匿名内部类的本质
本质:继承了该抽象类或者实现了接口的子类对象!
格式
new 类名(具体类名/抽象类名)/接口名(){
重写抽象方法;
} ;
4.this和super的区别
this:代表当前类对象的地址值引用
super:代表父类的空间标识(父类对象的地址值引用)
访问构造方法
this():访问本类的无参构造方法
this(xxx):访问的是本类的有参构造
super():访问父类的无参构造方法
super(xxx):访问的是父类的有参构造
成员方法:
this.方法名():访问的是本类的成员方法
super.方法名():访问的是父类的成员方法
成员变量:
this.变量名:本类的成员变量
super.变量名:父类的成员变量
5.面向对象的三大特征
封装,继承,多态(重点)
接口多态:使用最多:接口名指向子实现类名
抽象类多态:(其次)IO流中 抽象类名指向子类名 :InputStream in = new FileInputStream(“xxx.txt”)
1Map集合的遍历方式
方式1:
Set<K> keySet():获取所有键的集合
V get(Object key):通过键获取值
方式2:
Set<Map.Entry<K,V>>
entySet():通过map集合对象获取键值对对象的集合
K getKey():通过键值对对象获取键
V getValue():通过键值对对象获取值
public List<Product> findAll(){}
返回值:后台获取List列表----->前后端技术List---->传递到前台(json串)
需要在前台页面中展示所有列表数据--->将json串里面获取到遍历!
2.获取字节码文件的方式
目前有两种
Object类中的getClass()方法,任意Java类型的class属性
Class.forName("类的全限定名称")
3.List集合遍历的方式
五种
Object[] toArray();
Iterator iterator();
ListIterator listiterator();
size()+get(int index)结合的普通for
增强for:
for(集合储存数据类型 变量名:集合对象){
使用变量名....
}
4.Collection和Map集合的区别
Collection集合
Collection<E>:单例集合
它里面有两个子接口List Set:集合即可是重复的(有序的),也可以不重复(无序的)
Collection集合它的子实现类关联Map集合的子实现类相关方法
Map<K,V>:双列集合针对键有效,跟值无关(键:必须唯一,值可以重复)
HashMap<K,V>
TreeMap<K,V>
5.TreeSet集合针对自定义对象的 时候什么时候是自然排序,什么情况下是选择器排序
无参构造方法:TreeSet<自定义类型>():自然排序
条件:自定类必须实现一个接口:Comparable<T>重写public int comparTo(T t){}方法
有参构造方法:TreeSet<自定类型>(Comparator<T> com)
方式1:
自定义一个类:实现Comparator接口,重写接口中compar(T t1,T t2)方法
方式2
直接使用接口 匿名内部类来实现
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
public int compare(Student s1,Student s2){
....
}
}) ;
1.TreeSet集合存储自定义对象并按某种方式排序
按照主要条件进行排序!
自然排序
选择器排序
无参构造方法:TreeSet<自定义类型>():自然排序
条件:自定类必须实现一个接口:Comparable<T> 重写public int comparTo(T t){}方法
有参构造方法:
TreeSet<自定类型>(Comparator<T> com)
方式1:
自定义一个类:实现Comparator接口,重写接口中compar(T t1,T t2)方法
方式2
直接使用接口 匿名内部类来实现
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
public int compare(Student s1,Student s2){
....
}
}) ;
2.Map集合的遍历方式
方式1:
Set<K> keySet() :获取所有键的集合
V get(Object key):通过键获取值
方式2:
Set<Map.Entry<K,V>> entySet():通过map集合对象获取键值对对象的集合
K getKey():通过键值对对象获取键
V getValue():通过键值对对象获取值
3.Collections
针对集合操作工具类:
public static void sort(List<T> list):针对List集合自然排序
public static void sort(List<T> list,Comparator<T> com):针对:List集合进行比较器排序
max()
min()
1. 模拟斗地主洗牌和发牌
场景1:不保证牌有序的 ArrayList集合:牌盒
package com.luoliang.Arraylist_1;
import java.util.ArrayList;
import java.util.Collections;
public class CollectionsTest {
public static void main(String[] args) {
//创建一个牌盒ArrayList
ArrayList<String> array=new ArrayList<String>();
//装牌
/*
* 两个数组: 点数数数组 A 2 3 4 5 6 7 8 9 10 J Q K 花色数组:♥ ♠ ♣ ♦
*/
// 定义点数数组
String number[]= {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] colors= {"♥", "♠", "♣", "♦"};
// 2.1)将点数数组遍历,并且同时将花色数组遍历
// 将点数和花色拼接起来(String类型:concat())
//遍历
for(String num : number) {
for(String col:colors) {
String poker=col.concat(num);// 2.2)需要将牌添加到ArrayList集合 牌盒中
array.add(poker);
}
}
//储存大王小王
array.add("大王");
array.add("小王");
//3)洗牌
//Collections的静态功能:随机置换
Collections.shuffle(array);
//三个玩家
/**
* 三个玩家---->每一个玩家 看成以"集合" ArrayList
* 创建三个集合,存储对应自己的牌
* 创建一个集合:ArrayList---存储底牌:3张
* A,B,C三个人
* A--B---C ---A---B---C
* 遍历牌盒
* for(int x = 0 ; x < array.size(); x ++){
* //3个玩
* //规律
* 取底牌
* 如果
* x>=array.size()-3
* 获取底牌get(int index)
* 如果x % 3 == 0
* 获取第一个玩家的牌
* x% 3 == 1
* 获取第二个玩家的牌
* x% 3 == 2
* 获取第三个玩家的牌
* }
*/
ArrayList<String> player1 = new ArrayList<String>() ;
ArrayList<String> player2 = new ArrayList<String>() ;
ArrayList<String> player3 = new ArrayList<String>() ;
ArrayList<String> diPai = new ArrayList<String>() ;//它这个地方是给每个人还有底牌创建一个新的arraylist集合;记住
for(int x=0;x<array.size();x++) {
//判断是否是底牌
//判断三种情况
if(x>=array.size()-3) {
//底牌
diPai.add(array.get(x));
// List中get(int index)---获取集合中元素
}else if(x%3==0) {
//玩家1
player1.add(array.get(x)) ;
}else if(x%3==1) {
//玩家2
player2.add(array.get(x)) ;
}else if(x % 3 == 2) {
//玩家3
player3.add(array.get(x)) ;
}
}
/**
* 看牌
* 玩家1,玩家2,玩家3 , 同时还向看底牌
*/
lookPoker("农民", player1);
lookPoker("农民", player2);
lookPoker("地主", player3);
lookPoker("底牌", diPai);
}
private static void lookPoker(String name, ArrayList<String> array) {
// TODO Auto-generated method stub
System.out.print(name+"的牌是:");
for(String s:array) {
System.out.print(s+" ");
}
System.out.println();
}
}
场景2:洗牌和发牌 ,发到每个人的手上,牌是有序的!
package com.luoliang.Arraylist_1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
/**
* 模拟斗斗地主洗牌和发牌,并且保证每个人手上的有序!
*
* 分析:
* 1)创建牌盒
* HashMap<Integer,String>
* 键存储的是牌的编号
* 值存储的是就是每一个牌(花色和点数的拼接)
* ArrayList<Integer>
* 单独存储编号
*
* 2)装牌
* 定义一个编号:int index = 0 ;
* 定义花色字符串数组:♥ ♠ ♣ ♦
* 点数字符串数组 3 4 5 6 7 8 9 10 J Q k A 2
*
* 2.1)遍历点数数组和花色数组,拼接起来
* 2.2)给HashMap<Integer,String> 存储编号和牌
* 给ArrayList存储编号
* index ++
*
* 2.3)给HashMap<Integer,String>单独存储小王,和大王
* 给ArrayList<Integer>添加小王对应的编号 并index++
*
*
* 3)洗牌
* 洗 的是编号:
* Collections
* public static void shuffle(List<?> list):随机置换
*
* 4)发牌
* 发的也是编号,为了保证每个人手上的有序,所以三个玩家都需要TreeSet<Integer>
* for(int x = 0 ; x < array.size(); x ++){
* //3个玩
* //规律
* 取底牌
* 如果
* x>=array.size()-3
* 获取底牌get(int index)
* 如果x % 3 == 0
* 获取第一个玩家存储的编号
* x% 3 == 1
* 获取第二个玩家存储的编号
* x% 3 == 2
* 获取第三个玩家的编号
* }
*
*
* 5)看牌
* 封装成一个功能
* lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm)
*
* 遍历TreeSet集合:获取每一个手上的编号
* 在使用编号在hm集合寻找对应的值: get(K key)--->V value
* 输出牌即可!
*
*
*
*
* @author zhangyang
*
*/
public class CollectionsTest2 {
public static void main(String[] args) {
HashMap<Integer,String> hash=new HashMap<Integer,String>();
ArrayList<Integer> array=new ArrayList<Integer>();
//装牌
String[] number= {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] color= {"♥", "♠", "♣", "♦"};
//编号从零开始
int index=0;
//遍历点数数组和花色数组,拼接起来
for(String num:number) {
for(String col:color) {
//拼接
String poker=col.concat(num);//concat是拼接的意思
//将编号以及牌添加HashMap集合中
hash.put(index,poker);//他的意思就是说吧牌号和编号添加进来
//将编号存储在ArrayList集合中
array.add(index);
index++;
}
}
//储存小王
hash.put(index,"小王");
//将小王存储在ArrayList集合中
array.add(index);
index++;
//储存大王
hash.put(index,"大王");
//将大王编号存储在ArrayList集合中
array.add(index) ;
//测试
//洗牌,洗的是牌号
Collections.shuffle(array);//shuffle()该方法是打乱顺序
//发牌
//发的也是编号,为了保证每个人手上的有序,所以三个玩家都需要TreeSet<Integer>
/**
* for(int x=0;x<array.size();x++){
* x>=array.size()-3
* 获取底牌get(int index)
*
* 如果x%3==0;//%取余
* 获取第一个玩家储存的编号
*
* x%3==1;
* 获取第二个玩家存储的编号
*
* x% 3 == 2
* 获取第三个玩家的编号
* }
*
* */
TreeSet<Integer> player1=new TreeSet<Integer>();
TreeSet<Integer> player2=new TreeSet<Integer>();
TreeSet<Integer> player3=new TreeSet<Integer>();
TreeSet<Integer> dipai=new TreeSet<Integer>();
//判断底牌以及三种情况
for(int x=0;x<array.size();x++) {
//判断底牌以及三种情况
if(x>=array.size()-3) {
dipai.add(array.get(x));
}else if(x%3==0) {
//玩家1
player1.add(array.get(x)) ;
}else if(x %3 ==1) {
//玩家2
player2.add(array.get(x)) ;
}else if(x % 3 == 2) {
//玩家3
player3.add(array.get(x)) ;
}
}
//看牌
//将看牌封装成功能
//单独调用
lookpoker("地主",player1,hash);
lookpoker("农民",player2,hash);
lookpoker("农民",player3,hash);
lookpoker("底牌",dipai,hash);
}
'''
private static void lookpoker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hash) {
System.out.println(name+"的牌是");
//需要遍历TreeSet集合获取每一个手上的编号
for(Integer key:ts) {
//获取到了每一个编号
//在HashMap集合中:通过键获取值:获取的牌
String value=hash.get(key);
System.out.print(value+" ");
}
System.out.println();//换行
}
}
异常的处理方案有那些
1)try…catch…finally:标准格式 捕获异常
2)throws:抛出异常(抛出到方法上)
方式1:捕获异常的变形格式
try…catch…
try…catch…catch…
try…finally…(线程中:Lock锁)
-
格式:流程
- try{
-
...
-
...
-
可能出现问题代码
-
}catch(异常类名 变量名){//具体异常的类
-
//处理异常
-
//自己手动处理
-
- try{
/**
如果使用try…catch…catch…catch…
- 那么后面的catch语句中的异常类要么是同级关系要么是前面异常的类父类!
*/
关于Throwable中的一些方法
- public String getMessage():获取异常的消息字符串
- public String toString():获取异常信息的简述描述
- 异常的全限定名称:包名.类名:调用该异常对象的getMessage()详细的消息字符串
- public void printStacktrace():将此对象的信息追踪到堆栈中,具体获取到具体源码中那一块处问题了
针对异常处理的另一种方式:
throws:抛出异常
抛出在方法声明上,如果方法中的语句体现了异常,将异常交给jvm,jvm将异常信息输出到控制台上
面试题
throws和throw的区别
throws:抛出
书写位置在声明上
throws的后面跟的异常类名,而且可以跟多个异常类名,中间使用逗号隔开
对于throws它是由调用者进行处理,必须要对带throws的方法进行处理
throws表示抛出异常的一种肯定性(这个方法可能出现问题/可能没有问题)
throw:抛出
书写位置在方法体中
throw的后面跟的异常对象,一般都是匿名对象new XXXExceptioon();而且只能跟一个异常对象
由方法中逻辑判断进行处理(由方法体中语句进行处理)
throw:表示抛出异常一种肯定性(执行到逻辑的时候,一定会执行这个异常!)
自定义的异常!
- 1)自定义一个类,继承自Exception或者RuntimeException
- 2)提供无参构造方法 /有参构造 传递String参数(消息字符串)
异常的注意事项:
- 1)子类继承父类的时候,对父类的成员方法进行重写,如果父类的成员方法有异常
- 那么子类的该方法针对异常处理,要么是跟父类的异常类名一致,要么是父类异常类的子类
- 2)子类继承父类重写父类的方法的时候
- 父类的成员方法没有抛出异常,子类的该方法不能抛出异常,只能try…catch…
面试题
-
如果捕获异常的时候,
-
try...catch...finally,catch中如果有return语句,那么finally中的代码还会执行吗?
-
在return之前执行还是return之后执行
-
会执行,除非Jvm退出了不执行!
-
return 之前
1.什么是进程,什么是线程?
- 进程:分配?调度系统资源的基本单元,在执行过程产生一跟实例!
- 线程:是进程的执行流,进程中的某个任务
2.线程的实现方式1的步骤
关于多线程方式1:
- 自定义一个类继承自Thread类
- 重写Thread类中的run方法
- 在mian方法中创建当前线程类对象,启动线程start()启动
3.异常的处理方式有几种
两种
- 显示处理
- throws:抛出异常(为了操作方便)
- try…catch…finally:捕获异常,开发中,建议是这个方式
4.throw和thows的区别
throws
- 跟在方法声明上
- throws的后面跟的是异常类名,可以跟多个异常类名,中间使用逗号隔开
- throws抛出的异常:由调用者进行处理 (必须要对带有throws的方法进行处理!)
- throws抛出:表达的存在异常的可能性!
throws
- 在方法语句中
- throw后面跟的是异常对象,格式throw new XXException(),只能跟一个异常对象(匿名对象)
- throw抛出异常的处理---->由逻辑语句进行处理(if…else…)
- throw抛出:是存在异常的肯定性!
5.什么是finally
final,finalize
异常的处理:捕获异常的标准格式
try{
…
}catch(异常类名 对象名){
…
}finally{
//在释放相关的系统资源 ,这里面代码一定会执行 (除非:在执行finally语句之前jvm退出了!)
}
6.启动线程为什么是start而不是run方法
start()启动是通过jvm调用run方法,run方法调用只是普通方法!
start()底层是通过---public natvie....
2.异常类
Throwable
error :严重问题
以后:微服务的分布式项目中:内存溢出...
Exception:可以通过一些处理方式进行解决
编译时期异常:当前本身jdk提供的方法自带处理异常,必须解决!
运行时期异常RuntimeException:代码逻辑不够严谨导致的!
异常的处理
显示处理
throws:抛出异常 (为了操作方便)
try...catch...finally:捕获异常 开发中,建议是这个方式
4.多线程的引入
1)自定义一个类继承自Thread类
2)重写Thread类中的run方法
3)在main方法中创建当前线程类对象,启动线程 start()启动
3.线程的状态有几种呢? 6种
4.多线程的实现方式2:接口: Runnable
5. 多线程实现方式1和实现方式2对比
代理:---------->Java中一种设计模式
静态代理
动态代理
JDK动态代理
CGLib动态代理
java能够开启线程吗?
Java不能够直接开启线程的!
start方法方法—通过JVM调用
start方法本身就是同步方法----线程安全的方法
- 将所有的开启的线程(在运行之前),将线程添加到线程组中:ThreadGroup:一个线程组中包含多个线程
- 调用start0():间接实现的
- 本地方法----C++语言实现 !
public final void setDaemon(boolean on):设置守护线程
在启动线程之前,调用这个方法才能设置为守护线程 (注意事项!)
- (如果当前运行中线程都是守护线程,JVM退出)
如何获取主线程中名称呢?
- public static Thread currentThread():表示当前正在运行的线程
- getName():获取线程名称
- setName(String name):设置当前线程名称
public final void join() throws InterruptedException:等待该线程终止
public final void setPriority(int newPriority)
- 设置线程的优先级
- public final int getPriority():获取线程的优先级
- 线程的优先级: 常量值
- public static final int MAX_PRIORITY:最大优先级 10
- public static final int MIN_PRIORITY:最小优先级 1
- public static final int NORM_PRIORITY:默认优先级 5
- 优先级越大的线程抢占CPU的执行权几率大
- 优先级越小的线程抢占CPU的执行几率小
- 符号线程的执行具有随机性
public static void sleep(long millis) throws InterruptedException
- 线程睡眠 (阻塞式方法!)
- 参数为时间毫秒值!
线程的生命周期/线程的状态
-
State:线程的状态:是Thread类内部枚举
-
public enum State {
NEW, 线程新建状态 ---->public static final…
RUNNABLE,线程运行状态
BLOCKED,线程阻塞状态(sleep(),等待)
WAITING,//死死等待
TIMED_WAITING,//超时等待 等待到一定时间,不等了
TERMINATED;//线程终止!
}
@Deprecated:JDK提供内置注解:标记方法是否以过时!
- public final void stop():已过时的方法,但是可以使用!强迫线程停止执行
- public void interrupt():中断线程 :中断线程的一种状态!(6种状态),
- 打破了状态之后,继续执行程序!
public static void yield():暂停当前正在执行的线程对象,并执行其他线程!
-
理解为"谦让"
-
线程的执行随机性
多线程的实现方式2(推荐)
- 1)自定义一个类(资源类),这个类实现接口:Runnable接口—用到了Java设计模式之代理模式!
- 2)重写Runnable接口中的run方法
- 3)在主线程中main
- 3.1)创建当前资源类对象,
- 3.2)在创建Thread类对象,将3.2中的资源类对象作为参数进行传递
- 4)启动线程 start方法启动
方式1:
1)自定义一个类MyThread,继承自 Thread
2)重写Thread类中run方法
3)在main中,创建该线程类对象
MyThread my1 = new MyThread() ;
MyThread my2 = new MyThread() ;
MyThread my3 = new MyThread() ;
my1.start();
my2.start() ;
my3.start() ;
my1,my2在并发的执行
继承关系的弊端:
局限性
它不能够体现出"数据共享"的概念!
电影卖票:100张票 三个窗口
每一个窗口可能都在卖自己的100张票
线程的执行 "随机性"
原子性操作:
100张: 变量tickets (tickets--) 100 --- 99
栈内存 堆内存
MyThread my1 new MyThread() ;
MyThread my2 new MyThread() ;
MyThread my3 new MyThread() ;
第二种方式
优势:静态代理
能够体现出 “资源共享”
1)自定义一类MyRunnable implements Runnable
2)重写run方法
3)创建资源类对象,创建线程类对象,将资源类对象当做参数传递
MyRunnable my = new MyRunnable() ;
// public Thread(Runnable target, String name) :创建线程类对象并同时给线程设置名称
Thread t1 = new Thread(my, “窗口1”) ;
Thread t2 = new Thread(my, “窗口2”) ;
Thread t3 = new Thread(my, “窗口3”) ;
//启动线程
t1.start();
t2.start();
t3.start();
栈内存中 堆内存中
Thread t1 new Thread(0x01) Thread(Runnable runable)
Thread t2 ....
Thread t3 ...
MyRunnable my(0x01) ------> new MyRunnable()
package com.luoliang.Thread_4;
public class SellTicket implements Runnable {
//成员位置定义门票100张:共享
private int piao = 100 ;
Demo d=new Demo();
Object obj=new Object();
public void run() {
while(true) {
/**
* synchronized(锁对象){ //门的开/关
* 锁:可以是任意Java类对象(Object或者任意的子类)
* 多条语句对共享数据进行操作
* }
*/
synchronized(d) {
if(piao>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+(piao--)+"张门票");
}else {
System.out.println("同志,没有票了,记得早点来...");
break;
}
piao--;
}
}
}
}
class Demo{}
package com.luoliang.Thread_4;
public class SellTicketDemo {
public static void main(String[] args) {
//创建资源类对象
SellTicket st=new SellTicket();
//创建线程类对象
Thread st1=new Thread(st,"窗口1");
Thread st2=new Thread(st,"窗口2");
Thread st3=new Thread(st,"窗口3");
Thread st4=new Thread(st,"窗口4");
//启动线程
st1.start();
st2.start();
st3.start();
st4.start();
}
}
package com.luoliang.Thread_3;
public class SellTicket extends Thread{
//成员位置定义门票100张:共享
private static int piao = 100 ;
@Override
public void run() {
while(true) {
if(piao>0) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(getName()+"正在出售第"+(piao--)+"张门票");
}
}
}
}
package com.luoliang.Thread_3;
public class SellTicketDemo {
public static void main(String[] args) {
//创建线程类对象
SellTicket st1 = new SellTicket() ;
SellTicket st2 = new SellTicket() ;
SellTicket st3 = new SellTicket() ;
//设置线程名称
st1.setName("窗口1");
st2.setName("窗口2");
st3.setName("窗口3");
//启动线程
st1.start();
st2.start();
st3.start();
}
}
1.多线程中相关的一些方法
线程的优先级:priority
setPriority(int a)
最大优先级:10
最小优先级:1
默认优先级:5
sleep(long time) throws InterruptedException:参数为时间毫秒值,
休眠指定的时间;睡眠的过程中,线程暂停执行的状态
stop():过时了,强迫线程停止执行
interrupt():中断线程的一种状态
join():等待该线程终止!
底层依赖于 wait(long time),参数为0,等待状态:WATTING
参数为整数,到底一定时间,等待结束!
wait(long time):Object类中方法 (本地方法实现)
yield():暂定当前正在执行的线程,执行其他线程 "谦让"
2.电影院卖票—引入多线程的安全问题
能够体现数据共享---实现方式2
加入延迟操作:睡眠一定时间
同票
负票
解决方案:引入同步代码块
synchronized(锁对象){} ----能够解决安全问题---可能造成死锁!
锁对象:理解为门的"开和关"
锁对象必须是多个线程使用同一个锁对象!
1.同步方法的引入
2.死锁一种现象----如何解决
3.死锁引入----等待唤醒机制(生产消费者模式)
4.jdk5以后提供一种锁:可重入锁:Lock (java.util.concurrent:JUC(包))
具体的功能:
获取锁/释放锁
5.线程组(了解) ThreadGroup
6.线程池(ExecutorService—Executors的静态功能)
创建线程池
提交异步任务--->Callable接口 重写的call()方法
7.线程中匿名内部类的方式
1.多线程实现方式1和方式2的步骤
多线程实现方式1)
1)自定义一个类,继承自 extends Thread
2)重写Thread类中的run方法-----实质是本质调用Runnable接口的run
3)创建当前线程类对象
启动线程
多线程的实现方式2)
1)自定义一个类,实现Runnable接口 :implements Runnable
2)重写Runnable接口的run方法
3)创建当前资源类对象
然后创建Thread类对象,将资源类对象作为参数进行传递(资源类被共享)
2.什么是静态代理
代理角色:帮助真实角色完成一些事情,对真实角色的功能进行增强!
真实角色:专注于自己的事情
特点:真实角色和代理角色都需要实现接口 举例:MyRunnable(自定义的类)/Thread类 实现 Runnable接口
3.join()和yield()方法的区别
join():等待该线程终止!
底层依赖于 wait(long time),参数为0,等待状态:WATTING
参数为整数,到底一定时间,等待结束!
wait(long time):Object类中方法 (本地方法实现)
yield():暂定当前正在执行的线程,执行其他线程 "谦让"
4.Java能够开启线程吗?
不能直接开启
线程对象.start()
start0():本地方法 public native void start0().
5.线程的状态有几种 6种
Thread$State(枚举)
NEW , 新建
RUNNABLE, 执行
BLOCKED , 阻塞
WATTING ,:等待状态:一直等待
TIMED_WAITED,:超时等待 :wait(long time):正数 时间到了,等待结束! sleep(long time) join()
TERMINATED ; :线程终止(死亡)
6.校验多线安全问题的标准是什么,如何解决这种问题?
1)当前是否是多线程环境
2)是否有共享数据
3)是否存在多条语句对共享数据进行操作
解决方案:同步机制
关键字:
同步代码块---解决线程安全问题
锁对象:可以是任意Java类对象 Object obj = new Object();
synchronized(锁对象){
将多条语句对共享数据的操作包裹起来;
}
同步方法:非静态的 锁对象:this
方法声明上加入一个synchronized
package com.luoliang.homework4;
//插入排序
public class ArrayDemo {
public static void main(String[] args) {
//创建一个数组,静态初始化
int[] arr= {6,5,8,4,7};
//排序前
System.out.println("排序前");
printArray(arr);
insertSort(arr);
System.out.println("排序后");
printArray(arr);
}
private static void insertSort(int[] arr) {
// TODO Auto-generated method stub
for(int x=1;x<arr.length;x++) {
for(int y=x;y>0;y--) {
if(arr[y]<arr[y-1]) {
int temp=arr[y];
arr[y]=arr[y-1];
arr[y-1]=temp;
}else {
// 如果当前arr[y]> arr[y-1] 比较结束
break;
}
}
}
}
private static void printArray(int[] arr) {
// TODO Auto-generated method stub
System.out.print("[");
for(int x=0;x<arr.length;x++) {
if(x==arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+",");
}
}
}
}