一、Map
1. Map与HashMap
java.util.Map 查找表
Map体现的结构是一个多行两列的表格,左列称为key,右列称为value。
Map总是以key-value对的形式保存数据,并根据key提取value。
在Map中key是不允许重复的(equals判断)。
Map是一个接口,规定了Map所有功能对应的方法定义,其中常用的实现类: java.util.HashMap:散列表(哈希表),使用散列算法实现的Map,当今查询速度最快的数据结构。在缓存中被大量应用。
public class MapDemo {
public static void main(String[] args) {
Map map = new HashMap<>();
Integer value = map.put("语文",99);//新的key不会替换元素,返回值为null
System.out.println(value);
map.put("数学",98);
map.put("英语",97);
map.put("物理",96);
map.put("化学",99);
System.out.println(map);
value = map.put("数学",77);//将数学原有的98替换并返回
System.out.println(map);
System.out.println(value);
value = map.get("英语");
System.out.println(value);
value = map.get("体育");
System.out.println(value);
int size = map.size();
System.out.println("size:"+size);
value = map.remove("英语");
System.out.println(map);
System.out.println(value);
boolean ck = map.containsKey("语文");
boolean cv = map.containsValue(94);
System.out.println("包含key:"+ck);
System.out.println("包含value:"+cv);
}
}
java.util.Map 查找表
Map体现的结构是一个多行两列的表格,左列称为key,右列称为value。
Map总是以key-value对的形式保存数据,并根据key提取value。
在Map中key是不允许重复的(equals判断)。
Map是一个接口,规定了Map所有功能对应的方法定义,其中常用的实现类: java.util.HashMap:散列表(哈希表),使用散列算法实现的Map,当今查询速度最快的数据结构。在缓存中被大量应用。
public class MapDemo {
public static void main(String[] args) {
Map map = new HashMap<>();
Integer value = map.put("语文",99);//新的key不会替换元素,返回值为null
System.out.println(value);
map.put("数学",98);
map.put("英语",97);
map.put("物理",96);
map.put("化学",99);
System.out.println(map);
value = map.put("数学",77);//将数学原有的98替换并返回
System.out.println(map);
System.out.println(value);
value = map.get("英语");
System.out.println(value);
value = map.get("体育");
System.out.println(value);
int size = map.size();
System.out.println("size:"+size);
value = map.remove("英语");
System.out.println(map);
System.out.println(value);
boolean ck = map.containsKey("语文");
boolean cv = map.containsValue(94);
System.out.println("包含key:"+ck);
System.out.println("包含value:"+cv);
}
}
2. Map的遍历
Map提供了三种遍历方式:
1:遍历所有的key
2:遍历每一组键值对
3:遍历所有的value(相对不常用)
public class MapDemo2 {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("语文",99);
map.put("数学",98);
map.put("英语",97);
map.put("物理",96);
map.put("化学",99);
System.out.println(map);
Set keySet = map.keySet();
for(String key : keySet){
System.out.println("key:"+key);
}
Set> entrySet = map.entrySet();
for(Map.Entry entry : entrySet){//遍历每一组键值对
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+":"+value);
}
Collection values = map.values();
for(Integer value : values){
System.out.println("value:"+value);
}
Collection c = new ArrayList<>();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
for(String s : c){
System.out.println(s);
}
c.forEach( s -> System.out.println(s) );
map.forEach((k,v)-> System.out.println(k+":"+v));
}
}
二、反射机制
1. Java反射机制
Map提供了三种遍历方式:
1:遍历所有的key
2:遍历每一组键值对
3:遍历所有的value(相对不常用)
反射机制是java的动态机制,可以在程序"运行期间"再确定实例化对象,方法调用,属性操作等。
反射机制可以提高代码的灵活度,但是会带来较多的系统开销和较低的运行效率,因此不能过度依赖。
Class类
Class类称为类的类对象。
JVM加载一个类的class文件时,就会创建一个Class实例与该类绑定。因此每个被加载的 类都有且只有一个Class实例,这个实例就是该加载的类的类对象。
通过一个类的类对象我们可以获取这个类的一切信息(类名,属性,方法,构造器等)从而在 程序运行期间进行相关的操作 因此反射第一步就是要获取操作的类的类对象。而获取方式有三种:
1:类名.class Class cls = String.class; Class cls = int.class;
2:Class.forName(String className) Class cls = Class.forName("java.lang.String");//参数需要是完全限定名:包名.类名 注意:基本类型不支持此种方式获取类对象
3:ClassLoader类加载器形式获取
public static void main(String[] args) throws ClassNotFoundException {
//获取String的类对象
// Class cls = String.class;
// Class cls = ArrayList.class;
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要加载的类的名字:");
String className = scanner.nextLine();
Class cls = Class.forName(className);
String name = cls.getName();//获取完全限定名:包名.类名
System.out.println(name);
name = cls.getSimpleName();//仅获取类名
System.out.println(name);
String packageName = cls.getPackage().getName();
System.out.println("包名:"+packageName);
//获取String类的所有公开方法(包含从超类继承的方法)
//获取本类自己定义的方法(包含私有方法)
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods){
System.out.println(method.getName());
}
}
2. 使用反射机制实例化对象
使用反射机制实例化对象:
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
ArrayList list = new ArrayList();
System.out.println(list);
//1获取要实例化对象的类的类对象
// Class cls = Class.forName("java.util.ArrayList");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
Class cls = Class.forName(className);
//2调用Class的newInstance()来调用无参构造器
Object obj = cls.newInstance();
System.out.println(obj);
}
使用指定的构造器实例化对象:
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Person p = new Person("李四",33);
System.out.println(p);
//1加载类对象
Class cls = Class.forName("reflect.Person");
//2通过类对象获取指定的有参构造器:Person(String,int)
// Constructor c = cls.getConstructor();//不传参获取的就是无参构造器
Constructor c = cls.getConstructor(String.class,int.class);
Object obj = c.newInstance("王五",66);//new Person("王五",66);
System.out.println(obj);
}
3. 利用反射机制调用方法
利用反射机制调用方法:
public static void main(String[] args) throws Exception {
Person p = new Person();
p.watchTV();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入类名:");
String className = scanner.nextLine();
System.out.println("请输入方法名:");
String methodName = scanner.nextLine();
//1实例化
//1.1加载类对象
// Class cls = Class.forName("reflect.Person");
Class cls = Class.forName(className);
//1.2实例化
Object obj = cls.newInstance();//Object obj = new Person();
//2调用方法
//2.1通过类对象获取要调用的方法
// Method method = cls.getMethod("watchTV");
Method method = cls.getMethod(methodName);
//2.2通过方法对象执行该方法
method.invoke(obj);//obj.watchTV() 前提是obj表示的是一个Person对象
}
利用反射机制调用有参方法:
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Object obj = cls.newInstance();
//public void say(String info){
Method method = cls.getMethod("say",String.class);
method.invoke(obj,"你好!");//p.say("你好!");
//public void say(String info,int count){
Method method2 = cls.getMethod("say",String.class,int.class);
method2.invoke(obj,"Hello",5);//p.say("Hello",5)
}
三、注解
1. 注解
注解被大量应用与反射中,可以辅助反射机制做更多灵活的操作。后期使用的框架基本都是使用注解进行配置的。
在注解上我们有两个常用的注解用来说明当前注解的相关特性:
@Target:用于说明我们定义的注解可以被应用到哪里。
该注解可以传递的参数为ElementType类型,用来表示可标注的位置。
常见的有:ElementType.TYPE:在类上用
ElementType.METHOD:在方法上
ElementType.FIELD:在属性上用
如果不指定@Target,则当前注解可以被应用在任何注解可使用的位置上。
@Retention:当前注解的保留级别,有三个可选值
RetentionPolicy.SOURCE:当前注解仅保留在源代码中,编译后的字节码文件中没有该注解
RetentionPolicy.CLASS:保留到编译后的字节码文件中,但是反射机制不可访问
RetentionPolicy.RUNTIME:保留到字节码中且反射机制可以访问
不指定时,默认保留级别为CLASS
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRunClass {
}
2. 注解中定义参数的语法
3. 反射机制访问注解注解中定义参数的语法:
类型 参数名() [default 默认值];
注:[]中的内容可写,可不写。
如果当前注解只有一个参数时,那么参数名应当叫value。
此时当我们在外面使用该注解时,可以使用:
@AutoRunMethod(3) 进行传参。此时注解中value的值为3
如果该参数名不叫value,例如,定义时如下:
public @interface AutoRunMethod{
int num();
}
此时当我们在外面使用该注解时,可以使用:
@AutoRunMethod(num=3)
语法要求:传参时格式为:参数名=参数值
进行传参。此时注解中num的值为3
只有参数名叫value时,传递参数才可以将参数名忽略。
以上特性仅限于只有一个参数时。
当有多个参数时,例如,定义时如下:
public @interface AutoRunMethod{
int value(); String name();
}
使用注解传递参数时,参数名都不可以忽略,必须写为name=value的格式,且顺序无所谓。
例如:
@AutoRunMethod(value=1,name="张三")
@AutoRunMethod(name="张三",value=1)
以上都正确
参数可以使用default指定默认值,那么在使用注解时。可以不指定该参数的值,此时使用默认值
public @interface AutoRunMethod{
int value() default 1;
}
使用该注解时:
@AutoRunMethod(3)
此时value的值为3
@AutoRunMethod
此时value的值为1(默认值)
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
//cls所表示的类Person是否被注解@AutoRunClass标注过
boolean flag = cls.isAnnotationPresent(AutoRunClass.class);
if(flag){
System.out.println("被标注了!");
}else{
System.out.println("没有被标注!");
}
}
4.获取注解中的参数
public static void main(String[] args) throws Exception {
Class cls = Class.forName("reflect.Person");
Method method = cls.getMethod("sayHello");
if(method.isAnnotationPresent(AutoRunMethod.class)){
//获取该方法上的注解@AutoRunMethod
AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);
//通过注解对象获取value参数的值
int value = arm.value();
System.out.println(value);
}
}
四、线程池
线程池是线程的管理机制,主要解决两方面问题:
1:控制线程的数量
2:重用线程
public class ThreadPoolDemo {
public static void main(String[] args) {
//创建一个2线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for(int i=0;i<5;i++){
Runnable r = new Runnable() {
public void run() {
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在执行任务...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t.getName()+":执行任务完毕!");
}
};
threadPool.execute(r);//将任务指派给线程池
}
}
}
总结
本篇的内容为Java的Map集合、Java的反射机制、注解、线程池的知识点等。



