JAVA常见知识点

java5 - java12新特性 https://segmentfault.com/a/1190000018588495
ps: 1. jdk10以后没有jre目录:在安装目录的bin的目录打开cmd窗口执行命令生成JRE	bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre
    2. jdk12不支持新的switch写法,idea/file/project structure/language level 选择 "12(preview) - switch expressions"模式

*javadoc注释文档的生成
方法1:javac、javadoc命令的配置系统变量	CLASSPATH值		.;%JAVA_HOME%\bin
使用 javadoc -d 文档存储路径 java文件 生成注释文档index.html

方法2:ieda直接操作
Tools -> Generate JavaDoc…
勾选 whole projet、include jdk and... 
output directory:文档存储路径
line arguments: -encoding UTF-8 -charset UTF-8

*value注解设置默认值
@Value("${some.key:one,two,three}")
private String[] stringArrayWithDefaults;

//static注入,方法一
@Component
public class ConfigUtil {
    public static boolean ouSwitch;

    @Value("${ou.switch:false}")
    public void setOuSwitch(boolean ouSwitch) {
        ConfigUtil.ouSwitch = ouSwitch;
    }
}

//static注入,方法二
@Autowired
private DistributedLocker locker;
private static DistributedLocker distributedLocker;

@PostConstruct
private void init() {
    distributedLocker = locker;
}
public static RLock lock(String lockKey) {
    return distributedLocker.lock(lockKey);
}

*断言
//启动类配置vm options 添加断言开关 -ea
assert false : "断言失败,抛出错误信息xxx";
System.out.println("断言正常,ok");

*设置Multipart文件上传临时目录路径
tomcat启动时会创建两个文件夹tomcat.1691944433863531880.8083\work\Tomcat\localhost\admin和tomcat-docbase.2672810730193600147.8083
前一个是上传文件时,存二进制文件的目录(重要,删除后上传后台入参MultipartFile file会异常,上传成功后临时文件会自动删除)
配置类添加:
@Bean
MultipartConfigElement multipartConfigElement() {
	//创建目录
	File dir = new File("d:/tomcat/upload/temp");
	try {
		if (!dir.exists()) dir.mkdirs();
	} catch (Exception e) {
		e.printStackTrace();
	}

	MultipartConfigFactory factory = new MultipartConfigFactory();
	factory.setLocation("d:/tomcat/upload/temp");
	return factory.createMultipartConfig();
}

*获取项目路径
String path = request.getSession().getServletContext().getRealPath("/");       //绝对路径
String path = Main.class.getClassLoader().getResource("test-task.log").getPath();	//绝对路径,静态方法
String path= this.getClass().getResource("test-task.log").getPath();	//绝对路径,动态方法
String projectPath= System.getProperty("user.dir");	//项目根路径

*String、Bigdecimal均可用compareTo()进行比较
*String.format("您的账户于%tF %tT通过【%s】%f元.", new Date(), new Date(), "支付宝转账", 2000.00)	//您的账户于2019-06-03 10:17:29通过【支付宝转账】2000.000000 元.
*new BigDecimal().abs()  //bigdecimal取正
*导出不能用post请求
*DecimalFormat对数字进行格式化
*Map<String, List<RespSysLevelinfoCycle>> respSysLevelinfoCycleCollect = respSysLevelinfoCycles.stream().collect(Collectors.groupingBy(RespSysLevelinfoCycle::getLevelCode));	//Collectors.groupingBy分组
*CollectionUtils.arrayToList(array)	//array -> list
*json数组转list
JSONArray jsonArray = json.getJSONArray("list");
List<TradeOrder> list = jsonArray.toJavaList(TradeOrder.class);
*json直接赋值
JSONObject jsonBody = new JSONObject(){{
	put("sign", "81b040e9c41dbd964191e3c7586116b2");
	put("list", list);
}};
*类型转换(数字转成文字)
public class ParamMapUtils {
    public static final Map<String, String> symbolType = new HashMap<>();
    public static final Map<Integer, String> orderType = new HashMap<>();

