自动装箱与拆箱
基本类与包装类对应关系:
包装类型转基本类型:
基本类型转包装类型:
自动装箱,自动拆箱:
Integer i = 11;//自动装箱,实际上执行了Integer i = Integer.valueOf(11);
int t = i;//自动拆箱,实际上执行了 int t = i.intValue();
参考:https://baijiahao.baidu.com/s?id=1579601823966912111&wfr=spider&for=pc
枚举
package pers.terry.demo.jdk.jdk5;
public class EnumDemo {
// 无带参构造
public enum TrafficLamp {
RED, GREEN, YELLW;
}
// 提供带参构造
public enum TrafficLamp2 {
RED(30), GREEN(40), YELLW(5);
private int time;
private TrafficLamp2(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
// 提供带参构造,并有抽象方法
public enum TrafficLamp3 {
RED(30) {
@Override
public TrafficLamp3 nextLamp() {
return TrafficLamp3.GREEN;
}
},
GREEN(40) {
@Override
public TrafficLamp3 nextLamp() {
return TrafficLamp3.YELLW;
}
},
YELLW(5) {
@Override
public TrafficLamp3 nextLamp() {
return TrafficLamp3.RED;
}
};
private int time;
private TrafficLamp3(int time) {
this.time = time;
}
public int getTime() {
return time;
}
// 提供一个抽象方法,用于获取下个灯
public abstract TrafficLamp3 nextLamp();
}
public static void main(String[] args) {
System.out.println(TrafficLamp.GREEN);
System.out.println(TrafficLamp2.GREEN);
System.out.println(TrafficLamp2.GREEN.getTime());
System.out.println(TrafficLamp3.GREEN);
System.out.println(TrafficLamp3.GREEN.nextLamp());
}
}
参考:https://blog.youkuaiyun.com/kongqis/article/details/47315653
静态导入
可以直接导入到方法的级别,方法必须是静态的
格式:import static 包名….类名.方法名;
package pers.terry.demo.jdk.jdk5.importStatic;
public class ImportStatic01 {
public static String staticMethod(String say) {
return "say:" + say;
}
}
package pers.terry.demo.jdk.jdk5.importStatic;
import static pers.terry.demo.jdk.jdk5.importStatic.ImportStatic01.staticMethod;
public class ImportStatic02 {
public static void main(String[] args) {
System.out.println(staticMethod("terry"));
}
}
可变参数(Varargs)
定义方法的时候不知道该定义多少个参数
格式: 修饰符 返回值类型 方法名(数据类型… 变量名){ }
注意: 这里的变量其实是一个数组,如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
package pers.terry.demo.jdk.jdk5.varargs;
public class VarargsDemo {
public static int sum(int... a) {
System.out.println("a:"+a); //a是一个数组
int s = 0;
for (int x : a) {
s += x;
}
return s;
}
public static void main(String[] args) { // 2个数据求和
int a = 10;
int b = 20;
int c = 30;
int d = 30;
int result = sum(a, b);
System.out.println("result:" + result);
result = sum(a, b, c);
System.out.println("result:" + result);
result = sum(a, b, c, d);
System.out.println("result:" + result);
result = sum(a, b, c, d, 40);
System.out.println("result:" + result);
result = sum(a, b, c, d, 40, 50);
System.out.println("result:" + result);
}
}
参考:https://blog.youkuaiyun.com/gafeng123456/article/details/50764876
内省(Introspector)
主要用于操作JavaBean中的属性,通过getXxx/setXxx。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
Introspector.getBeanInfo()方法,得到的BeanInfo对象,BeanInfo的getPropertyDescriptors(),获得属性的描述PropertyDescriptor数组。PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
1. getPropertyType(),获得属性的Class对象;
2. getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法;
3. hashCode(),获取对象的哈希值;
4. setReadMethod(Method readMethod),设置用于读取属性值的方法;
5. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。
6 getName, 获取属性名
package pers.terry.demo.jdk.jdk5.introspector;
public class User {
private String name;
private String address;
public User() {
}
public User(String name, String address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
private String say(String words) {
return "say:" + words;
}
}
package pers.terry.demo.jdk.jdk5.introspector;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Arrays;
public class IntrospectorDemo {
public static void main(String[] args) throws Exception {
final User user = new User();
user.setName("nana");
user.setAddress("hangzhou");
//如果不想把父类的属性也列出来的话,那getBeanInfo的第二个参数填写父类的信息
BeanInfo beanInfo = Introspector.getBeanInfo(user.getClass(), Object.class);
PropertyDescriptor[] descriptor = beanInfo.getPropertyDescriptors();
Arrays.stream(descriptor).forEach(x -> {
try {
System.out.println(x.getName() + " before: " + x.getReadMethod().invoke(user));
x.getWriteMethod().invoke(user, "suzhou");
System.out.println(x.getName() + " after: " + x.getReadMethod().invoke(user));
} catch (ReflectiveOperationException e) {
e.getLocalizedMessage();
}
});
}
}
结果如下:
address before: hangzhou
address after: suzhou
name before: nana
name after: suzhou
参考:https://www.jianshu.com/p/086ba5cd3704
补充:
通过反射可以获得所有属性、构造方法的信息,和执行所有方法(包括private)。
package pers.terry.demo.jdk.jdk5.introspector;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
public class ReflexDemo {
public static void testField(Class<?> clazz) {
//getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
// Field[] fields = clazz.getFields();
Field[] fields = clazz.getDeclaredFields();
if (fields != null) {
for (Field field : fields) {
System.out.println(field.getModifiers() + " " + field.getType() + " " + field.getName());
}
}
}
public static void testConstructor(Class<?> clazz) {
// Constructor<?>[] constructors = clazz.getConstructors();
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
if (constructors != null) {
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName() + "**" + constructor.getParameterTypes());
}
}
}
public static void testMethod(Class<?> clazz) {
// Method[] methods = clazz.getMethods();
Method[] methods = clazz.getDeclaredMethods();
if (methods != null) {
for (Method method : methods) {
String methodName = method.getName();
Class<?>[] paramTypes = method.getParameterTypes();
System.out.println("methodName=" + methodName + "**params=" + Arrays.toString(paramTypes));
if ("say".equals(methodName)) { //say 方法是 private类型的
try {
method.setAccessible(true); //暴力破解
Object result = method.invoke(clazz.getDeclaredConstructor().newInstance(), new Object[]{"haha"});
System.out.println(methodName + " invoke result=" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
testField(User.class);
testConstructor(User.class);
testMethod(User.class);
}
}
输出:
2 class java.lang.String name
2 class java.lang.String address
pers.terry.demo.jdk.jdk5.introspector.User**[Ljava.lang.Class;@6e2c634b
pers.terry.demo.jdk.jdk5.introspector.User**[Ljava.lang.Class;@37a71e93
methodName=getName** params=[]
methodName=setName** params=[class java.lang.String]
methodName=getAddress** params=[]
methodName=say** params=[class java.lang.String]
say invoke result=say:haha
methodName=setAddress**params=[class java.lang.String]
参考:https://blog.youkuaiyun.com/top_code/article/details/40784093
泛型(Generic)
泛型的好处:
1)将运行时期异常提前到了编译时期
2)优化了设计,解决了黄色警告线问题
3)避免了强制类型转换
4)提高了程序的安全性!
注意:类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
- 将泛型定义在类上:解决了向下类型转换出现的问题:ClassCastException
package pers.terry.demo.jdk.jdk5.generic;
public class ObjectTool<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
public static void main(String[] args) {
//创建ObjectTool对象
ObjectTool<String> ot = new ObjectTool<>() ;
//赋值
ot.setObj("高圆圆");
String s = ot.getObj() ;
System.out.println("ot:"+s);
ObjectTool<Integer> ot2 = new ObjectTool<>() ;
ot2.setObj(Integer.valueOf(12));
System.out.println("ot2:"+ot2.getObj());
}
}
- 将泛型定义在方法上
package pers.terry.demo.jdk.jdk5.generic;
import pers.terry.demo.jdk.jdk5.introspector.User;
public class ObjectTool2 {
//泛型是可以在方法上定义的
public <T> T show(T t) {
System.out.println(t);
return t;
}
public static void main(String[] args) {
//创建ObjectTool类的对象
ObjectTool2 ot = new ObjectTool2();
ot.show("hello");
ot.show(true);
ot.show(100);
ot.show(new User());
}
}
- 将泛型定义在接口上
//将泛型定义在接口上
package pers.terry.demo.jdk.jdk5.generic;
public interface Inter<T> {
//接口中变量是常量: public static final int num ;
public abstract void show(T t) ; //抽象方法
}
package pers.terry.demo.jdk.jdk5.generic;
//第一种情况:指定接口泛型
public class InterImpl implements Inter<String> {
public static void main(String[] args) {
Inter<String> i = new InterImpl();
i.show("i");
}
@Override
public void show(String t) {
System.out.println("show:" + t);
}
}
package pers.terry.demo.jdk.jdk5.generic;
//第一种情况:不指定接口泛型
public class InterImpl2<T> implements Inter<T> {
public static void main(String[] args) {
Inter<String> i = new InterImpl2();
i.show("String");
Inter<Integer> i2 = new InterImpl2();
i2.show(2);
}
@Override
public void show(T t) {
System.out.println("show:" + t);
}
}
- 泛型高级(通配符)
<?>:代表任意类型Object类型,或者任意的Java类
<? super E>:向上限定,E及其他的父类
<? extends E>:向下限定,E的子类或者E这个类型
class Animal{
}
class Cat extends Animal {
}
class Dog extends Animal{
}
public static void main(String[] args) {
//创建集合对象,泛型如果明确的情况下,前后必须保持一致
Collection<Object> c1 = new ArrayList<Object>() ;
// Collection<Object> c2 = new ArrayList<Cat>() ;//错误
// Collection<Object> c3 = new ArrayList<Animal>() ;//错误
//<?> :代表任意类型Object类型,或者任意的Java类
Collection<?> c4 = new ArrayList<Object>() ;
Collection<?> c5 = new ArrayList<Animal>() ;
Collection<?> c6 = new ArrayList<Dog>() ;
Collection<?> c7= new ArrayList<Cat>() ;
// <? extends E>:向下限定,E的子类或者E这个类型
Collection<? extends Object> c8 = new ArrayList<Object>() ;
Collection<? extends Object> c9 = new ArrayList<Animal>() ;
Collection<? extends Object> c10 = new ArrayList<Cat>() ;
// Collection<? extends Aninal> c11 = new ArrayList<Object>() ;//错误
// <? super E>:向上限定,E及其他的父类
// Collection<? super Animal> c12 = new ArrayList<Cat>() ;//错误
Collection<? super Animal> c13 = new ArrayList<Animal>() ;
Collection<? super Animal> c14 = new ArrayList<Object>() ;
}
参考:https://blog.youkuaiyun.com/xing_ran_ran/article/details/80426642
For-Each循环
高级ForEach()是一种高级技术,它必须有遍历的目标,该目标要么是Arrays数组,要么是集合Collection单列集合,格式:
for(类型 变量:集合or数组){
sysop();//输出语句
}
//遍历集合
List<String> list =new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
for(String s : list){
System.out.println(s);
}
//遍历map
Map<Integer,String> map=new HashMap<Integer,String >();
map.put(3,"zhagsan");
map.put(1,"wangyi");
map.put(7,"wagnwu");
map.put(4,"zhagsansan");
//直接对mapforEach
for(Map.Entry<Integer,String> me:map.entrySet()){
Integer key=me.getKey();
String value=me.getValue();
System.out.println(key+":"+value);
}
//对key forEach,再取value
for(Integer key:map.keySet()){
String value=map.get(key);
System.out.println(key+":"+value);
}
参考:https://blog.youkuaiyun.com/zhanshixiang/article/details/82751759
注解
- 基本内置注释(JDK5.0自带的)
1) Override 注释能实现编译时检查,你可以为你的方法添加该注释,以声明该方法是用于覆盖父类中的方法。如果该方法不是覆盖父类的方法,将会在编译时报错。例如我们为某类重写toString() 方法却写成了tostring() ,并且我们为该方法添加了@Override 注释,那么编译是无法通过的。
2)Deprecated 的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc 里的 @deprecated 标记有相同的功能。
3)SuppressWarnings 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数值都是已经定义好了的,我们选择性的使用就好了,参数如下:
- unused 没有被访问过的元素,去除警告。
- deprecation 使用了过时的类或方法时的警告
- unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型
- fallthrough 当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
- path 在类路径、源文件路径等中有不存在的路径时的警告
- serial 当在可序列化的类上缺少 serialVersionUID 定义时的警告
- finally 任何 finally 子句不能正常完成时的警告
- all 关于以上所有情况的警告
- 自定义注释类型
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface Greeting {
public enum FontColor {RED, GREEN, BLUE}
String title();
String content();
FontColor fontColor() default FontColor.RED;
}
@Greeting(title = "健康", content = "你最近身体好吗", fontColor = Greeting.FontColor.BLUE)
public static void sayHello(String name) {
}
参考:https://blog.youkuaiyun.com/xiaomageit/article/details/48695595
协变返回类型
子类overRide父类方法时,实际返回类型可以是要求的返回类型的一个子类型