1.为什么重写equals方法必须重写hashCode方法
是因为判断两个对象是否相等的时候,先判断hash值是否相等,然后再比较内容
hash一样的对象不一定相等,但是对象相等,要求hash值必须一样的
2.使用字符流复制一个文本文档到另外一个盘符下面
BufferedReader br = new BufferedReader(new FileReader(new File("路径")));
BuffererWriter bw = new BufferedWriter(new FileWriter(new File("被复制到哪的路径"));
int length = -1;
char[] cbuf = new char[4 * 1024];
while ((length = br.read(cbuf))) {
bw.write(cbuf, 0, length);
}
bw.close();
br.close();
3.接口和抽象类的区别
接口的定义:
interface 接口 {
抽象的方法
}
抽象类:
abstract 抽象类 {
非抽象方法
抽象方法
}
用一个普通类去继承(extends)抽象类
用一个普通类去实现(inplements)接口
4.重写和重载的区别
重写:
有继承关系,在子类中去重写父类的方法
方法完全一样的,方法的额名字 返回值 参数
重载:
只能在一个类中,方法名字一样,参数列表一定不同
5.final关键字的使用
final修饰成员变量
修饰局部变量
修饰方法
修饰类
面试:为啥使用final修饰成员变量?这个final修饰的量不能再赋值,值不能再改变了
效率就会高点!!!
6.static关键字的使用
static修饰成员变量
修饰成员方法
修饰代码块
类名.成员变量
类名.方法
7.复制一个视频文件到另外一个盘符下面 使用字节流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File ("文件路径")));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("被复制的路径")));
byte[] buf = new byte[4 * 1024];
int length = -1;
while ((length = bis.read(buf))) {
bos.write(buf, 0, length);
}
bos.close()
bis.close();
关于流,你只要听懂昨天讲的流,那么其他流都在不再话下,思路都是一样的!!!
教你们方法 方式,而不是单纯的教技术!!! 这些东西都是可以举一反三的!!!
1.IO流
干嘛的?对磁盘上面的文件的内容进行 读和写的
2.
输入流:
对磁盘上面的文件进行读取的 磁盘-》内存的
FileInputStream 字节输入流 想加缓冲效果 BufferedInputStream
这个类一个方法 read()
FileReader 字符输入流 想加缓冲效果 BufferedReader
这个类一个方法 read()
输出流:
从内存中写入到磁盘 内存-》磁盘
FileOutputStream 字节输出流 想加缓冲效果 BufferedOutputStream
这个类一个方法 write()
FileWriter 字符输出流 想加缓冲效果 BufferedWriter
这个类一个方法 write()
之后再讲一个对象流 序列化!!!
我不用讲,你看着官方手册就会写了
常用类
看API官方手册
线程安全的,可变的字符序列
关于StringBuffer的代码相当简单是个人都会的,但是底层和面试问的东西比较深的所以你们下去一定看看一些东西
String 不可变
package com.qfedu.a_stringbuffer;
public class Demo1 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
//构造一个没有字符的字符串缓冲区(容器),初始容量为16个字符。
//在整个缓冲去放数据,放啥数据?字符串!!!
System.out.println(sb);
sb.append("xi");//追加
sb.append("he");
sb.append("ha");
//插入 这个2 就是下标索引
sb.insert(2, "gou");
System.out.println(sb);//xigouxihehehaha
//字符串反转
System.out.println(sb.reverse());//ahahehehixuogix
//删除一个字符串delet(int start, int end)
//不要怀疑 始终记得 要头不要尾 start包含 end 不包含
System.out.println(sb.delete(1,3));
//问题:
//咱们有String了为啥还要学习StringBuffer和StringBuilder
//拼接字符串的效率不一样的
//字符串String 拼接的是时候,效率底 + concat()
//StringBuffer 和StringBuilder拼接字符串效率高
//为啥StringBuffer和StringBuilder高,为啥String效率低
//如果使用String拼接100个字符串,会出来100个对象 因为String 不可变的
String str = "123";
str += "457";
str += "457";
str += "457";
str += "457";
//以上有几个对象? 6个
}
}
Stringbuffer与StringBuilder区别
package com.qfedu.a_stringbuffer;
public class Test {
public static void main(String[] args) {
//String 连接10000次消耗1127ms
//StringBuffer 连接10000次消耗5ms
//StringBuilder 连接10000次消耗3ms
StringTest(10000);
StringBufferTest(10000);
StringBuilderTest(10000);
}
public static void StringTest(int n){
String str = "";
//获取当前系统的时间 还没有执行下面for循环的时候的时间
Long startTime = System.currentTimeMillis();
//使用for循环来拼接!!!
for(int i=0;i<n;i++){
str += i;
}
//获取当前系统的时间 执行下面for循环的时候的时间
Long endTime = System.currentTimeMillis();
System.out.println("String 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
public static void StringBufferTest(int n){
StringBuffer str = new StringBuffer();
Long startTime = System.currentTimeMillis();
for(int i=0;i<n;i++){
str.append(i);
}
Long endTime = System.currentTimeMillis();
System.out.println("StringBuffer 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
public static void StringBuilderTest(int n){
StringBuilder str = new StringBuilder();
Long startTime = System.currentTimeMillis();
for(int i=0;i<n;i++){
str.append(i);
}
Long endTime = System.currentTimeMillis();
System.out.println("StringBuilder 连接"+ n +"次消耗"+(endTime-startTime)+"ms");
}
}
我们可以清楚的看到String的字符串的连接效率是最低的,这一点对于大量字符串的拼接可以很明显的表示出来,所以说大量字符串的拼接最好不要选择String。[StringBuffer]和StringBuilder对于字符串的拼接效率是大致相同的
为啥StringBUilder效率高?
因为StringBuilder是线程不安全的,StringBuffer线程安全
四、总结
1.String为固定长度的字符串,StringBuilder和StringBuffer为变长字符串;
2.stringBuffer是线程安全的,StringBuilder是非线程安全的;
3.StringBuffer和StringBuilder的默认初始容量是16,可以提前预估好字符串的长度,进一步减少扩容带来的额外开销
Java 中的枚举是一个特殊的类,一般是表示一组常量 final static int a = 30;
比如一年有四季 一天24小时 pi e
枚举就是用来表示常量的,只不过是常量的换一种写法而已!!!
Java中定义枚举类的时候的语法格式:
public enum 枚举类名 { //下面写常量,常量之间使用逗号隔开 }
package com.qfedu.b_enum;
public enum Color {
//常量,一般都是大写的 没有任何数据类型的!!!
RED, GREEN, BLUE
}
枚举类的实例用法
package com.qfedu.b_enum;
//声明一个枚举类 是一个特殊的类
enum Color2 {
RED, GREEN, BLUE
}
public class Demo2 {
public static void main(String[] args) {
//RED这个数据 属于Color2这个类的实例的
//Color2.RED 为啥可以用类名.常量 常量是static修饰的!!!
Color2 red = Color2.RED;
System.out.println(red);//RED
Color2 green = Color2.GREEN;
System.out.println(green);
}
}
swicth (表达式) {}
表达式数据类型有哪些:
byte short int char String 枚举
枚举在swicth-case中如何使用【这个重要】
package com.qfedu.b_enum;
enum Color3 {
RED, GREEN, BLUE
}
//可以通过switch-case将咱们的常量变成咱们所数据类型
//RED===》红色
//只是一个用判断的一个东西
public class Demo3 {
public static void main(String[] args) {
Color3 red = Color3.RED;
switch (red) {
case RED:
System.out.println("红色");
break;
case GREEN:
System.out.println("绿色");
break;
case BLUE:
System.out.println("蓝色");
break;
}
}
}
枚举类中的几个方法
values();枚举类中所有的值
ordinal();可以找到每个枚举类中常量的索引
valueOf();返回值的是指定字符串的枚举常量
package com.qfedu.b_enum;
enum Color4 {
RED, GREEN, BLUE
}
public class Demo4 {
public static void main(String[] args) {
//values();枚举类中所有的值
//ordinal();可以找到每个枚举类中常量的索引
//valueOf();返回值的是指定字符串的枚举常量
Color4[] values = Color4.values();//返回是数组
//遍历
for (Color4 value : values) {
System.out.println(value + "对应的索引:" + value.ordinal());
}
//valueOf返回的是字符串的枚举常量对象
//只是换了一种写法而已。
//通过常量所对应的字符串获取常量的对象
Color4 red = Color4.valueOf("RED");
//一般开发使用Color4.RED;
Color4 red1 = Color4.RED;
System.out.println(red);
System.out.println(red.hashCode());
System.out.println(red1);
System.out.println(red1.hashCode());
}
}
枚举在真实的开发中使用:
在很多时候我们定义一些状态量都是使用0或者1,-1这样在数据库中定义,这样的数据存放在数据库的相应字段中方便数据读取,但是只存储数字,如果定义的表很多,对应的字段也很多,设计的状态就非常多,编码很容易分辨不清楚,一方面去数据库中查看相应字段的注释非常费时间,而且容易产生差错,如果我们使用枚举类,这个问题就很好的解决了。
比如当我们定义了许多状态量,比如订餐支付,未支付,订单的完结,派送,制作等有许多状态,如果不使用枚举,我们在代码层进行判断的时候总是要去思考这个状态是定义的什么呢,0还是-1呢,当项目比较大的时候,光靠我们记是不行的,干脆我们就使用枚举来简化我们的编程,而且还较少了逻辑上出错的可能。
package com.qfedu.b_enum;
enum ProductEnum {
UP(0, "在架"),
DOWN(1, "下架");
private Integer code;
private String message;
ProductEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
public class Demo5 {
public static void main(String[] args) {
System.out.println(ProductEnum.UP.getCode());
System.out.println(ProductEnum.UP.getMessage());
System.out.println(ProductEnum.DOWN.getCode());//1
System.out.println(ProductEnum.DOWN.getMessage());//"下架"
}
}
Java有八大基本数据类型,都有与之对应的包装类
为啥会有八大基本数据类型的包装类?
包装类能被实例化,封装了很多方法,可以使用,这样操作八大基本数据类型就比较方便了
所以开发中的实体类都是写的包装类
int age====>Integer age;
int->Integer
byte->Byte
short->Short
long->Long
float->Float
double->Double
boolean->Boolean
char->Character
【重点】:
1.自从JDK1.5之后,有拆箱和装箱
自动装箱:将基本数据类型转为包装类
自动拆箱:将包装类转为基本数据类型
2.***Value();将包装类转为基本数据类型
3.toString();将基本数据类型转为字符串
4.parse***();将字符串类型的数据转为基本数据类型【以后开发用】
5.valueOf();将基本数据类型转为包装类类似手动装箱
package com.qfedu.c_baozhuang;
public class Demo1 {
public static void main(String[] args) {
//自1.5以后 有自动装箱和自动拆箱
//自动装箱: 将int转为Integer
//自动拆箱: 将Integer转为int
//毫无违和感 都是自动的!!!特别方便
System.out.println(Integer.MAX_VALUE);//2147483647
System.out.println(Integer.MIN_VALUE);//-2147483648
//自动装箱 45本身是int类型的数据,现在是Integer
//int 变成了Integer 报错没?没有就证明可以自动的装箱
Integer i1 = 45;
//自动拆箱 没有报错 就证明自动的在拆箱
int i2 = i1;
System.out.println(i1);
System.out.println(i2);
//除了自动装箱和拆箱外,Java还给咱们提供了方法。让咱们装箱和拆箱
Boolean b1 = true;//b1 是包装类
//***Value();将包装类转为基本数据类型
//intValue() booleanValue() floatValue() doubleValue()
//b是基本数据类型
//有自动拆箱,还有必要使用***Value吗?没有!!!
boolean b = b1.booleanValue();
System.out.println(b);
//toString();将基本数据类型转为字符串【重要】
int i3 = 45;
String s = Integer.toString(i3);
System.out.println(s);//"45"
String s1 = Double.toString(67.8);
System.out.println(s1);//"67.8"
//以后做银行项目的时候,double 和float 有可能数据丢失
//可以转为字符串操作!!!绝对不会
//parse***();将字符串类型的数据转为基本数据类型【以后开发用】
//parsetInt(); parseDouble(); parseFloat();parseByte()
int i = Integer.parseInt("250");
System.out.println(i);//250
//开发中 分页 前段URL传一个字符串值过来 pageNo=2 这个2传
//到Java代码中,是字符串类型的数据,将字符串转为int类型的数据
//然后操作数据库
//valueOf();将基本数据类型转为包装类类似手动装箱
byte b2 = 34;//b2 基本数据类型
Byte aByte = Byte.valueOf(b2);
System.out.println(aByte);//aByte 就是包装类
//有没有必要写这个方法?没有 因为会自动装箱
}
}
面试题:
Integer i1 = 10;
Integer i2 = 10;
sout(i1 == i2);
Integer i3 = 1000;
Integer i4 = 1000;
sout(i3 == i4);
package com.qfedu.a_baozhuang;
public class Demo2 {
public static void main(String[] args) {
Integer i1 = 10; // i1 储存在常量池中
Integer i2 = new Integer(10);
// i1 和i2 内存地址不一样
System.out.println(i1 == i2); // false
int b = 10; // b储存在栈区中 栈区的引用会直接指向常量池中i1这个地址
System.out.println(i1 == b); // true
System.out.println(i2 == b); // true
}
}
Math
类包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。专门处理数学运算的一个类
绝对值 abs()
最大值 max()
最小值 min()
向上取整 ceil()
向下取整floor()
四舍五入round()
随机数random()
package com.qfedu.d_math;
public class Demo1 {
public static void main(String[] args) {
System.out.println(Math.PI);
System.out.println(Math.E);
//以上是两个常量
System.out.println(Math.abs(-89));//绝对值 89
System.out.println(Math.max(34, 56));//最大值 56
//求三个数的最大值?咋办?
System.out.println(Math.max(23, Math.max(45,12)));//45
//最小值
System.out.println(Math.min(34, 12));//12
//向上取整
System.out.println(Math.ceil(45.2));//46.0
//向下取整
System.out.println(Math.floor(89.8));//89.0
//四舍五入
System.out.println(Math.round(45.5));//46
//随机数大于等于 0.0 ,小于 1.0 double
System.out.println(Math.random());
//随机1-100之间的整数int 0.45 * 100=45 int
int i1 = (int)(Math.random() * 100);
System.out.println(i1);
}
}
专门处理随机数的类
package com.qfedu.e_random;
import java.util.Random;
public class Demo1 {
public static void main(String[] args) {
Random random = new Random();
System.out.println(random.nextInt());
System.out.println(random.nextInt(100));//[0,100);
System.out.println(random.nextFloat());
System.out.println(random.nextDouble());
System.out.println(random.nextBoolean());
}
}
作业:
1.题目要求:
根据int变量n的值,来获取随机数字,范围是[1 , n],可以取到1也可以取到n。
2.题目:
用代码模拟猜数字的小游戏。
思路:
1.首先需要产生一个随机数字,并且一旦产生不再变化。用Random的nextInt方法
2.需要键盘输八,所以用到了Scanner
3.获取键盘输入的数字,用scanner当中的nextInt方法
4.已经得到了两个数字,判断(if)一下:
如果太大了,提示太大,并且重试;
如果太小了,提示太小,并且重试;
如果猜中了,游戏结束。
5.重试就是再来一次,循环次数不确定,用while(true)。
package com.qfedu.f_system;
import java.io.PrintStream;
import java.util.Properties;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
PrintStream out = System.out;//是一个流 PrintStream 打印流
out.println("goudan");
System.out.println("goudan");//标准输出流打印的东西
System.err.println("xixi");//错误输出流打印的东西
new Scanner(System.in);//输入流
//你把控制台想象成一个磁盘。就是输入流和输出流
//用的很多
// 在1970年1月1日UTC之间的当前时间和午夜之间的差异,以毫秒为单位
long l = System.currentTimeMillis();
//2022年到1970年 是不是52
System.out.println(l/1000/60/60/24/365);
//获取系统的东西 System 英文单词就是系统的意思
Properties properties = System.getProperties();
//os.name 系统的名字
System.out.println(properties.get("os.name"));
System.out.println(properties.get("os.version"));
System.out.println(properties.get("user.name"));
System.out.println(properties.get("user.dir"));
System.out.println(properties.get("java.version"));
//Windows 10
//10.0
//bowang
//C:\Users\bowang\IdeaProjects\day21_wb
//1.8.0_241
}
}
package com.qfedu.g_runtime;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
//1.获取runtime对象
Runtime runtime = Runtime.getRuntime();
//runtime对象可以启动咱们电脑上面任意的一个软件
//使用代码启动软件
runtime.exec("C:\\Program Files (x86)\\Notepad++\\notepad++.exe");
//返回Java虚拟机将尝试使用的最大内存量。字节数
System.out.println(runtime.maxMemory() / 1024 / 1024);//MB
//返回Java虚拟机中的可用内存量 字节数
System.out.println(runtime.freeMemory()/1024/1024);
//返回Java虚拟机中的内存总量 字节数
System.out.println(runtime.totalMemory()/1024/1024);
}
}
专门处理日期的一个类,不过好多方法已经过期了
在类的所有方法
Date
接受或返回年,月,日,小时,分钟和秒值,以下表述中使用:
- y年代表整数y
- 1900
。- 一个月由0到11的整数表示; 0是1月,1是2月,等等; 11月12日。
- 日期(月的一天)以通常的方式从1到31的整数表示。
- 一小时由0到23之间的整数表示。因此,从午夜到凌晨1点的时间是小时0,从中午到下午1点的小时是12小时。
- 一般以0〜59的整数表示。
- 第二个由0到61的整数表示; 值60和61仅发生在闰秒上,甚至仅在实际上正确跟踪闰秒的Java实现中发生。 由于目前引入闰秒的方式,在同一分钟内不会发生两个闰秒,但是本规范遵循ISO C的日期和时间约定。
package com.qfedu.h_date;
import java.util.Date;
public class Demo1 {
public static void main(String[] args) {
Date date = new Date();
//Tue Aug 09 16:11:11 IRKT 2022
System.out.println(date);
//获取年份 这个年份是减去1900以后的值,所以得加上1900
System.out.println(date.getYear() + 1900);
//7
//2
//16
//15
//42
//获取月份
System.out.println(date.getMonth() + 1);//7
//这个日期的星期几。
System.out.println(date.getDay());//2
System.out.println(date.getHours());//16
System.out.println(date.getMinutes());//15
System.out.println(date.getSeconds());//42
}
}
现在国际通用的是Calendar类
package com.qfedu.h_date;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Demo2 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
//获取当前的年份
int i = calendar.get(Calendar.YEAR);
System.out.println(i);//2022
//获取月份 需要加1的
System.out.println(calendar.get(Calendar.MONTH) + 1);//8
//获取当月的第几天
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//9
//获取这周的第几天 漂亮国的周日是第1天
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//3
//获取这一年的第几天
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//221
//获取时
System.out.println(calendar.get(Calendar.HOUR));//4
System.out.println(calendar.get(Calendar.MINUTE));//39
System.out.println(calendar.get(Calendar.SECOND));//3
//重要的方法 获取当前的时间的 返回值是Date类型的数据
//可以转为Date类型的数据
Date time = calendar.getTime();
System.out.println(time);
//Tue Aug 09 16:40:21 IRKT 2022
//这上面时间 对程序员相当不友好!!!
//通过一个类将日期格式转换一下
SimpleDateFormat sdf = new SimpleDateFormat("yyyy—MM-dd HH:mm:ss");
//yyyy-MM-dd HH:mm:ss
//年-月-天 时:分:秒
//2022-08-09 16:43:32
//将这个格式Tue Aug 09 16:40:21 IRKT 2022
//转换为2022-08-09 16:43:32
String format = sdf.format(time);
System.out.println(format);
//yyyy-MM-dd HH:mm:ss
//以上能不能胡乱写?不能
//以后开发中要用的!!
}
}
输入两个日期计算出两个日期相差多少天
package com.qfedu.h_date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Demo3 {
public static void main(String[] args) throws ParseException {
//输入两个日期计算出两个日期相差多少天
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//将一个字符串类型的数据变成一个Date类型的数据
Date strat = sdf.parse("2012-08-01");
Date end = sdf.parse("2022-08-09");
//一定要将字符串转为Date类型 才能按照日期来算
//将Date类型的数据转为时间戳了,
//为啥转为时间戳?因为时间戳是一个long类型数据可以想减!!!
//算两个时间的间隔,相减。转为int或者long才能转
long startTime = strat.getTime();
long endTime = end.getTime();//毫秒数
long num = endTime - startTime;
System.out.println(num/1000/60/60/24);
}
}
作业:
1.输入两个日期计算出两个日期相差多少天 2.一个你的生日,计算出来你几岁了 3.新闻类:标题 内容 时间 有10条新闻 ,按照时间降序进行排列 打印!!! 4.学生类:学号 姓名 出生日期 把学生类放到集合中, 找出来比张三年龄大的学生 5.题目要求: 根据int变量n的值,来获取随机数字,范围是[1 , n],可以取到1也可以取到n。 6.题目: 用代码模拟猜数字的小游戏。 思路: 1.首先需要产生一个随机数字,并且一旦产生不再变化。用Random的nextInt方法 2.需要键盘输八,所以用到了Scanner 3.获取键盘输入的数字,用scanner当中的nextInt方法 4.已经得到了两个数字,判断(if)一下: 如果太大了,提示太大,并且重试; 如果太小了,提示太小,并且重试; 如果猜中了,游戏结束。 5.重试就是再来一次,循环次数不确定,用while(true)。 7.自己去百度一下Calendar这个类详解。 因为以后开发中日期在项目中是必用的!!!啥时候下的单子,超过15分钟没有支付。都要考虑的!!!日期很重要的!!!