    static {
        symbolType.put("2","足金9999 发发金预订金条 ");
        symbolType.put("3","足银9999 发发银预订银条 ");
		
        orderType.put(0, "ORDER_TYPE_OPEN");
        orderType.put(1, "ORDER_TYPE_CLOSE");
    }
}
使用
order.setOrderType(ParamMapUtils.orderType.get(order.getOrderStatus()));

*获取parmas_config.properties参数
private static ResourceBundle resourceBundle = new PlatformResourceBundleLocator("parmas_config").getResourceBundle(Locale.getDefault());
String value = resourceBundle.getString("resp.status.success");

*键盘输入
Scanner sc = new Sanner(System.in);
int 获取输入的值 = sc.nextInt()

*科学记数法数值格式化
double s = Double.parseDouble("1.3447E8");
String format = NumberFormat.getInstance().format(s);

*字符串日期严格转换
simpleDateFormat.setLenient(false);
SimpleDateFormat为非线程安全,多线程下需结合LocalThread绑定线程或每次使用完即销毁

*获取request
 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

*启动类
public class APIApplication extends SpringBootServletInitializer implements ApplicationListener<ContextRefreshedEvent> { }
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
	return application.sources(APIApplication.class);
}

@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
	logger.info("程序启动成功。。。");
}

*遍历map
Map<String, ?> map = null;
for(Map.Entry<String, ?> query : map.entrySet()) {
	query.getKey();
	query.getValue();		  
}

for(Iterator<Map.Entry<String, String>> it = paramerMap.entrySet().iterator(); it.hasNext();) {
	Map.Entry<String, String> entry = it.next();
	if(StringUtils.isEmpty(entry.getValue())) {
		it.remove();
	}
}

*用for来代替while(true)实现无限循环
for(;;){}

*compareTo() 比较器不支持值为null的数值包装类

*编码&解码url参数
String name = URLEncoder.encode("张三", UTF8);
System.out.println(name);
System.out.println(URLDecoder.decode(name));

*try-catch的简写(try括号内的资源会在try语句结束后自动释放,前提是这些可关闭的资源必须实现 java.lang.AutoCloseable 接口)
try(
	InputStream fis = new FileInputStream(source);
	OutputStream fos = new FileOutputStream(target)
){
	//内容体		
} catch(Exception e){
	e.printStackTrace();
}

*接口签名生成	 https://www.cnblogs.com/hujunzheng/p/9725168.html
//获取请求头部属性列表
Map<String, Object> headerMap = Collections.list(request.getHeaderNames())
            .stream()
            .filter(headerName -> SignatureHeaders.HEADER_NAME_SET.contains(headerName))
            .collect(Collectors.toMap(headerName -> headerName.replaceAll("-", "."), headerName -> request.getHeader(headerName)));
//Spring的MapPropertySource刷新系统属性值(key-value配置在外部系统中如redis,数据库等)
PropertySource propertySource = new MapPropertySource("signatureHeaders", headerMap);

*加密生成签名
String postData = jsonDataString
Map<String,String> parameterMap = new HashMap<>();
parameterMap.put("appid", "4430");
parameterMap.put("timestamp", String.valueOf(System.currentTimeMillis()/1000L));
parameterMap.put("nonce", UUID.randomUUID().toString().replaceAll("-",""));
parameterMap.put("payload_sig", DigestUtils.md5Hex(postData).toUpperCase());
List<Map.Entry<String, String>> list = new ArrayList<>(parameterMap.entrySet());
Collections.sort(list, (o1, o2) -> o1.getKey().compareTo(o2.getKey()));		//升序排序
String param = list.stream().map(m -> { return String.format("&%s=%s", m.getKey(), URLEncoder.encode(m.getValue(), "UTF-8")); }).collect(Collectors.joining());		//url参数拼接
param+="&key="+appSecret;
String data = param.substring(1);				  
Mac md5_info = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(appSecret.getBytes("UTF-8"), "HmacSHA256");
md5_info.init(secret_key);
byte[] result = md5_info.doFinal(data.getBytes("UTF-8"));
String signature = Hex.encodeHexString(result).toUpperCase();

