泛型
泛型
泛型接口
interface Demo_inter<T>{
T getVal();
}
class Demo_inter_1<T> implements Demo_inter<T>{
T val;
public void setVal(T val) {
this.val = val;
}
@Override
public T getVal() {
return val;
}
}
class Demo_inter_2 implements Demo_inter<String>{
String val;
@Override
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
}
Demo_inter_1<String> di1=new Demo_inter_1<String>();
di1.setVal("123");
System.out.println(di1.getVal());
Demo_inter_2 di2=new Demo_inter_2();
di2.setVal("234");
System.out.println(di2.getVal());
泛型方法
public static <T extends Number> _Num<T> get_Num(T t){
_Num<T> temp=new _Num<T>(t);
return temp;
}
只需要在使用泛型的时候呢,声明一下,然后通过函数的输入决定泛型的类型
泛型数组
我们用可变参数为例子
泛型嵌套
_嵌套_实现<_嵌套_base<Integer,String>> th=new _嵌套_实现<_嵌套_base<Integer,String>>(new _嵌套_base<Integer,String>(12,"asd"));
这里 _嵌套_base<Integer,String> 指定为 _嵌套_实现 的泛型的类型了
枚举
enum Color{
Red,White,Blue;
}
enum实际上是继承了Enum 构造方法 Enum(String name, int ordinal)
上面的语句实际上就是条用了这个构造方法
String name()
返回此枚举常量的名称,在其枚举声明中对其进行声明。
int ordinal()
返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
Class类
这里用到反射机制,通过实例就可以获得他的类信息
Class类构造方法私有化
实例化方法
- Class.forName()
- 类.class
- 实例.getclass()
class类用来实例化对象
但是对象必须是有无参的构造方法
//Class来实例化对象
try {
c c_instance= (c) c1.newInstance();
c_instance.setName("lz");
System.out.println(c_instance.toString());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
当没有无参的构造方法的时候
//不存在无参数的构造方法怎么处理
try {
Class <?> c4=Class.forName("基础.c1");
Constructor<?> constructor[]=c4.getConstructors();
c1 ccc= (基础.c1) constructor[0].newInstance(123);
System.out.println(ccc.x);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
class获得类的结构
实现的全部接口
Class<?> inter[]=c5.getInterfaces();
for (int i = 0; i < inter.length; i++) {
System.out.println(inter[i].getName());
}
获得父类
Class<?> fatther=c5.getSuperclass();
System.out.println(fatther.getName());
获得构造方法
Constructor<?>[] constructor=c5.getConstructors();
StringBuffer sb=new StringBuffer();
for (int i = 0; i < constructor.length; i++) {
sb.append(Modifier.toString(constructor[i].getModifiers())+" ");
sb.append(constructor[i].getName()+"(");
Class <?> para[]=constructor[i].getParameterTypes();
for (int j = 0; j < para.length; j++) {
sb.append(para[j]);
if(j+1!=para.length){
sb.append(",");
}
else
sb.append(")");
}
System.out.println(sb);
}
Constructor类,可以单独获得构造方法的修饰符,名称参数等等
Modifier类,指定标识符的类型
获得方法
Method类,取得跟方法有关的相关信息
Method []declaredMethod=c5.getDeclaredMethods();
for (int i = 0; i < declaredMethod.length; i++) {
sb.append(Modifier.toString(declaredMethod[i].getModifiers())+" ");
sb.append(declaredMethod[i].getName()+"(");
Class<?>[] para=declaredMethod[i].getParameterTypes();
for (int j = 0; j < para.length; j++) {
sb.append(para[j].getName());
if(j+1!=para.length){
sb.append(",");
}
}
sb.append(")");
System.out.println(sb);
sb.delete(0,sb.length());
}
Class.getDeclaredMethods 获得本类中定义的方法
Class.getMethods() 获得所有方法,包括父类中的
获得属性
Field []field=c5.getDeclaredFields();
利用反射直接调用方法
Class<?> c6=Class.forName("基础.c");
Method m1=c6.getMethod("print",String.class);
m1.invoke(c6.newInstance(),"中国");
Method m2=c6.getMethod("print",String.class,int.class);
String ret=(String) m2.invoke(c6.newInstance(),"中国",43);
System.out.println(ret);
这里调用了invoke函数来执行Method
通过反射改变属性
Object obj=c6.newInstance();
Field nameField=c6.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set((c)obj,"lz");
Field ageField=c6.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set((c)obj,12);
这样就不需要set和get方法了,而且对于私有的属性只要setAccessible为true就可以访问修改了
这就是说Class类可以获得一个类中的全部所有的信息,包括创建这个类的实例,并且在这个实例上面去操作属性/方法等
通过反射处理数组
可变参数
public static void main(String[] args) {
fun("1223","13","123123");
fun("w");
fun(123,"asd","22e");
}
public static void fun(String...args){
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
public static void fun(int x,String...args){
System.out.println(x);
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
所谓的可变参数就是一个动态的数组,注意
- 只能有一个参数是可变参数
- 可变参数必须是参数表的最后一个
- 注意在重载的时候不要发生冲突,导致jvm不知道应该去执行哪一个函数
区分 正斜杠/ 反斜杠\
在java里面 /就是一个普通的字符,作用大概就是注释,文件路径之类
\用来转义,因此"\"才代表一个\
转移比较容易理解,但是在正则表达式的应用场合就比较难受,例如
String s ="sdf\\a\\aa";
//把s中的反斜杠\ 替换为\\
方法1
System.out.println(s.replaceAll("\\\\", "\\\\\\\\"));
这里按照正则表达式处理,"\\"首先认为是字符串,实际的值就是"\",然后正则表达式转义就是\,同理后面的8个\就变成了"\\"
方法2
System.out.println(s.replace("\\", "\\\\"));
这里就是简单的模式匹配,没有调用到正则表达式,也就少了一层转义。
就是说如果没有用到正则表达式的话,就没有必要进行两次转义的操作了
Annotation
系统内建的
-
@Override
- 重写
-
@Deprecated
- 已经过时
-
@SuppressWarnings()
- 压制警告
自定义的Annotation
//无参数的
@interface Annotation01 {}
//有参数
@interface Annotation02{
public String value();
}
//多参数
@interface Annotation03{
public String value();
public String key();
}
//数组
@interface Annotation04{
public String[] value();
}
//默认值的
@interface Annotation06{
public String value() default "name";
}
//枚举类型
@interface Annotation07{
public This value() default This.Blue;
}
调用
@Annotation02("lz");
@Annotation03(key="lz",value="123");
@Annotation04(value={"1","2","3"});
@Annotation07(This.White);
@Retention,用来指定自定义的Annotation的作用范围,修饰Annotation
@Retention(RetentionPolicy.RUNTIME)表示在运行时有效
RetentionPolicy.SOURCE 只对源码有效
RetentionPolicy.CLASS 加载到Class类中
Target,用来指定自定义的Annotation的使用的位置(比如只能在构造方法上使用等)