- 1.关于Object类中的wait和notify方法(生产者和消费者模式)
- 2.反射机制概述
- 1)反射机制有什么用?
- 2)反射机制的相关类在哪个包下?
- 3)反射机制的相关重要的类有哪些?
- 3.获取Class的三种方式
- 4.通过反射实例化对象
- 5.通过读属性文件实例化对象
- 6.Class.forName()可以只让静态代码块执行!
- 7.获取类路径下文件的绝对路径
- 8.以流的形式直接返回(路径)
- 9.资源绑定器
- 10.反射Field
- 11.通过反射机制访问对象属性(重点)
- 12.可变长度参数
- 13.反射Method
- 14.通过反射机制调用方法(重点)
- 15.反射Constructor
- 16.通过反射机制调用构造方法
- 17.获取父类和父接口
第一:wait和notify方法不是线程对象的方法,是java任何一个java对象都有的方法,因为这两个方式是Object类中自带的。
wait方法和notify方法不是通过线程对象调用。
不是这样: t.wait(),也不是这样的:t.notify()
第二:wait()方法作用?
Object o=new Object();
o.wait();
表示:
让正在o对象上活动的线程进入等待状态,无期限等待。
直到被唤醒为止。
o.wait():方法的调用,会让"当前线程(正在o对象上活动的线程)"进入等待状态。
第三:notify()方法作用?
Object o=new Object();
o.notify();
表示:
唤醒正在o对象上等待的线程。
还有一个notifyAll()方法:
这个方法是唤醒o对象上处于等待状态的所有线程。
第四:
wait和notify方法建立在synchronized线程同步的基础之上。
o.wait()方法会让正在o对象上活动的当前线程进入等待状态,并且释放之前占有的o对象的锁。
o.notify()方法只会通知,不会释放之前占有的对象的锁。
模拟生产者和消费者模式
package com.jmpower.javase.thread;
import java.util.ArrayList;
import java.util.List;
public class ThreadTest14 {
public static void main(String[] args) {
//创建一个仓库对象,共享的。
List list=new ArrayList();
//创建两个线程对象
//生产者线程
Thread t1=new Thread(new Producer(list));
//消费者线程
Thread t2=new Thread(new Costumer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
class Producer implements Runnable{
//仓库
private List list;
public Producer(List list) {
this.list = list;
}
@Override
public void run() {
//一直生产(使用死循环来模拟一直生产)
while(true) {
//对仓库对象list加锁
synchronized (list){
if(list.size()>0){//大于0,表示仓库中已经有一个元素了
try {
//当前线程进入等待状态,并且释放Producer之前占有的list集合的锁。
list.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//线程能执行到这里说明仓库是空的,可以生产
Object obj=new Object();
list.add(obj);
System.out.println(Thread.currentThread().getName()+"--->"+obj);
//唤醒消费者进行消费
list.notify();
}
}
}
}
class Costumer implements Runnable{
//仓库
private List list;
public Costumer(List list) {
this.list = list;
}
@Override
public void run() {
//一直消费
while(true){
synchronized (list){
if(list.size()==0){
try {
//仓库空了,消费者线程进入等待,释放list集合的锁
list.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//程序能够执行到这里说明仓库中有数据,进行消费
Object obj=list.remove(0);
System.out.println(Thread.currentThread().getName()+"--->"+obj);
//唤醒生产线程进行生产
if(list.size()==0) list.notify();
}
}
}
}
2.反射机制概述
1)反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。
有点类似于黑客。(可以读和修改字节码文件)
通过反射机制可以操作字节码片段。(class文件)
java.lang.reflect.*;
3)反射机制的相关重要的类有哪些?java.lang.Class: 代表整个字节码,表示一个类型,代表整个类。
java.lang.reflect.Method: 代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor: 代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field: 代表字节码中的属性字节码。代表类中的成员变量(静态变量和成员变量)。
java.lang.Class:
public class User{
//Field
int no;
//Constructor
public User(){
}
public User(int no){
this.no=no;
}
//Method
public void doSome(){
}
3.获取Class的三种方式
三种方式:
第一种: Class c=Class.forName(“完整类名带包名”);
第二种: Class c=对象.getClass();
第三种: Class c=任何类型.class;
package com.jmpower.javase.reflect;
import java.util.Date;
public class ReflectTest01 {
public static void main(String[] args) {
Class c1=null;
Class c2=null;
try {
c1=Class.forName("java.lang.String");//c1代表String.class文件,或者说c1代表String类
c2=Class.forName("java.util.Date");//c2代表Date类
Class c3=Class.forName("java.lang.Integer");//c3代表Integer类型
Class c4=Class.forName("java.lang.System");//c4代表System类型
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//java种任何一个对象都有一个方法: getClass()
String s="abc";
Class x=s.getClass();
System.out.println(x);//x代表String.class字节码文件,x代表String类型
System.out.println(c1==x);//true(==判断的是对象的内存地址)
Date time=new Date();
Class y=time.getClass();
System.out.println(c2==y);//true(c2和y两个变量种保存的内存地址都是一样的,都指向方法区中的字节码文件)
//第三种方式: java语言种任何一种类型,包括基本数据类型,他都有.class属性
Class z=String.class;//z代表String类型
Class k=Date.class;//k代表Date类型
Class e=int.class;//e代表int类型
Class d=Double.class;//d代表Double类型
System.out.println(x==z);//true
System.out.println(d);
}
}
4.通过反射实例化对象
package com.jmpower.javase.reflect;
import com.jmpower.javase.bean.User;
public class ReflectTest02 {
public static void main(String[] args) {
//这是不使用反射机制,创建对象
User user=new User();
System.out.println(user);
//下面是使用反射机制创建对象
try {
//通过反射机制,获取Class,通过Class来实例化对象
Class c=Class.forName("com.jmpower.javase.bean.User");
//newInstance()方法会调用User这个类的无参数构造方法,来完成对象的创建
//重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
Object obj=c.newInstance();
System.out.println(obj);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
5.通过读属性文件实例化对象
package com.jmpower.javase.reflect;
import java.io.FileReader;
import java.util.Properties;
public class ReflectTest03 {
public static void main(String[] args) throws Exception {
//这种方式代码就写死了,只能创建一个User类型的对象。
//User user=new User();
//以下代码是灵活的,代码不需要改动,可以修改配置文件,配置文件修改之后,可以创建出不同的实例对象
//通过IO流读取class.properties文件
FileReader reader=new FileReader("C:\Users\Jm\IdeaProjects\untitled47\class.properties");
//创建属性类对象Map
Properties pro=new Properties();
//加载
pro.load(reader);
//关闭流
reader.close();
//通过key获取value对象
String className=pro.getProperty("className");
//System.out.println(className);
//通过反射机制实例化对象
Class c=Class.forName(className);
Object obj=c.newInstance();
System.out.println(obj);
}
}
6.Class.forName()可以只让静态代码块执行!
package com.jmpower.javase.reflect;
public class ReflectTest04 {
public static void main(String[] args) {
try {
//class.forName()这个方法执行会导致: 类加载
Class.forName("com.jmpower.javase.reflect.MyClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class MyClass {
static {
System.out.println("类加载,进行静态代码块");
}
}
7.获取类路径下文件的绝对路径
package com.jmpower.javase.reflect;
public class AboutPath {
public static void main(String[] args) {
//这种方式的路径缺点是:移植性差,在IDEA中默认的当前路径是project的根。
//这个代码假设离开了IDEA,换到了其他位置,可能当前路径就不是project的根了,这时这个
//FileReader reader=new FileReader("");
//接下来说一种比较通用的一种路径。即使代码换位置了,就这样编写依然是通用的。
//注意: 使用以下通用的方式的前提是: 这个文件必须在类路径下。
//什么类路径下?方式在src下的都是类路径下。
//src是类的根路径。
String path=Thread.currentThread().getContextClassLoader()
.getResource("class.properties").getPath();//这种方式获取文件绝对路径是通用的。
//采用以上的代码可以拿到一个文件的绝对路径。
///C:/Users/Jm/IdeaProjects/untitled45/out/production/untitled47/class.properties
System.out.println(path);
//获取db.properties文件的绝对路径(从类的根路径下作为起点开始)
String path2=Thread.currentThread().getContextClassLoader()
.getResource("com/jmpower/javase/reflect/db.properties").getPath();
System.out.println(path2);
}
}
8.以流的形式直接返回(路径)
package com.jmpower.javase.reflect;
import java.io.InputStream;
import java.util.Properties;
public class IoPropertiesTest {
public static void main(String[] args) throws Exception {
//获取一个文件的绝对路径!!!
InputStream reader=Thread.currentThread().getContextClassLoader()
.getResourceAsStream("class.properties");
Properties pro=new Properties();
pro.load(reader);
//通过key获取value
String className=pro.getProperty("className");
System.out.println(className);
}
}
9.资源绑定器
package com.jmpower.javase.reflect;
import java.util.ResourceBundle;
public class ResourceBundleTest {
public static void main(String[] args) {
//资源绑定器,只能绑定xxx.properties文件。并且这个文件必须在类路径下。文件扩展名也必须是properties
//并且在写路径的时候,路径后面的扩展名不能写。
ResourceBundle bundle=ResourceBundle.getBundle("com/jmpower/javase/reflect/db");
String className=bundle.getString("className");
System.out.println(className);
}
}
10.反射Field
package com.jmpower.javase.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest05 {
public static void main(String[] args) throws Exception{
//获取整个类
Class studentClass=Class.forName("com.jmpower.javase.bean.Student");
String className=studentClass.getName();
System.out.println("完整类名: "+className);
String simpleName=studentClass.getSimpleName();
System.out.println("简类名: "+simpleName);
//获取类中所有的public修饰的Field
Field[] fields=studentClass.getFields();
System.out.println(fields.length);//2
//取出这个Field
Field f=fields[0];
String fieldName=f.getName();
System.out.println(fieldName);
//获取类中所有的Field
Field[] fs=studentClass.getDeclaredFields();
System.out.println(fs.length);
System.out.println("====================================");
//遍历
for(Field field:fs){
//获取属性的修饰符列表
int i=field.getModifiers();//返回的修饰符是一个数字,每个数字是修饰符的代号!
//可以将这个"代号"数字转换成"字符串"吗?
String modifierString= Modifier.toString(i);
System.out.print(modifierString+" ");
//获取属性的类型
Class fieldType=field.getType();
//String fName=fieldType.getName();
String fName=fieldType.getSimpleName();
System.out.print(fName+" ");
//获取属性的名字
System.out.println(field.getName());
}
}
}
11.通过反射机制访问对象属性(重点)
package com.jmpower.javase.reflect;
import com.jmpower.javase.bean.Student;
import java.lang.reflect.Field;
public class ReflectTest06 {
public static void main(String[] args) throws Exception {
Student s=new Student();
//给属性赋值
s.no=1111;
//读取属性的值
System.out.println(s.no);
//使用反射机制,怎么去访问一个对象的属性。(set get)
Class studentClass=Class.forName("com.jmpower.javase.bean.Student");
Object obj=studentClass.newInstance();//obj就是Student对象(底层调用无参数构造方法)
//获取no属性(根据属性的名称来获取Field)
Field noField=studentClass.getDeclaredField("no");
//给obj对象(Student对象)的no属性赋值
noField.set(obj,2222);//给obj对象的no属性赋值2222
//读取obj对象的属性no的值
System.out.println(noField.get(obj));
//可以访问私有属性吗?
Field nameField=studentClass.getDeclaredField("name");
//打破封装(反射机制的特点: 打破封装,可能会给不法分子留下机会)
//这样设置之后,在外面也是可以访问private的
nameField.setAccessible(true);
//给name属性赋值
nameField.set(obj,"jackson");
//获取name属性的值
System.out.println(nameField.get(obj));
}
}
12.可变长度参数
package com.jmpower.javase.reflect;
public class ArgsTest {
public static void main(String[] args) {
m();
m(10);
m(10,20);
//编译报错
//m("abc");
m2(10);
m2(20,"a");
m2(20,"a","b");
m3("a");
m3("a","b");
m3("a","b","c");
String[] strs={"我","是","帅","哥"};
m3(strs);//没必要
m3("我","是","帅","哥");
}
public static void m(int... args){
System.out.println("m方法执行了!");
}
public static void m2(int a,String... args){
System.out.println("m2方法执行了!");
}
public static void m3(String... args){
//args有length属性,说明是一个数组!
//可以将可变长度参数当作一个数组来看
System.out.println("m3方法执行了!");
for(int i=0;i
System.out.print(args[i]+" ");
}
System.out.println();
}
}
13.反射Method
package com.jmpower.javase.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTest07 {
public static void main(String[] args) throws Exception{
//获取类
Class userServiceClass=Class.forName("com.jmpower.javase.bean.userService");
//获取所有的Method(包括私有的)
Method[] methods=userServiceClass.getDeclaredMethods();
//System.out.println(methods.length);// 2
//遍历Method
for(Method method:methods){
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获取返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取方法名
System.out.println(method.getName());
//方法的修饰符列表(一个方法的参数可能有多个)
Class[] parameterTypes=method.getParameterTypes();
for(Class parameterType:parameterTypes){
System.out.println(parameterType.getSimpleName());
}
}
}
}
14.通过反射机制调用方法(重点)
package com.jmpower.javase.reflect;
import com.jmpower.javase.bean.userService;
import java.lang.reflect.Method;
public class ReflectTest08 {
public static void main(String[] args) throws Exception{
//不使用反射机制,怎么调用方法
//创建对象
userService userService=new userService();
//调用方法
int maxn=userService.ma(99,100);
System.out.println(maxn);
//使用反射机制来调用一个对象的方法该怎么做?
Class userServiceClass=Class.forName("com.jmpower.javase.bean.userService");
//创建对象
Object obj=userServiceClass.newInstance();
//获取Method
Method loginMethod=userServiceClass.getDeclaredMethod("login", String.class, String.class);
Object retMax=loginMethod.invoke(obj,"123","lbk");
System.out.println(retMax);
}
}
15.反射Constructor
package com.jmpower.javase.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class ReflectTest09 {
public static void main(String[] args) throws Exception{
StringBuilder s=new StringBuilder();
Class vipClass=Class.forName("com.jmpower.javase.bean.Vip");
s.append(Modifier.toString(vipClass.getModifiers()));
s.append(" class ");
s.append(vipClass.getSimpleName());
s.append("{n");
//拼接构造方法
Constructor[] constructors=vipClass.getDeclaredConstructors();
for(Constructor constructor:constructors){
//public Vip(int name, int price, int value) {
s.append("t");
s.append(Modifier.toString(vipClass.getModifiers()));
s.append(" ");
s.append(vipClass.getSimpleName());
s.append("(");
//拼接参数
Class[] parameterTypes=constructor.getParameterTypes();
for(Class parameterType:parameterTypes){
s.append(parameterType.getSimpleName());
s.append(",");
}
//删除最后下标位置上的字符
if(parameterTypes.length>0) {
s.deleteCharAt(s.length()-1);
}
s.append("){}n");
}
s.append("}");
System.out.println(s);
}
}
16.通过反射机制调用构造方法
package com.jmpower.javase.reflect;
import java.lang.reflect.Constructor;
public class ReflectTest10 {
public static void main(String[] args) throws Exception{
//使用反射机制创建对象
Class c=Class.forName("com.jmpower.javase.bean.Vip");
//调用无参数构造方法
Object obj=c.newInstance();
System.out.println(obj);
//调用有参数构造方法
//第一步: 先获取这个参数的构造方法
Constructor con=c.getDeclaredConstructor(String.class,int.class,int.class);
//第二步: 调用构造方法new对象
Object newObject=con.newInstance("jackson",100,200);
System.out.println(newObject);
//获取无参数构造方法
Constructor con2=c.getDeclaredConstructor();
Object newObject2=con2.newInstance();
System.out.println(newObject2);
}
}
17.获取父类和父接口
package com.jmpower.javase.reflect;
public class ReflectTest11 {
public static void main(String[] args) throws Exception{
//String举例
Class stringClass=Class.forName("java.lang.String");
//获取String的父类
Class superClass=stringClass.getSuperclass();
System.out.println(superClass.getName());
//获取String类实现的所有接口(一个类可以实现多个接口)
Class[] interfaces=stringClass.getInterfaces();
for(Class in:interfaces){
System.out.println(in.getName());
}
}
}



