步骤 1 : 什么是类对象 步骤 2 : 获取类对象 步骤 3 : 获取类对象的时候,会导致类属性被初始化 步骤 4 : 练习-在静态方法上加synchronized,同步对象是什么? 步骤 5 : 答案-在静态方法上加synchronized,同步对象是什么?
在理解类对象之前,先说我们熟悉的对象之间的区别:
garen和teemo都是Hero对象,他们的区别在于,各自有不同的名称,血量,伤害值。 然后说说类之间的区别 Hero和Item都是类,他们的区别在于有不同的方法,不同的属性。 类对象,就是用于描述这种类,都有什么属性,什么方法的
获取类对象有3种方式
1. Class.forName 2. Hero.class 3. new Hero().getClass() 在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。 注: 准确的讲是一个ClassLoader下,一种类,只会有一个类对象存在。通常一个JVM下,只会有一个ClassLoader。因为还没有引入ClassLoader概念, 所以暂时不展开了。 package reflection;
import charactor.Hero;
public class TestReflection {
public static void main(String[] args) {
String className = "charactor.Hero";
try {
Class pClass1=Class.forName(className);
Class pClass2=Hero.class;
Class pClass3=new Hero().getClass();
System.out.println(pClass1==pClass2);
System.out.println(pClass1==pClass3);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package reflection; import charactor.Hero; public class TestReflection { public static void main(String[] args) { String className = "charactor.Hero"; try { Class pClass1=Class.forName(className); Class pClass2=Hero.class; Class pClass3=new Hero().getClass(); System.out.println(pClass1==pClass2); System.out.println(pClass1==pClass3); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
为Hero增加一个静态属性,并且在静态初始化块里进行初始化,参考 类属性初始化。
static String copyright; static { System.out.println("初始化 copyright"); copyright = "版权由Riot Games公司所有"; } 无论什么途径获取类对象,都会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = Hero.class 这种方式,这种方式不会导致静态属性被初始化) package charactor;
public class Hero {
public String name;
public float hp;
public int damage;
public int id;
static String copyright;
static {
System.out.println("初始化 copyright");
copyright = "版权由Riot Games公司所有";
}
}
package reflection;
import charactor.Hero;
public class TestReflection {
public static void main(String[] args) {
String className = "charactor.Hero";
try {
Class pClass1=Class.forName(className);
Class pClass2=Hero.class;
Class pClass3=new Hero().getClass();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
在之前有一个练习,练习-在类前面加修饰符synchronized
在对象方法前,加上修饰符synchronized ,同步对象是当前实例。 那么如果在类方法前,加上修饰符 synchronized,同步对象是什么呢? 编写代码进行验证
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
当synchronized修饰静态方法的时候, 同步对象就是这个类的类对象。
如代码中的例子,当第一个线程进入method1的时候,需要占用TestReflection.class才能执行。 第二个线程进入method2的时候进不去,只有等第一个线程释放了对TestReflection.class的占用,才能够执行。 反推过来,第二个线程也是需要占用TestReflection.class。 那么TestReflection.class就是method2的同步对象。 换句话说,静态方法被修饰为synchronized的时候,其同步对象就是当前类的类对象。 package reflection;
public class TestReflection {
public static void main(String[] args) throws InterruptedException {
Thread t1= new Thread(){
public void run(){
//调用method1
TestReflection.method1();
}
};
t1.setName("第一个线程");
t1.start();
//保证第一个线程先调用method1
Thread.sleep(1000);
Thread t2= new Thread(){
public void run(){
//调用method2
TestReflection.method2();
}
};
t2.setName("第二个线程");
t2.start();
}
public static void method1() {
synchronized (TestReflection.class) {
// 对于method1而言,同步对象是TestReflection.class,只有占用TestReflection.class才可以执行到这里
System.out.println(Thread.currentThread().getName() + " 进入了method1方法");
try {
System.out.println("运行5秒");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static synchronized void method2() {
// 对于mehotd2而言,必然有个同步对象,通过观察发现,当某个线程在method1中,占用了TestReflection.class之后
// 就无法进入method2,推断出,method2的同步对象,就是TestReflection.class
System.out.println(Thread.currentThread().getName() + " 进入了method2方法");
try {
System.out.println("运行5秒");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。
问答区域
2022-10-09
代码飘红
回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
2021-03-15
类对象
2021-02-05
不用synchronized会怎样
2020-11-20
站长,这个侵犯了您的版权
2020-10-03
静态方法前加synchronized
提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 16 条以前的提问,请 点击查看
提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
|