一、四种代码块
在java中用 { } 包裹起来的代码片段称为代码块,一共有以下4种:
二、普通代码块
示例代码:
public class CommonBlock {
public static void main(String[] args) {
//普通代码块:定义在方法内
{
String commonBlock = "执行普通代码块1";
System.out.println(commonBlock);
}
String main = "执行main方法";
System.out.println(main);
{
String commonBlock = "执行普通代码块2,变量名同普通代码块1";
System.out.println(commonBlock);
}
}
}
运行结果:
执行普通代码块1
执行main方法
执行普通代码块2,变量名同普通代码块1
总结
普通代码块和一般语句的执行顺序由编写顺序决定
三、构造代码块
示例代码:
public class ConstructionBlock {
{
String constructionBlock = "构造代码块1";
System.out.println(constructionBlock);
}
public ConstructionBlock(int i) {
System.out.println("第" + i + "次调用构造方法");
}
{
String constructionBlock = "构造代码块2";
System.out.println(constructionBlock);
}
public static void main(String[] args) {
new ConstructionBlock(1);
System.out.println("==============");
new ConstructionBlock(2);
System.out.println("==============");
new ConstructionBlock(3);
}
}
执行结果:
构造代码块1
构造代码块2
第2次调用构造方法
==============
构造代码块1
构造代码块2
第3次调用构造方法
总结:
1.每次创建对象都会被调用,构造代码块优先级高于构造函数;
2.存在多个构造代码块时,执行顺序由编写顺序决定。
四、静态代码块
示例代码:
public class StaticBlock {
static {
System.out.println("执行静态代码块1");
}
{
System.out.println("执行构造代码块1");
}
public StaticBlock(int i) {
System.out.println("第"+i+"次调用构造函数");
}
public static void main(String[] args) {
new StaticBlock(1);
System.out.println("==================");
new StaticBlock(2);
}
{
System.out.println("执行构造代码块2");
}
static {
System.out.println("执行静态代码块2");
}
}
执行结果:
执行静态代码块1
执行静态代码块2
执行构造代码块1
执行构造代码块2
第1次调用构造函数
==================
执行构造代码块1
执行构造代码块2
第2次调用构造函数
总结:
1.静态代码块只会执行一次,静态代码块优先级高于主方法;
2.存在多个静态代码块时,执行顺序由编写顺序决定。
五、综合
示例代码:
public class TogetherBlock {
//静态代码块:定义在类中,只执行一次
static {
System.out.println("静态代码块");
}
//构造代码块:定义在类中,每次实例化对象都会执行
{
System.out.println("构造代码块");
}
//构造方法:每次实例化都会调用
public TogetherBlock() {
System.out.println("调用了构造方法");
}
public void commonMethod() {
//普通代码块:定义在方法中,调用方法时执行
{
System.out.println("普通方法中的普通代码块");
}
}
public static void staticCommonMethod() {
{
System.out.println("静态方法中的普通代码块");
}
}
public static void main(String[] args) {
new TogetherBlock().commonMethod();
new TogetherBlock().commonMethod();
System.out.println("======================");
TogetherBlock.staticCommonMethod();
TogetherBlock.staticCommonMethod();
}
}
执行结果:
静态代码块
构造代码块
调用了构造方法
普通方法中的普通代码块
构造代码块
调用了构造方法
普通方法中的普通代码块
======================
静态方法中的普通代码块
静态方法中的普通代码块
总结:
1.静态代码块总是最先执行,并且只有在创建对象的第一个实例时才会被执行一次;
2.构造代码块其后执行,并且创建一次对象实例的时候就被执行一次;
3.构造方法其后执行,并且创建一次对象实例的时候就被执行一次;
3.普通代码块在方法被调用时执行。
六、同步代码块
示例代码:
//不安全的取钱
//两个人去银行取钱,账户
public class SynBlock {
public static void main(String[] args) {
//账户
Account account = new Account(100,"结婚基金");
Withdraw you = new Withdraw(account,50,"你");
Withdraw girlfriend = new Withdraw(account,100,"女朋友");
you.start();
girlfriend.start();
}
}
//账户
class Account{
int money;//余额
String name;//卡号
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Withdraw extends Thread{
Account account;//账户
int withdrawMoney;//取多少钱
int nowMoney;//现在手里有多少钱
public Withdraw(Account account,int withdrawMoney,String name){
super(name);
this.account = account;
this.withdrawMoney = withdrawMoney;
}
//取钱
//synchronized默认锁的是this
@Override
public void run() {
synchronized (account){
//判断有没有钱
if (account.money - withdrawMoney < 0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
//sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//卡内余额 = 余额 - 你取的钱;
account.money = account.money - withdrawMoney;
//你手里的钱
nowMoney = nowMoney + withdrawMoney;
System.out.println(account.name+"余额为:"+account.money);
//Thread.currentThread().getName() == this.getName()
//Withdraw继承Thread,Thread有getName()方法
System.out.println(this.getName()+"手里的钱"+nowMoney);
}
}
}
执行结果:
结婚基金余额为:50
你手里的钱50
女朋友钱不够,取不了
总结:
多个进程访问同一资源是保证只有一个线程能执行