JAVA知识盲区整理
- 静态内部类的调用时机
- 静态内部类
- Java中volatile关键字及其作用
- 一篇反射的好文链接
- 获取指定包下的注解--reflections工具类
- Spring如何在value注解中传入变量作为参数---使用SPEL表达式
- DocumentBuilderFactory解析XML
- SpringBoot整合JWT---令牌
- Google guava工具类的介绍和使用
- 大佬的java体系笔记整理
- Java必会的工具库,让你的代码量减少90%
- commons-beanutils使用介绍
- java字符串常量池
- 注解处理器(Annoation Processor)
- Maven 实战(三)——多模块项目的 POM 重构
- POM文件中,${xxx.version} 引用版本号爆红问题处理
- Spring Boot 中的maven插件 spring-boot-maven-plugin
- mybatis中type-aliases-package的用法
- Springboot启动类 红线问题解决
- Hutool
- xStream工具
- Guava官方教程
- Java Timer(定时器)
- 定时任务框架Quartz
- 用final修饰的变量只能赋值一次,并且必须在构造方法结束前进行赋值
- SpringBoot默认集成的Jackson框架,处理xml的还有xstream
- dom4j解析xml
- JAVA 笔记xx.getClass().getClassLoader().getResourceAsStream()
- 反射中的强转类型转换方法--cast
- Java File类常用方法及文件名过滤器(FilenameFilter)
- 使用ZipEntry压缩与解压缩
- java无需解压zip压缩包直接读取包内的文件名(含中文)
- java 解压 zip 包并删除
- ZipFile的entries()和getEntry(name)方法
- Java的ZipFile解压乱码报错---使用org.apache.tools.zip.ZipFile
- 分隔符File.separator和File.pathSeparator和\\ 的区别
- getParentFile在解压文件时的作用
静态内部类的调用时机
- 调用外部类的静态变量,静态方法可以让外部类得到加载,不过这里静态内部类没有被加载
- 静态内部类的加载不需要依附外部类,在使用时才加载。不过在加载静态内部类的过程中也会加载外部类
- 静态修饰过后的一切物件都只与类相关,不与对象引用相关
- 静态变量,静态方法,静态块等都是类级别的属性,而不是单纯的对象属性。他们在类第一次被使用时被加载(记住,是一次使用,不一定是实例化)。我们可以简单得用 类名.变量 或者 类名.方法来调用它们。与调用没有被static 修饰过变量和方法不同的是:一般变量和方法是用当前对象的引用(即this)来调用的,静态的方法和变量则不需要。从一个角度上来说,它们是共享给所有对象的,不是一个角度私有。这点上,静态内部类也是一样的。
class Singleton
{
static class A{
static public void show()
{
System.out.println("静态内部类");
}
}
}
public class Main
{
public static void main(String[] args)
{
//静态内部类和静态变量和静态方法一样,可以直接通过类名调用
Singleton.A.show();
}
}
静态内部类何时初始化
静态内部类
- 静态内部类跟静态方法一样,只能访问静态的成员变量和方法,不能访问非静态的方法和属性,但是普通内部类可以访问任意外部类的成员变量和方法
- 静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法
- 静态内部类可以单独初始化:
Inner i = new Outer.Inner();
- 普通内部类初始化:
Outer o = new Outer();
Inner i = new o.Inner();
java 静态内部类
Java中volatile关键字及其作用
- 内存可见性:某线程对 volatile 变量的修改,对其他线程都是可见的。即获取 volatile 变量的值都是最新的
- 不能保证变量的原子性,要么都成功,要么都失败
浅析Java中volatile关键字及其作用
一篇反射的好文链接
Java基础之—反射(非常重要)
获取指定包下的注解–reflections工具类
依赖
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
实现代码
//入参 要扫描的包名
Reflections f = new Reflections("com.ggband.netty.execute.command");
//入参 目标注解类
Set<Class<?>> set = f.getTypesAnnotatedWith(Cmd.class);
使用大全:
package com.mh.others.reflect_;
import com.mh.others.log.LOGUtils;
import org.junit.Test;
import org.reflections.Configuration;
import org.reflections.Reflections;
import org.reflections.scanners.*;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* 学习 org.reflections
*/
public class ReflectionsStu {
@Test
public void test1() throws Exception {
Reflections reflections = new Reflections(
"com.mh.others.reflect_", //指定被扫描的包名
Arrays.asList(
new SubTypesScanner(false)//允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes 会报错.默认为true.
,new MethodParameterNamesScanner()//设置方法参数名称 扫描器,否则调用getConstructorParamNames 会报错
,new MethodAnnotationsScanner() //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
,new MemberUsageScanner() //设置 member 扫描器,否则 getMethodUsage 会报错, 不推荐使用,有可能会报错 Caused by: java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot be cast to javassist.bytecode.MethodrefInfo
,new TypeAnnotationsScanner()//设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
)
);
Set<Class<? extends ReflectionsStu>> subTypes = reflections.getSubTypesOf(ReflectionsStu.class);//获取某一类的子类
Set<Class<?>> annotatedTypes = reflections.getTypesAnnotatedWith(ReflectClassFlag.class); //获取在Class上标有 ReflectClassFlag 注解的类, 包含被继承的子类
Set<Class<?>> annotatedTypesHonor = reflections.getTypesAnnotatedWith(ReflectClassFlag.class, true);//获取在Class上标有 ReflectClassFlag 注解的类, 不包含被继承的子类
Set<String> allTypes = reflections.getAllTypes(); //获取所有Object类的所有子类.此方法不推荐, 推荐 reflections.getSubTypesOf(class)
List<String> constructorParamNames = reflections.getConstructorParamNames(ChildReflectionsStu.class.getDeclaredConstructor(ReflectionsStu.class,Integer.class)); //获取构造方法上参数的名称
Set<Constructor> constructorsAnnotatedWith = reflections.getConstructorsAnnotatedWith(ReflectConstructorFlag.class);//获取标有注解ReflectConstructorFlag 的构造对象
Set<Method> methodsAnnotatedWith =
reflections.getMethodsAnnotatedWith(ReflectConstructorFlag.class); //获取带有ReflectConstructorFlag的注解的 method对象
Set<Member> methodUsage = reflections.getMethodUsage((Method)methodsAnnotatedWith.toArray()[0]); //获取 method 的 结构描述, 不推荐使用
reflections.save("/home/cmj/dump/a.txt"); //将数据保存到a.txt
Reflections collect = reflections.collect(new File("/home/cmj/dump/a.txt")); //从a.txt中加载数据
LOGUtils.printLog(Arrays.toString(subTypes.toArray()));
LOGUtils.printLog(Arrays.toString(annotatedTypes.toArray()));
LOGUtils.printLog(Arrays.toString(annotatedTypesHonor.toArray()));
LOGUtils.printLog(Arrays.toString(allTypes.toArray()));
LOGUtils.printLog(Arrays.toString(constructorParamNames.toArray()));
}
@ReflectClassFlag
class ChildReflectionsStu extends ReflectionsStu{
private String name;
private Integer age;
@ReflectConstructorFlag
public ChildReflectionsStu(String name) {
this.name = name;
}
public ChildReflectionsStu(Integer age) {
this.age = age;
}
public ChildReflectionsStu() {
}
@ReflectConstructorFlag
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
class GrandsonReflectionsStu extends ChildReflectionsStu{
}
}
Spring内部的ClassUtils类
reflections工具类
使用建议看此篇文章
Reflections 反射api使用总结
Spring如何在value注解中传入变量作为参数—使用SPEL表达式
SpEL表达式总结
DocumentBuilderFactory解析XML
参考链接
SpringBoot整合JWT—令牌
SpringBoot整合JWT
Google guava工具类的介绍和使用
Google guava工具类的介绍和使用
Google guava工具类的介绍和使用-csdn
详细版本
大佬的java体系笔记整理
链接
Java必会的工具库,让你的代码量减少90%
Java必会的工具库,让你的代码量减少90%
commons-beanutils使用介绍
BeanUtils
BeanUtils工具
commons-beanutils使用介绍
Common-BeanUtils 使用
java字符串常量池
字符串常量池,程序当中直接写上双引号字符串,就在字符串常量池中
-
对于基本类型来说 == 是进行数值得比较
-
对于引用类型来说 == 是进行【地址值】比较
String s1 = “abc”;
String s2 = “abc”;
System.out.println(s1==s2);
结果是 true;
采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"abc"这个对象,如果不存在,则在字符串常量池中创建"abc"这个对象,然后将池中"abc"这个对象的引用地址返回给"abc"对象的引用s1,这样s1会指向字符串常量池中"abc"这个字符串对象;如果存在,则不创建任何对象,直接将池中"abc"这个对象的地址返回,赋给引用s2。因为s1、s2都是指向同一个字符串池中的"abc"对象,所以结果为true。
String s3 = new String(“xyz”);
String s4 = new String(“xyz”);
System.out.println(s3==s4);
结果是 false
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"xyz"这个字符串对象,如果有,则不在池中再去创建"xyz"这个对象了,直接在堆中创建一个"xyz"字符串对象,然后将堆中的这个"xyz"对象的地址返回赋给引用s3,这样,s3就指向了堆中创建的这个"xyz"字符串对象;如果没有,则首先在字符串池中创建一个"xyz"字符串对象,然后再在堆中创建一个"xyz"字符串对象,然后将堆中这个"xyz"字符串对象的地址返回赋给s3引用,这样,s3指向了堆中创建的这个"xyz"字符串对象。s4则指向了堆中创建的另一个"xyz"字符串对象。s3 、s4是两个指向不同对象的引用,结果当然是false。
注解处理器(Annoation Processor)
注解处理器(Annoation Processor)
Maven 实战(三)——多模块项目的 POM 重构
Maven 实战(三)——多模块项目的 POM 重构
pom.xml中使用“import”的scope来解决Maven项目单继承问题
POM文件中,${xxx.version} 引用版本号爆红问题处理
POM文件中,${xxx.version} 引用版本号爆红问题处理
Spring Boot 中的maven插件 spring-boot-maven-plugin
Spring Boot Maven Plugin能够将Spring Boot应用打包为可执行的jar或war文件,执行springboot应用
Spring Boot 中的maven插件 spring-boot-maven-plugin
mybatis中type-aliases-package的用法
springboot项目中的application.yml文件中的mybatis:type-aliases-package:什么时候用
mapper.xml文件中resultMap的type、parameterType、resultType会引用一些实体类,我们需要写上全限定类名,如果不写全限定类名,只写一个实体类的名称的话,那就需要在application.yml文件中设置mybatis:type-aliases-package参数;
怎么写application.yml中的mybatis:type-aliases-package
mybatis:
type-aliases-package: com.atguigu.springcloud.entities #实体类所在的包
在配置好mybatis后,我们在mapper.xml映射文件中不需要写出实体类的完整路径,只需要写出类名即可
使用type-aliases-package
指定实体类所在包让mybatis
自定扫描到自定义的实体类。
Springboot启动类 红线问题解决
爆红线的原因是直接放在了java目录下,需要放在包下。
Hutool
Hutool官网
xStream工具
xStream操作详细总结
XStream 简介
Guava官方教程
中文文档
【吐血整理】想学Google Guava看这篇就够了
Java Timer(定时器)
Timer
定时任务框架Quartz
定时任务框架Quartz-(一)Quartz入门与Demo搭建
用final修饰的变量只能赋值一次,并且必须在构造方法结束前进行赋值
SpringBoot默认集成的Jackson框架,处理xml的还有xstream
Jackson快速入门
Java-Jackson使用详解
dom4j解析xml
maven依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
使用Dom4j解析XML
SAXReader reader = new SAXReader();
Document document = reader.read(new File("csdn.xml"));
read的参数可以是File对象,也可以是一个字符串表示路径
JAVA 笔记xx.getClass().getClassLoader().getResourceAsStream()
Tools.class.getClassLoader().getResourceAsStream(file);
首先,调用对象的getClass()方法是获得对象当前的类类型,这部分数据存在方法区中,而后在类类型上调用getClassLoader()方法是得到当前类型的类加载器,在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),所以在这里通过当前类的加载器来加载资源也就是保证是和类类型同一个加载器加载的。
最后调用了类加载器的getResourceAsStream()方法来加载文件资源
ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别
- Class.getResourceAsStream() 会指定要加载的资源路径与当前类所在包的路径一致
例如你写了一个MyTest类在包com.test.mycode 下,那么MyTest.class.getResourceAsStream(“name”) 会在com.test.mycode包下查找相应的资源
如果这个name是以 ‘/’ 开头的,那么就会从classpath的根路径下开始查找。
- ClassLoader.getResourceAsStream() 无论要查找的资源前面是否带’/'都会从classpath的根路径下查找。
所以: MyTest.class.getResourceAsStream("/name") 和
MyTest.getClassLoader().getResourceAsStream(“name”) 的效果是一样的。
JAVA 笔记xx.getClass().getClassLoader().getResourceAsStream()
反射中的强转类型转换方法–cast
A类名.class.cast(要转换成A类型的B实例对象)
B要是A的子类或是当前类型
class A {
public static void show() {
System.out.println("Class A show() function");
}
}
class B extends A {
public static void show() {
System.out.println("Class B show() function");
}
}
public class TestCast {
public static void main(String[] args) {
TestCast cls = new TestCast();
Class c = cls.getClass();
System.out.println(c);
Object obj = new A();
B b1 = new B();
b1.show();
// casts object
A a = new A();
a = A.class.cast(b1);
System.out.println(obj.getClass());
System.out.println(b1.getClass());
System.out.println(a.getClass());
}
}
此方法只能转换当前类型或其子类下的对象,只是简单进行强转。
Java File类常用方法及文件名过滤器(FilenameFilter)
Java File类常用方法及文件名过滤器(FilenameFilter)
使用ZipEntry压缩与解压缩
使用ZipEntry压缩与解压缩
java无需解压zip压缩包直接读取包内的文件名(含中文)
java无需解压zip压缩包直接读取包内的文件名(含中文)
//在不解压压缩文件的情况下,读取压缩文件里面的文件名
public List<String> getZipInnerFileName(String zipPath) throws IOException//压缩文件的路径
{
List<String> fileNameLists=new ArrayList<>();
java.util.zip.ZipEntry zipEntry = null;
File file = new File(zipPath);
if(file.exists()){ //判断文件是否存在
ZipInputStream zipInputStream = new ZipInputStream( new FileInputStream(zipPath), Charset.forName("GBK")); //解决包内文件存在中文时的中文乱码问题
while ((zipEntry=zipInputStream.getNextEntry()) != null) {
//遇到文件夹就跳过
if(zipEntry.isDirectory())
{
continue;
}else
{
//获取到压缩文件里面文件的名称
fileNameLists.add(zipEntry.getName());
}
}
//关闭流---一定要管理流,不然不能删除zip压缩文件
zipInputStream.close();
}
return fileNameLists;
}
java 解压 zip 包并删除
java 解压 zip 包并删除
ZipFile的entries()和getEntry(name)方法
ZipFile的entries()和getEntry(name)方法
Java的ZipFile解压乱码报错—使用org.apache.tools.zip.ZipFile
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.10</version>
</dependency>
Java的ZipFile解压乱码报错
package xfx.com.reader;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipInputStream;
//从properties文件中读取路径
@Component
@PropertySource("classpath:path.properties")
public class PathReader
{
@Value("${file.path}")
private String filePath;
@Value("${img.path}")
private String imgPath;
@Value("${course.file.prefix}")
private String filePrefix;
@Value("${course.study.prefix}")
private String studyPrefix;
@Value("${course.file.name}")
private String courseFileName;
@Value("${course.file.cover}")
private String courseFileCover;
public String getCourseFileName() {
return courseFileName;
}
public String getCourseFileCover() {
return courseFileCover;
}
public String getFilePrefix() {
return filePrefix;
}
public String getStudyPrefix() {
return studyPrefix;
}
public String getFilePath() {
return filePath;
}
public String getImgPath() {
return imgPath;
}
//在不解压压缩文件的情况下,读取压缩文件里面的文件名
public List<String> getZipInnerFileName(String zipPath) throws IOException//压缩文件的路径
{
List<String> fileNameLists=new ArrayList<>();
java.util.zip.ZipEntry zipEntry = null;
File file = new File(zipPath);
if(file.exists()){ //判断文件是否存在
ZipInputStream zipInputStream = new ZipInputStream( new FileInputStream(zipPath), Charset.forName("GBK")); //解决包内文件存在中文时的中文乱码问题
while ((zipEntry=zipInputStream.getNextEntry()) != null) {
//遇到文件夹就跳过
if(zipEntry.isDirectory())
{
continue;
}else
{
//获取到压缩文件里面文件的名称
fileNameLists.add(zipEntry.getName());
}
}
//关闭流
zipInputStream.close();
}
return fileNameLists;
}
private static byte[] _byte = new byte[1024*8] ;
//解压文件的方法
//zipFile 解压缩文件
//descDir 压缩的目标地址
public void unZipFile(File zipFile,String descDir)
{
try {
//指定使用编码格式,防止中文乱码
ZipFile _zipFile = new ZipFile(zipFile,"GBK");
//得到枚举,通过循环来读取zip文件内部一个个文件
for(Enumeration entries = _zipFile.getEntries(); entries.hasMoreElements() ; )
{
//创建文件条目对象,来接收枚举得到的文件或者目录
ZipEntry entry = (ZipEntry)entries.nextElement();
//当前压缩文件具体要解压到的地址
//压缩到具体的目录地址+分隔符号(即'\')+当前文件的名字
File _file = new File(descDir + File.separator + entry.getName()) ;
//如果当前得到的不是文件而是目录,那么就创建目录
if( entry.isDirectory() )
{
_file.mkdirs() ;
}
else//如果得到的是文件
{
//获得父目录
File _parent = _file.getParentFile() ;
//判断父目录是否存在,如果不存在,就创建父目录
if( !_parent.exists() ){
_parent.mkdirs() ;
}
//将当前文件条目对象放到文件字节输入流中---将文件里面的数据读取出来
InputStream _in = _zipFile.getInputStream(entry);
//获得文件字节输出流---将数据写到文件里面
OutputStream _out = new FileOutputStream(_file) ;
//当len=-1表示读取完毕
int len ;
while( (len = _in.read(_byte)) > 0)
{
//参数一是缓冲数组,参数2是从数组中的哪个位置开始读取,参数3是读取的长度
_out.write(_byte, 0, len);
}
//将读取数据刷新到硬盘上
//然后关闭输出流
if (null !=_out){
_out.flush();
_out.close();
}
//关闭输入流
if (null !=_in){
_in.close();
}
}
}
//关闭zip流
_zipFile.close();
//删除解压完后的压缩文件
zipFile.delete();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
分隔符File.separator和File.pathSeparator和\ 的区别
一、File.pathSeparator在win7上输出的话,显示为 (分号;)
二、而 File.separator 才是路径分隔符 \ 注: 可移植行强 是首选
三、 \ 在不同系统上不一样
getParentFile在解压文件时的作用
getParentFile()的作用是获得父目录
问题就是.mkdirs(); 这个方法只能生成一层一层的文件夹,不能生成文件,而你的file对象路径是直接到文件那一层的,
不用getParentFile()获得父目录的话,就会想你说的那样生成两个文件夹而不是你想要的文件,所以要先调用getParentFile()获得父目录,
用.mkdirs()生成父目录文件夹,最后把你想要的文件生成到这个文件夹下面,就是想要的结果