* 抽象类不能用@RestController,无法注入到spring
*HttpServletRequest获取请求参数
HttpServletRequest req = (HttpServletRequest)request;
String token = req.getHeader("token");
String weeks = req.getParameter("weeks");
注:getHeader对get、post均可,getParameter获取json字符串时用getInputStream()

*@RestController下进行页面跳转
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
return mv;

*@Async
启动类添加 @EnableAsync
实现类添加 @Async

* springboot项目启动解析不了配置 1.配置缺失 2.文件名错误(标准application-xxx)

*泛型为反射类型
Map<Class<? extends Animal>, User>  map = new HashMap<Class<? extends Animal>, User>();
map.put(Dog.class, new User());

*反射获取实例的几种方式(必须有无参构造)
User user1 = (User)Class.forName("com.aurora.happy.pojo.User").newInstance();

User user2 = (User)DemoTest.class.getClassLoader().loadClass("com.aurora.happy.pojo.User").newInstance();

User user3 = User.class.newInstance();

User user4 =  User.class.getDeclaredConstructor(Long.class, String.class, Integer.class).newInstance(1L, "lisa", 18);

*类中接口
public class SettlementRelationService {
  	public interface Iface {
    		public ReceivableSearchResult getRelReceivableBySLTId(String settlementId, String bizTypeId, int pageSize, int pageIndex) ;
}
  }
implements SettlementRelationService .Iface 

*引入依赖包中的配置文件
<import resource="classpath*:shiro/spring-shiro.xml"/>

【对象映射获取对象setter/getter方法一】	 https://blog.csdn.net/u014082714/article/details/82220510
Class clazz = Class.forName("com.ssm.model.Price");
Object obj =  clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
//写数据,即获得写方法(setter方法)给属性赋值
for(Field f : fields){
String name = f.getName();

//法一
PropertyDescriptor pd = new PropertyDescriptor(name, clazz);
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(obj, "345");

//法二
char[] chars = name.toCharArray();
chars[0]-=32;
String setName = "set".concat(String.valueOf(chars));
Method method = clazz.getDeclaredMethod(setName, f.getType());
method.invoke(obj, "123");

//法三
String setName = "set".concat(StringUtils.capitalize(name));
Method method = clazz.getDeclaredMethod(setName, f.getType());
method.invoke(obj, "123");
 }
System.out.println(obj.toString());


【对象映射获取对象setter/getter方法二】
Class<T> clazz = Entity.class;	//获取实体映射
Field[] fields= clazz.getDeclaredFields();	//实体属性数组
List<T> list = new ArrayList<T>();
T t = clazz.newInstance();	//映射机制获取实体对象
for(Field f : fields){
    //1.获取set名称
    char[] chars = f.getName().toCharArray();
    chars[0]-=32; //ASCII码转大写
    String setName = "set".concat(String.valueOf(chars));
    //2.获取set方法
    Method method = clazz.getDeclaredMethod(setName, f.getType());
    //3.给对象赋值
    switch (f.getGenericType().toString()){  //字段类型
        case "int":
        case "class java.lang.Integer":
            method.invoke(t, 1001);
            break;
        case "char":
        case "class java.lang.Char":
            method.invoke(t, '男');
            break;
        case "class java.lang.String":
            method.invoke(t, "李海");
            break;
        default: break;
    }
}

switch支持的类型:byte short int char string enum

【对象属性复制】bean -> dto
BeanUtils.copyProperties(bean, dto);      //不支持list拷贝
dto.setAmount(String.valueOf(bean.getAmount()));	//同名不同类型
ps:只能复制 1.共同存在的 2.必须是同类型同名称的 3.其余的单独手动set
Collections.copy(tag, src)	//支持同泛型的list,推荐使用dozer

【字符串数值 ==> 数值类型】
DecimalFormat f = new DecimalFormat("0.00");  //保留位数
String sf = f.format(Object number);   //任意数值类型转换成字符串
Double.valueOf(sf );	//字符串转换成对于数值对象

【lombok建造者】
@Data
@Builder
public class User {}
UserBuilder userBuilder = User.builder().id(1).age(18).name("liming").sex("男");
User user = userBuilder.build();

【非注解方式建造者】
public class User {
    private int id;
    private String name;
    private Map<String, Object> filterMap;

