main方法
main方法是Java虚拟机调用的。也就是说必须要是public。
在main方法中,可以直接调用main方法所在类的静态方法或静态属性,,但是不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象访问类中的非静态成员。
在IDEA下,如何给main方法args字符串数组传参数
/**
* @auther
*/
public class Hello {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
Mary,Jone,Tom
Process finished with exit code 0
代码块
代码块又称为初始化块,属于类的一部分,类似于方法,但又和方法不同,没有方法名,没有参数,只有方法体,不能通过对象或类显式调用。而是在加载类时,或创建对象时隐式调用。
基本语法
[修饰符] {
代码
};
修饰符可选,要写的话,也只能写static。使用static修饰的为静态代码块,没有static修饰的为普通代码块。
代码块的好处:相当于另一种形式的构造器,对构造器的补充,可以做初始化操作。
使用场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的复用性。
每个构造器都有相同的语句,这样代码看起来比较冗余,可以把相同的语句,放到一个代码块中,这样不管使用那个构造器,都会调用代码块中的内容。代码块的调用是优先于构造器。
/**
* @auther
*/
public class CodeBlock01 {
public static void main(String[] args) {
Movie m1 = new Movie("误杀2");
Movie m2 = new Movie("误杀2",53,"陈思成");
}
}
class Movie{
private String name;
private double price;
private String director;
{
System.out.println("电影正在上演");
System.out.println("电影即将开始播放");
}
public Movie(String name) {
this.name = name;
}
public Movie(String name, double price, String director) {
this.name = name;
this.price = price;
this.director = director;
}
}
电影正在上演
电影即将开始播放
电影正在上演
电影即将开始播放
Process finished with exit code 0
使用细节:
- 如果代码块前面被static修饰,则为静态代码块。它会随着类的加载而执行,并且只会执行一次。普通代码块,每创建一个对象就执行一次。如果只使用类的静态成员时,普通代码块并不会执行。
- 类什么时候被加载?1、创建对象实例时 2、创建子类对象实例,父类也会被加载 3、使用类的静态属性或静态方法时。
/**
* @auther
*/
public class CodeBlock02 {
public static void main(String[] args) {
//1、创建对象实例时
//new AA();
//2、创建子类对象实例,父类也会被加载。而且父类先被加载
BB b = new BB();
}
}
class AA{
static {
System.out.println("AA静态代码块被执行");
}
}
class BB extends AA{
static {
System.out.println("BB静态代码块被执行");
}
}
AA静态代码块被执行
BB静态代码块被执行
Process finished with exit code 0
/**
* @auther
*/
public class CodeBlock03 {
public static void main(String[] args) {
//使用Cat的静态成员时,会执行静态代码块
System.out.println(Cat.n1);
}
}
class Cat{
public static int n1 = 10;
static {
System.out.println("Cat的静态代码块被执行");
}
}
Cat的静态代码块被执行
10
Process finished with exit code 0
-
创建一个对象时,在一个类,调用的顺序是
-
1)调用静态代码块和静态属性初始化。两者的优先级相同,如果有多个,则按照定义的顺序调用。
-
2)调用普通代码块和普通属性的初始化。两者优先级相同,如果有多个,则按照定义的顺序调用。
-
3)调用构造方法。
-
构造器的最前面隐藏了super()和调用普通代码块
/**
* @auther
*/
public class CodeBlock04 {
public static void main(String[] args) {
new A();
}
}
class A extends AAA{
public A() {
//隐含了super()为父类的无参构造器
//还隐含了调用普通代码块的部分
System.out.println("A的无参构造器");
}
{
System.out.println("A的普通代码块");
}
}
class AAA{
public AAA(){
System.out.println("父类的无参构造器");
}
}
父类的无参构造器
A的普通代码块
A的无参构造器
Process finished with exit code 0
当创建一个子类(含有继承关系)时,调用顺序为
1)调用父类静态代码块和静态属性初始化。两者的优先级相同,如果有多个,则按照定义的顺序调用。
2)调用子类静态代码块和静态属性初始化。
3)调用父类普通代码块和普通属性的初始化。两者优先级相同,如果有多个,则按照定义的顺序调用。
4)调用父类的构造方法。
5)调用子类普通代码块和普通属性的初始化。两者优先级相同,如果有多个,则按照定义的顺序调用。
6)调用子类的构造方法。
/**
* @auther
*/
public class CodeBlock05 {
public static void main(String[] args) {
new C();
}
}
class B{
static {
System.out.println("父类的静态代码块");
}
public static int n1 = getN1();
{
System.out.println("父类的普通代码块");
}
public static int getN1() {
System.out.println("父类的静态属性");
return 100;
}
public B() {
System.out.println("父类中的构造器");
}
}
class C extends B{
static {
System.out.println("子类的静态代码块");
}
public static int n2 = getN1();
{
System.out.println("子类中的普通代码块" );
}
public static int getN1() {
System.out.println("子类的静态属性");
return 200;
}
public C() {
System.out.println("子类中的构造器");
}
}
父类的静态代码块
父类的静态属性
子类的静态代码块
子类的静态属性
父类的普通代码块
父类中的构造器
子类中的普通代码块
子类中的构造器
Process finished with exit code 0