class Singleton
{
static class A{
static public void show()
{
System.out.println("静态内部类");
}
}
}
public class Main
{
public static void main(String[] args)
{
//静态内部类和静态变量和静态方法一样,可以直接通过类名调用
Singleton.A.show();
}
}
Inner i = new Outer.Inner();
Outer o = new Outer();
Inner i = new o.Inner();
依赖
<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使用总结
字符串常量池,程序当中直接写上双引号字符串,就在字符串常量池中
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。
pom.xml中使用“import”的scope来解决Maven项目单继承问题
POM文件中,${xxx.version} 引用版本号爆红问题处理
Spring Boot Maven Plugin能够将Spring Boot应用打包为可执行的jar或war文件,执行springboot应用
Spring Boot 中的maven插件 spring-boot-maven-plugin
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
自定扫描到自定义的实体类。
爆红线的原因是直接放在了java目录下,需要放在包下。
定时任务框架Quartz-(一)Quartz入门与Demo搭建
maven依赖:
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
SAXReader reader = new SAXReader();
Document document = reader.read(new File("csdn.xml"));
read的参数可以是File对象,也可以是一个字符串表示路径
Tools.class.getClassLoader().getResourceAsStream(file);
首先,调用对象的getClass()方法是获得对象当前的类类型,这部分数据存在方法区中,而后在类类型上调用getClassLoader()方法是得到当前类型的类加载器,在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),所以在这里通过当前类的加载器来加载资源也就是保证是和类类型同一个加载器加载的。
最后调用了类加载器的getResourceAsStream()方法来加载文件资源
ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别
例如你写了一个MyTest类在包com.test.mycode 下,那么MyTest.class.getResourceAsStream(“name”) 会在com.test.mycode包下查找相应的资源
如果这个name是以 ‘/’ 开头的,那么就会从classpath的根路径下开始查找。
所以: MyTest.class.getResourceAsStream("/name") 和
MyTest.getClassLoader().getResourceAsStream(“name”) 的效果是一样的。
JAVA 笔记xx.getClass().getClassLoader().getResourceAsStream()
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)
//在不解压压缩文件的情况下,读取压缩文件里面的文件名
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;
}
ZipFile的entries()和getEntry(name)方法
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.10</version>
</dependency>
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.pathSeparator在win7上输出的话,显示为 (分号;)
二、而 File.separator 才是路径分隔符 \ 注: 可移植行强 是首选
三、 \ 在不同系统上不一样
getParentFile()的作用是获得父目录
问题就是.mkdirs(); 这个方法只能生成一层一层的文件夹,不能生成文件,而你的file对象路径是直接到文件那一层的,
不用getParentFile()获得父目录的话,就会想你说的那样生成两个文件夹而不是你想要的文件,所以要先调用getParentFile()获得父目录, 用.mkdirs()生成父目录文件夹,最后把你想要的文件生成到这个文件夹下面,就是想要的结果