    public User() {
        this.filterMap = new HashMap<String, Object>();
    }

    public static User newBuilder() {
        return new User();
    }

    public User id(int id) {
        this.setId(id);
        return this;
    }

    public User name(String name) {
        this.setName(name);
        return this;
    }

    public User filterMap(String key, Object val) {
        this.filterMap.put(key, val);
        return this;
    }
    //setter|getter省略

    public static void main(String[] args) throws Exception{
        User user = User.newBuilder()
                .id(11)
                .name("susan")
                .age(18)
                .filterMap("page", 1)
                .filterMap("rows", 50);
        System.out.println(new ObjectMapper().writeValueAsString(user));
    }
}

【system获取系统属性】
Properties properties = System.getProperties();
properties.get("java.version");	//jdk
properties.get("os.name");	//操作系统

【list转array】
String[] strs = (String[]) list.toArray(new String[0]);

# 非序列化线程共享变量
private transient volatile String ip;

# 通过静态变量获取对象
public static ConfService Current = new ConfService();

# 同步方法
private synchronized void initialize(){}

# 同步代码块
synchronized(App.class) {}

# this代表类对象,不可再static方法内使用

# static静态方法
随着类的加载而加载,只执行一次,优于主函数执行,在静态方法之前执行,用于给类初始化

# 方法加载顺序
静态变量 - 静态代码块 - 动态代码块(new obj调用方法时触发) - 无参构造 - 静态/动态方法

# 系统变量的获取
String value = System.getenv()

# 系统变量,启动jar时可以自定义添加
Properties properties = System.getProperties();
properties.stringPropertyNames().forEach(key -> {
	System.out.println(properties.getProperty(key));
});

# 获取配置文件属性
Properties properties = new Properties();
InputStreamReader streamReader = new InputStreamReader(new FileInputStream(filePath), charset);
properties.load(streamReader);
// properties.load(new StringReader(extConfig));  //extConfig为properties配置内容
properties.getProperty(key)

【mybatis多数据源构造不同的sqlsession】
# 根据xml配置文件和自定义properties内容构造sqlsession工厂
ClassLoader classLoader = ServicesHelper.class.getClassLoader()
InputStream stream = classLoader.getResourceAsStream("mybatis.xml")
Thread.currentThread().setContextClassLoader(classLoader);
//mybatis.xml可用${key}获取properties中的对应key的value, 其中db-default为数据源id
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream, "db-default", properties);		
# 关闭资源
ClassLoader pre = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(pre);
stream.close();
# 获取sqlsession
SqlSession sqlSession = factory.openSession();

# 布尔值的获取
Boolean.TRUE.toString()

# 路径获取
String fileName = Paths.get(path).getFileName().toString();

# 字符集的获取
Charset.forName("UTF-8");

# 字符串为空判断
StringUtils.hasText(字符串)

# http请求
URIBuilder builder = new URIBuilder(url);
builder.setParameter("appid", Integer.toString(appid)).setParameter("appname", appName).setParameter("env", env).setParameter("host", host);
HttpRequestBase request = new HttpGet();
request.setURI(builder.build());
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
if (response.getStatusLine().getStatusCode() == 200) {
	return EntityUtils.toString(response.getEntity()).getBytes();
}

# list泛型转换	
List<String> values
String.join(",", values)	//Joiner.on(",").join(list)
List<String> newList = Lists.transform(values, new Function<Integer, String>() {
	public String apply(Integer input) {
		return input.toString();
	}
});	

