目录
-
- I/O
-
-
- File、InputStream、URL、Resource的区别???
- io流writer写时,若不关闭流,会出现什么;reader需要关闭吗
- flush方法应该怎么用
- FileWriter的write方法源码
- nio对普通IO的优化???
- BufferedWriter源码
- read()方法读出的是什么,read(char[] chars)呢
- 以追加的方式写入,而不是覆盖;换行怎么写
- BufferedReader
- 字节流FileOutputStream、FileInputStream 、BufferedInputStream、BufferedOutputStream
- InputStream转字节数组
- BufferedOutputStream源码
- 字符流编码与字节流
- 打印流,只有writer,没有reader
- Properties
- 序列化流
- 标签接口
- File
-
- 反射
-
- 每个类编译之后都会有一个class文件,什么时候加载到JVM中的,static{//代码块}这里面的代码块什么时候被执行
- 获得Class的几种途径,基本数据类型例如int有class属性吗
- 通过反射创建类对象
- instanceof 与 isInstance与isAssignableFrom区别
- getFields()与getDeclaredFields()区别
- 获取指定公有字段和私有字段,并使用
- 获取类的方法,并使用,普通方法和静态方法
- 获得类上的注解,Method,Field
- 可以获取继承来的属性和方法吗
- Class的getName、getSuperclass、getInterfaces、isInterface、getSimpleName三个方法的含义
- java-Type
- ResolvableType
- java动态代理
- 动态代理实现数据库事务
- 注解
- 元注解Target、Retention作用
- 怎么定义注解,怎么定义注解处理器
- 元素命名为value有什么讲究
- 注解元素可用的类型
- 注解与接口区别
- 注解+动态代理实现事务
- 阿里巴巴java开发规范
-
- 命名方面知道哪些
- POJO的Boolean类型变量命名为什么不要加is
- 包名规范要注意()
- 缩写要注意()
- 接口类中的方法和属性要加修饰符吗,例如public
- 接口与实现类命名()
- 获取单个对象的方法使用()做前缀,多个对象(),统计值(),插入(),删除(),修改()
- 领域模型包括()()()
- 什么是数据对象,什么是展示对象,命名规范是什么
- 为什么不能使用xxxPOJO命名
- 什么是魔法值
- Long类型的值要注意()
- 所有常量放在一个常量类中可以吗
- 常量复用有五层,类、包、()()()
- 易懂变量要定义在五层中的哪一层
- 大括号强制()
- 左小括号与字符间()
- 保留字与括号之间()
- 运算符的左右需要加()
- 注释的斜线与注释的内容()
- 单行字符超过120个,需换行,换行需注意运算符(),一二行(),
- 调用方法时,多个参数需要()
- 如何使单个方法总行数不超过80
- 访问类的静态变量或方法要避免()
- 可变参数编程提倡吗
- equals的左右注意
- 包装类型之间值的比较,使用equals还是==
- pojo属性使用基本类型还是包装类型
- 局部变量使用基本类型还是包装类型
- 返回值和参数使用基本类型还是包装类型
- pojo类属性默认值可以设置吗
- 构造方法内需要业务逻辑怎么办
- pojo类必须写()方法,方便测试
- 类内方法定义的顺序依次是
- 循环体内拼接字符串使用string还是stringbuilder
- 重写equals方法时,要注意
- 为什么我们经常使用string来作为map的key
- ArrayList为什么不可强转为subList
- 集合转数组toarray要注意什么
- foreach时候删除怎么办
- 实现comparable接口时,要注意()
- 遍历map应该使用哪种方式
- 讨论hashmap、treemap、ConcurrentHashMap 、hashtable的空值与线程安全
- 怎么理解集合的有序和稳定,哪些是有序,哪些是稳定
- 线程池与显示创建线程注意什么
- 线程池创建要注意
- 为什么不能使用executor创建线程池
- 怎么正确创建线程池
- TimeUnit类型:将一天转为24小时,一小时有多少秒,3天转为小时
- timeunit进行延时怎么做
- SimpleDateFormat 是线程不安全的类怎么解决安全问题
- Date、Calendar、SimpleDateFormate在jdk1.8可被哪些替代
- 对象锁与类锁哪些对性能更好
- 对多个资源,数据表,对象加锁时需要()
- 并发修改同一记录时,避免更新丢失,加锁方式:应用层加锁,(),()
- 什么时候用乐观锁,什么时候用悲观锁
- 定时任务timer使用()代替
- 使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown 方法,线程执行代码注意 ()
- 子线程抛出的异常能否在主线程trycatch到()
- 异常被捕获了,事务还会回滚吗
- 事务只能回滚()异常
- 一个类里面。a方法调用b方法,b方法调用c方法,只有c方法需要事务, 我应该把transaction注解加在哪个方法上面
- 有 try 块放到了事务代码中,catch 异常后,如何回滚事务
- spring事务传递
- 外围方法未开启事务的情况下Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰,举例理解
- 外围方法a有事务,调用b,c方法后外围方法a抛出runtimeexception,b、c都开启了自己的事务(Propagation.REQUIRED),问:b、c会回滚自己的事务吗
- 外围方法a,内部方法b,c都开启事务,b抛出runtimeexception,只会回滚b方法吗
- 外围方法a,内部方法b,c都开启事务REQUIRED,在a中trycatch调用b代码块的异常,还会回滚吗
- 将上述b、c方法上改为Propagation.REQUIRES_NEW,a方法也开启事务会怎么样
- c是REQUIRES_NEW,a是REQUIRED,c的异常会导致a回滚吗
- b以REQUIRES_NEW和以REQUIRED抛出异常,在a处捕获,会导致a的事务回滚吗
- runtimeException一般不用捕获,但是我捕获之后事务还会回滚吗
- Propagation.NESTED,修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务。举例论证
- NESTED与REQUIRES_NEW区别
- Random的问题,以及替代方案
- volatile 解决多线程内存不可见问题,对于()是可以解决变量同步问题,但是对于()同样无法解决线程安全问题,对于count++操作,推荐使用()
- ThreadLocal 对象建议使用 ()修饰
- 使用switch,必须()()
- 在 if/else/for/while/do 语句中必须使用()。即使只有一行代码,
- 在高并发场景中,避免使用()判断作为中断或退出的条件。
- 超过 3 层的 if-else 的逻辑判断代码可以使用()()()
- 不要在条件判断中执行()
- 哪些地方不需要做参数校验
- 注释必须()
- 注释所有的类都必须添加()()
- 使用正则表达式注意
- 获取当前毫秒数 建议使用()
- 循环里没有trycatch异常,抛出异常会终止程序吗
- 为什么不要在 finally 块中使用 return
- 日志不能直接使用(),而应依赖()
- 日志文件至少保存()天
- 日志文件的命名方式
- 为什么输出日志要加条件判断 if (logger.isDebugEnabled())
- 举例占位符打印日志
- 遇到过重复打印日志的情况吗,怎么解决
- 日志记录异常信息应该包括()和()
- 日志级别排序
- 生产环境禁止输出()日志
- 编码时隶属用户个人的页面或功能必须()
- 用户敏感数据展示必须()
- 什么是SQL注入
- 为什么mybatis的$不能防止SQL注入,而#可以防止大部分
- mybatis怎么防止SQL注入
- 用户输入的参数必须()
- 跨域问题
- CSRF攻击,以及解决方式
- 在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防()
- MySQL数据库建表,Boolean类型的字段命名(),数据类型()
- 数据库表名,字段名可以使用大写吗,表名要不要使用复数
- 主键索引命名,唯一索引命名,普通索引命名
- 小数类型必须使用()
- 如果存储的字符串长度几乎相等使用()类型
- 表必备三字段
- 哪种字段可以考虑冗余
- 什么时候可以考虑分库分表
- 业务上唯一特性的字段或多个字段组合强制()
- 建立索引必须制定(),没必要对全字段建立索引
- 如果有order by,索引怎么建
- count(*)与count(列名)区别
- 统计不重复的行数
- count(distinct col1, col2) 如果其中一列全为 NULL,另一列有不同的值会返回()
- 当某一列的值全是 NULL 时,count(col)的返回结果为 (),但 sum(col)的返回结果为 ()
- 使用 ()来判断是否为 NULL 值。
- 分页时遇到count为0时,应该()
- 不得使用外键或级联,怎么办
- 为什么禁止使用存储过程
- 数据的update和delete时,要先()
- pojo的Boolean不能加is,而数据库字段加is,所以要()
- 更新数据表记录时,必须同时更新记录对应的 ()
- 使用事务的地方需 要考虑各方面的回滚方案,包括()(搜索引擎回滚)()()
- 开放接口层、终端显示层、web层、service层、manager层、dao层、外部接口或第三方平台
- dao层不需要打印日志,因为()
- 注意超过 2 个参数的查询封装使用()对象,禁止使用()来传输
- groupid、artifactid、version格式
- 高并发服务器建议调小 TCP 协议的 time_wait 超时时间,为什么
- 在线上生产环境,JVM 的 Xms 和 Xmx 设置
- 主流的 linux 服务器默认所支持最大 fd 数量为 1024,fd是什么,什么时候可以调大
- 这些图是什么,怎么用:用例图、状态图、时序图、类图、活动图
- 用例图与参与者的关联关系、包含、扩展、泛化
- 状态图若存在不同维度,例如一个订单有支付维度、快递状态、订单开闭状态,怎么画
- 时序图用来描述用例中的()
- 当执行一个用例时, 时序图中的每条消息对应了()
- 时序图中()是时间轴,横轴代表(),生命线指(),消息指(),激活和钝化指()
- 泛型
-
-
- Class的泛型
- 泛型类和泛型方法的区别,泛型类和泛型接口的区别
- 杠杆利用类型参数推断
- 例子
- <? extends Parent> 的由来
- 泛型擦除的问题
- 边界 T extends Test & Hello
- 例3,内部类
- 局部内部类与匿名内部类
- 匿名内部类与工厂模式
- 嵌套类与普通内部类区别,什么时候使用嵌套类
- 接口内部的类
- 内部类与闭包,内部类、继承、包含三者比较
- 例子
- 函数式编程接口可以有()个方法
- 范例
- 函数式接口Runnable
- 转换为函数式编程
- 转换为函数式编程-内部类
- 简化函数式编程
- 上一个例子是静态方法引用,普通方法引用实现呢
- 函数式接口功能型、消费型、供给型作用,以及使用
- consumer的addthen方法使用
- 举例 ?extends T 的用法。。? super T
- 容器
-
- 容器是指()和()
- 数组与集合比较(数组大小固定)、(集合里面不能存基本数据类型)、()、()
- collection接口下有哪些接口,接口有些什么特征
- list.contains(object)、indexof(object)、remove(object)都会用到object的()方法
- equals与==区别
- 怎么clone出一个跟原对象互不影响的对象
- originList 与 subList 在 collections.shuffle或sort后的变化
- 举例说明一个迭代器的好处
- 遍历map的两种方式
- ArrayList 与 linkedList比价
- hashset、treeset、linkedhashset比较
- 异常
- 设计模式
-
- 回忆策略模式、观察者模式、装饰者模式、工厂模式、单例模式、命令模式、适配器模式、外观模式、模板方法模式、迭代器模式、组合模式、状态模式、代理模式
- 懒汉单例模式怎么不安全了,怎么解决
- 命令模式使用场景与实现
- 类适配器和对象适配器区别
- 适配器只能包装一个类吗?外观模式可以包装一个类吗
- 最少知识原则
- 如何理解comparable接口作为排序的模板方法
- 底层是数组、底层是队列、底层是链表,使用迭代器模式遍历
- 组合模式菜单与菜单项的不同
- 状态模式
- 什么是远程代理
- 什么是RMI
- 阿里编码规范中约束的分层:终端显示层、开放接口层、请求处理层(web层)、业务逻辑层(service)、通用处理层(manager)、数据持久层(dao)、
- Java8新特性
-
I/O
File、InputStream、URL、Resource的区别???
io流writer写时,若不关闭流,会出现什么;reader需要关闭吗
数据写不进去,其实手动writer.flush(),也可以将数据刷新进去
reader也需要关闭
flush方法应该怎么用
当有大量数据需要写入时,要分批进行writer.flush一下,否则缓存压力过大
FileWriter的write方法源码
FileWriter extends OutputStreamWriter
OutputStreamWriter extends Writer{
final StreamEncoder se;
public void write(char cbuf[], int off, int len) throws IOException {
se.write(cbuf, off, len);
}
public void flush() throws IOException {
se.flush();
}
}
class nio.StreamEncoder extends Writer {
}
nio对普通IO的优化???
BufferedWriter源码
class BufferedWriter extends Writer {
Writer out;
char cb[];
public void write(String s, int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
int b = off, t = off + len;
while (b < t) {
// 不停往cb里面填数据
s.getChars(b, b + d, cb, nextChar);
// 当数据超出一个临界值时,会自动先out.write(cb, 0, nextChar);
if (nextChar >= nChars)
flushBuffer();
}
}
}
public void flush() throws IOException {
synchronized (lock) {
flushBuffer();
out.flush();
}
}
void flushBuffer() throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar == 0)
return;
out.write(cb, 0, nextChar);
nextChar = 0;
}
}
}
read()方法读出的是什么,read(char[] chars)呢
reader = new FileReader(file);
//一个数字,ASCII码,可以强制转换回char
int i = reader.read();
// 连续读三次,可以读到三个字符,若第三个没值,则返回-1,可作为读取结束条件
reader.read()
reader.read()
reader.read()
read(char[] chars)是将数据读入到参数的数组中,返回的是读取到数据的长度
reader = new FileReader(file);
char[] cs = new char[5];
int i = reader.read(cs);
// 若最后只读取到i=2个数据,只会覆盖原数组的前两个数据,后面三个不变
// 当i = -1时候,说明没有读到数据了
i = reader.read(cs);
以追加的方式写入,而不是覆盖;换行怎么写
new FileWriter(“file.txt”,true)
\n代表换行,或\r\n
BufferedReader
reader = new BufferedReader(new FileReader(file));
String line = reader.readLine();
// BufferedReader关闭,里面的FileReader也会关闭
reader.close();
if(line != null){
//这个就是读取的边界
}
writer = new BufferedWriter(new FileWriter(file));
//写入一行
writer.write("abc");
// 要想换换必须加这个方法
writer.newLine();
writer.write("xyz");
writer.flush();
字节流FileOutputStream、FileInputStream 、BufferedInputStream、BufferedOutputStream
byte[] bytes = {
123,34,45,34};
outputStream = new FileOutputStream(file);
outputStream.write(bytes);
// 字节流无需flush
outputStream.close()
byte[] bs = new byte[5];
FileInputStream inputStream = new FileInputStream(file);
// 读到多少个字节 i,当i为-1时,表示没有读到数据
int i = inputStream.read(bs);
// 指定解码格式,对字节进行解码
String(@NotNull byte[] bytes,
int offset,
int length,
@NotNull java.nio.Charset charset)
in = new BufferedInputStream(new FileInputStream(file));
out = new BufferedOutputStream(new FileOutputStream(file));
byte[] bs = new byte[1024];
// 当len为-1时候表示没读到数据
int len = in.read(bs)
out.write(bs,0,len)
InputStream转字节数组
byte[] readStream(final InputStream inputStream) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
int bytesRead;
while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, bytesRead);
}
outputStream.flush();
return outputStream.toByteArray();
}
class ByteArrayOutputStream extends OutputStream {
// 数据没有存在文件里,而是这个数组中
byte buf[];
public ByteArrayOutputStream() {
this(32);
}
void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) - b.length > 0)) {
throw new IndexOutOfBoundsException();
}
ensureCapacity(count + len);
// 复制数组
System.arraycopy(b, off, buf, count, len);
count += len;
}
}
BufferedOutputStream源码
class BufferedOutputStream extends FilterOutputStream {
byte buf[];
public synchronized void write(byte b[], int off, int len) throws IOException {
if (len >= buf.length) {
flushBuffer();
out.write(b, off, len);
return;
}
// 将数据先放到buf缓存中
System.arraycopy(b, off, buf, count, len);
count += len;
}
private void flushBuffer() throws IOException {
if (count > 0) {
out.write(buf, 0, count);
count = 0;
}
}
}
class FilterOutputStream extends OutputStream {
OutputStream out;
public void write(int b) throws IOException {
out.write(b);
}
}
字符流编码与字节流
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), "gbk");
// 这个“中”字是以gbk形式存储,将来读取的时候也要以gbk取数据
writer.write("中");
char[] cs = new char[1024];
// 解码必须以jdb
InputStreamReader reader = new InputStreamReader(new FileInputStream(file), "GBK");
int len = reader.read(cs);
new String(cs,0,len);
打印流,只有writer,没有reader
// 将数据输出到文件file
PrintWriter writer = new PrintWriter(file);
writer.println("hello");
writer.print("world");
writer.flush();
// 将读到的数据打印到控制台
PrintWriter writer = new PrintWriter(System.out);
writer.flush();
Properties
// 线程安全,只能存字符串
Properties extends Hashtable<Object,Object> {
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
}
Properties properties = new Properties();
properties.setProperty("001","张三");
properties.setProperty("002","李四");
String value = properties.getProperty("001");
// 将properties数据写到文件中
PrintWriter writer = new PrintWriter(file);
properties.list(writer);
writer.flush();
// 从文件中加载到properties里
Properties properties = new Properties();
FileInputStream inputStream = new FileInputStream(file);
properties.load(inputStream);
序列化流
// Person要实现序列化接口,加一个序列化id,不加序列化id,当类变化例如增加字段时,反序列化会报错
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
outputStream.writeObject(new Person());
outputStream.flush();
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
Object o = inputStream.readObject();
// 一般使用集合,集合实现了序列化接口
list.add(person1)
list.add(person2)
outputStream.writeObject(list);
标签接口
- 标签接口没有任何方法和属性
- 主要有两个用途,第一:标识同一类型的类,如org.aopalliance.aop.Advice;第二:使程序或JVM采取一些特殊处理,如io.Serializable
File
- File:
file.exists()
file.createNewFile()
file.mkdir()
//创建多级目录
file.mkdirs()
//删除不走回收站,删除文件和目录最后一层
file.delete()
//获取文件绝对路径
file.getAbsolutePath()
//new File("b.txt"),相对路径是相对项目名作为根路径
//获取相对路径
file.getPath()
file.getName()
//文件大小,多少字节
file.length()
File[] files = file.listFiles();
boolean canExecute = file.canExecute();
boolean canRead = file.canRead();
boolean canWrite = file.canWrite();
boolean hidden = file.isHidden();
//体现层级关系递归打印目录树,注意space的使用
int space = 1;
void print(File file) {
space ++;
File[] files = file.listFiles();
for (File f : files) {
printSpace(space);
System.out.println(f);
if (f.isDirectory()) {
printFile(file);
}
}
space --;
}
// 递归删除目录下的所有文件和目录,注意,只能删除空目录
void deleteDirector(File file) {
if (file == null || !file.exists()) {
return;
}
File[] files = file.listFiles();
for (File f : files) {
if (f.isDirectory()) {
deleteDirector(f);
}else {
f.delete();
}
}
//这步是点睛之笔
file.delete();
}
nio之Paths、Files使用
Path path= Paths.get(new URI(myPath));
byte[] cLassBytes= Files.readAllBytes(path);
反射
每个类编译之后都会有一个class文件,什么时候加载到JVM中的,static{//代码块}这里面的代码块什么时候被执行
对其第一次使用时:
new Dog();
Class<?> clazz = Class.forName("com.file.Dog");
Dog.staticAttribute
Dog.staticMethod
类加载器的意义
任意一个类,都需要由加载它的类加载器和这个类本身一同确定其在java虚拟机中的唯一性
双亲委派模型的好处
Java类随着它的类加载器具备了一种带有优先级的层次关系。例如Object放在rt.jar中,无论哪一个类加载器加载这个类,最终都是委派给模型最顶端的启动类加载器加载
ClassLoader的使用与getDefaultClassLoader源码
- 双亲委派模型
启动类加载器(bootstrap classloader):负责JAVA_HOME/lib目录
扩展类加载器(extension classloader):JAVA_HOME/lib/ext目录
应用程序类加载器(application classloader):也叫系统类加载器,负责类路径
// 应用程序类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Class<?> loadClass(String name) {
// 检查是否已被加载过
Class<?> c = findLoadedClass(name);