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(){}; //实例化抽象类, 必须有实现, 相当于继承的子类
JAVA常见知识点
于 2023-12-30 21:19:17 首次发布