# list<Object>泛型转换	List<Map<String,Object>>
public <T> List<Map<String, Object>> listConvert(List<T> list) {
    List<Map<String,Object>> listMap = new ArrayList<>();
    try {
        for (T t : list) {
            Field[] fields=t.getClass().getDeclaredFields();
            Map<String, Object> m = new HashMap<>();
            for(Field field : fields){
                String keyName = field.getName();
                if (!"this$0".equals(keyName)) {
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();
                    Object o = getMethod.invoke(t);
                    m.put(keyName, o);
                }
            }
            listMap.add(m);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return listMap;
}

# 字符串大小写、驼峰的转换	
CaseFormat.UPPER_CAMEL

# Spring中ApplicationContext的三种不同实现	
ApplicationContext ctx  = new FileSystemXmlApplicationContext("spring-config.xml")
ApplicationContext ctx  = new ClassPathXmlApplicationContext("spring-config.xml")
ApplicationContext ctx  = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
UserService us = (UserService) ctx.getBean("UserService");
UserService us = ctx.getBean(UserService.class);

//spring mvc拦截器
HandlerInterceptorAdapter

//java时间处理
java.time中的 LocalDateTime
java.util中的 Date 、Calender
java.text中的 SimpleDateFormat
hutool中的 DateTime

//xml格式解析
Unmarshaller

* LinkHashMap是有序put,HashMap则是无序的。而TreeMap则按key的ASCII值升序来排。TreeSet可以升序去重。HashedMap为apache commons包下的一个Map类似HashMap。
  在JDK1.8中,ConcurrentHashMap的性能和存储空间要优于ConcurrentSkipListMap,但是ConcurrentSkipListMap有一个功能: 它会按照键的自然顺序进行排序。

* 科学记数法(其他数值也可)格式成原有格式以string输出
String strVal = new BigDecimal(XXX.toString()).toPlainString();

*excel解析时出现科学记数法或数值浮点型时
case XSSFCell.CELL_TYPE_NUMERIC:    // 数字
    cell.setCellType(cell.CELL_TYPE_STRING);
    return String.valueOf(cell.getStringCellValue());

*Java8前,接口中的实现方法必须是abstract的,实现该接口的类必须重写该方法,Java8后增加了default关键词,用default修饰的方法可以有实现内容,实现该接口的类可以不重写用default修饰的方法,类似于继承。

*Dozer实现属性复制
protected final static <T, S> T map(S source, Class<T> clazz) {
    if (source == null) {
        return null;
    }
    Assert.notNull(clazz, "clazz can not be null");
    return DozerBeanMapperBuilder.buildDefault().map(source, clazz);
}

*自定义lambda的function接口
public static <T> T doInDataBase(Function<SqlSession, T> func) {
    SqlSession sqlSession = sqlSessionContext.get();
    if (sqlSession == null)  sqlSession = getDefaultSqlSession();
    T result = func.apply(sqlSession);
}
//apply()即调用lambda接口
return ServicesHelper.doInDataBase(sqlSession -> {
	//todo someting ...
	return Object;
});

*guava中本地缓存
private static LoadingCache<String, List<OuBean>> ouCaches = CacheBuilder.newBuilder()
        .maximumSize(100)
        .expireAfterAccess(3600, TimeUnit.SECONDS)
        .build(new CacheLoader<String, List<OuBean>>() {
            @Override
            public List<OuBean> load(String s) throws Exception {
                return 主体逻辑;
            }
        });

*java定时器
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
   @Override
    public void run() {
           cacheMap.remove(key);
     }
};
 //启动
 timer.schedule(timerTask , date);

*map中若key对应的value为空,会将第二个参数的返回值存入该key并返回
Object key2 = map.computeIfAbsent("key", k -> new Object());

*根据模板发送邮件
1.thymeleaf引擎将发送内容填入模板页面,然后格式化成文本
String contentBody = thymeleafEngine.process(templateName, context);
2.调用email工具类发送
EmailUtil.sendEmailTo(sendTo, "", subject, contentBody);

*StringUtils.isEmpty("  ") = false 与 StringUtils.isBlank("  ") = true

*利用string进行日期格式化
String.format("%tF %tT", date, date) 	//2018-08-08 08:00:00
String.format("%tF %tT", date, date) 	//2018-08-08 08:00:00

*断言验证非空
Objects.requireNonNull(user, "user is not null");
Assert.notNull(user, "user is not null");
Assert.isTrue(StringUtils.isNotBlank(str), "str is null or empty");
list.isEmpty() 类似于 list.size() == 0
Assert.notEmpty(list, "list is not null or empty");

*StringUtils的使用	https://blog.csdn.net/diypp2012/article/details/82971716
非空判断、大小写转换、字符常规操作、字符拆分合并

*BigDecimal的使用 https://blog.csdn.net/u011936655/article/details/86173862

*生成数字字符串(不一定唯一)
CRC32 crc32 = new CRC32();
crc32.update("法国萨法沙发".getBytes("UTF8"));
long seq = crc32.getValue();

*判断字符串是否为全数字
StringUtils.isNumeric(str);

*判断是否为两位小数数字
str.matches("-?\\d+\\.?\\d{0,2}");

//推断局部变量类型(Java 10+不需要借助lombok已支持该功能),只能用于局部变量,作用相当于 final + var
val nodes = StringUtils.commaDelimitedListToSet("aaa,bbb,ccc");

//list除stream外,也可以直接调用循环接口
list.forEach(lambda表达式)

*参数校验、基础查询、日志添加、执行时间、异常处理等操作,最好通过 Aspect切面、注解、过滤器或接口实现

*值传递 与 引用(类型)传递  https://www.zhihu.com/question/31203609
值传递:8大基础类型 + String     	//作为形参传递时,不会影响原值
引用传递: 数组、对象、集合等  	//作为形参传递时,会影响原对象属性值

*数值类型最值限制
举栗:int值相乘,如果值超过其最大值2^31-1时,结果会异常
long num = 2<<30     (错误,正确写法 2L<<30)
long num = 365*24*3600*1000     (错误,正确写法 365*24*3600*1000L)

*原子包装类计数
AtomicInteger successCount = new AtomicInteger();
successCount.getAndIncrement();		//每执行一次 +1

*try-catch中io流的关闭简化
try(OutputStream is = new ByteArrayOutputStream()) { 
//todo
} catch(Exception e) {
e.printStackTrace();
}

*直接导入常量类,可以直接用该变量,省去类名点
import static saas.receivable.common.constants.ReceivableConstant.CREDIT_MEMO;

*k-v对象
NameValuePair nv = new BasicNameValuePair("name", "value");
nv.getName()

*小型set,只能int,去重有序
BitSet bs = new BitSet();

*字符半角全角转换	https://blog.csdn.net/hy_coming/article/details/93390469
SBC-全角(ASCII码范围:33 ~ 126)
DBC-半角(ASCII码范围:65281 ~ 65374)
半角全角间隔偏移量:65248
全角空格SBC_SPACE:12288	//不遵循偏移量,单独处理
半角空格DBC_SPACE: 32		//无对应ASCII码,单独处理

*java四种引用类型:强引用  >  软引用  >  弱引用  >  虚引用

*编码格式,等价于Charset.forName("UTF-8")
StandardCharsets.UTF_8; 

*线程休眠
TimeUnit.SECONDS.sleep(10);

*本地线程变量的Lambda创建形式
ThreadLocal<T> threadLocal = ThreadLocal.withInitial(() -> { });

*多线程下,产生随机布尔值
boolean b = ThreadLocalRandom.current().nextBoolean();

*获取ServletContext的方法共5种(page域这里不考虑,JSP太少用了)
ServletConfig#getServletContext()
GenericServlet#getServletContext()
HttpSession#getServletContext()
HttpServletRequest#getServletContext()
ServletContextEvent#getServletContext()

*特殊字符处理:空格、制表、换行、回车
if (str != null) {
	Pattern p = Pattern.compile("\\s*|\t|\r|\n");
	Matcher m = p.matcher(str);
	dest = m.replaceAll("");
}

*Lambda功能函数里使用外部变量,只能是引用的,不能是String、8大基础类型及包装类

*thrift中的cglib代理对象,get为代理属性值,set为真实属性值,故不可用set方法,建议用原子引用类AtomicReference进行存值

*分页查询再汇总
List<String> ids = services.searchReceiptListByDs();
List<ReceiptEntity> totalList = Lists.newLinkedList();
int remainCount = ids.size();
int idx = 0;
while (remainCount > 1000) {
	List<String> tempIds = receiptIds.subList(idx, idx + 1000);
	List<ReceiptEntity> list = ReceiptSelectDsDao.searchReceiptListByDs(tempIds);
	totalList.addAll(list);
	idx += 1000;
	remainCount -= 1000;
}
List<String> tempIds2 = ids.subList(idx, ids.size());
List<ReceiptEntity> list2 = ReceiptSelectDsDao.searchReceiptListByDs(tempIds2);
totalList.addAll(list2);

*对List进行操作时报错java.lang.UnsupportedOperationException
List<String> list = Collections.emptyList()
list.addAll(mybatis结果集)		-- mybatis默认返回ArraysList
或
List<String> list = Arrays.asList(array);

list.add("6");
原因:Collections.emptyList()和Arrays.asList(array)返回的list均不是java.util.ArraysList,而是属于内部类list对象,故不支持ArraysList的操作
解决:new ArrayList<>(Collections.emptyList())   或  new ArrayList<>(Arrays.asList(1,2,3))

*内部类创建对象
普通内部类:PersonDto.WomenDto = new PersonDto().new WomenDto();
静态内部类:PersonDto.WomenDto = new PersonDto.WomenDto();

*浏览器URL请求参数中含有“+”等特殊字符,被自动替换成空格
url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值。
+    URL 中+号表示空格                   %2B   
空格 URL中的空格可以用+号或者编码          %20 
/     分隔目录和子目录                    %2F     
?    分隔实际的URL和参数                  %3F     
%   指定特殊字符                          %25     
#    表示书签                             %23     
&    URL 中指定的参数间的分隔符            %26     
=    URL 中指定参数的值                   %3D


*阻塞当前线程
System.in.read();      //相当于程序无法终止

*大数可用下划线分隔符,更佳简洁好看代码
long sum = 100_0000L;
for (int i = 0; i < 1_000_000L; i++)

*查看class字节码内容
cmd窗口命令:javap -c xxx.class

* equals 和 hashcode 方法要重写的原因
hashCode主要用于提升查询效率,来确定在散列结构中对象的存储地址;
重写equals()必须重写hashCode(),二者参与计算的自身属性字段应该相同;

*父类子类加载顺序
先父后子:(静态变量/代码块)、(非静态变量/代码块、构造函数)、子类重写方法

*配置类实现 implements InitializingBean, DisposableBean
可以完成配置加载后的一些初始化工作和销毁方法

* 排出其他包的自动配置类
@SpringBootApplication的exclude 专门用来排除auto-configuration 也就是我们说的自动配置的类的,
如果我们想排除自己定义的@Bean,可以用 @ComponentScan(excludeFilters= {@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value= {AvoidScan.class})})

*内部类上的注解需要在外部类上添加@Component才能被扫描到

*枚举方法
static enum A implements PrintOut{
     RED(1, "red"){
        @Override
        public void prinft{
           this.getColor();
           //todo
       }
    },
    BLUE(...)
    ;
    private int code;
    private String color;

    static String getColorByCode(int code){
          //todo
    }
}

*同一请求内,变量独有使用ThreadLocal。同一用户登录后的不同请求,线程可能不一样(线程池),所以需要用

* bean设计
接口 - 抽象类 - 默认抽象实现类
                      - 自定义实现类
配置类 - 接口对象注入
            - 重写接口对象,@Primary优先使用 

* long强转int类型问题
负数取模结果为0或负数
(int)

* 定时执行方法
new Timer() 或 Executors.newScheduledThreadPool(2)

* 注入循环
@Autowired 注入会存在循环,虽然spring已经做了处理,但对象是无限嵌套的

* 对象方法重写
User user = new User(){
      @Override
      public String get Name(){
           return "abc";
      }
}

* 钩子函数,JVM退出时调用
Runtime.getRuntime().addShutdownHook(thread);

* 泛型类返回类型指定
class UserBuilder<T>{}
//两步式
UserBuilder<String> build = User.create();
User u = build.name("").age(12).build();
//一步式
UserBuilder.<Abc>create();

* 修改bean属性
implements BeanPostProcessor

* 利用无参方法进行初始化
@Component    会调无参方法

* 详细异常
e.getMessage()   获取下层异常信息
e.getCause().getLocalizedMessage()   获取底层异常e

* new抽象类
new AbstractUser(){};    //实例化抽象类, 必须有实现, 相当于继承的子类

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值