目录
1.类变量,类方法
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
在jdk7以前,是放在方法区;从jdk8以后,放在class对象,而class对象放在堆中。
1.当方法使用了static修饰后,该方法就可以访问静态属性
2.类方法中不允许使用this,super等和对象有关的关键字
3.静态方法只能访问静态成员(必须遵守访问权限)
4.非静态方法可以访问静态成员和非静态成员
1.1重点
1.静态方法,只能访问静态成员;
2.非静态方法,可以访问所有成员;
3.在编写代码时,仍然要遵守访问权限的规则;
public static void staticMethod1(){}
static public void staticMethod2(){}
2.main方法
1.main方法由虚拟机调用
2.java虚拟机需要调用类的main方法,所有该方法的访问权限必须是public
3.java虚拟机在执行main方法时不必创建对象,所以该方法必须是static
4. java执行的时候,传入参数1、参数2、参数3
2.1传入参数1、参数2、参数3
2.1.1 cmd命令行运行
public class Static_ {
public static void main(String[] args) {
//演示args 如何传入
//遍历显示
for(int i = 0; i < args.length; i++) {
System.out.println("第" + (i+1) + "个参数为" + args[i]);
}
}
}
javac Static_.java
java Static_ tom jack smith
========================输出============================
第1个参数为tom
第2个参数为jack
第3个参数为smith
2.1.2 Idea工具运行
5.main()方法作为一个静态方法,可以访问该方法所有的静态成员,但是不能访问非静态成员
public class Main01 {
//静态的变量/属性
private static String name = "scott";
//非静态的变量/属性
private int n1 = 10000;
//静态方法
public static void hi() {
System.out.println("Main01 hi()方法");
}
//非静态方法
public void cry() {
System.out.println("Main01 cry()方法");
}
public static void main(String[] args) {
//1.静态方法main()可以访问本类的静态成员
System.out.println("name=" + name);
hi();
//2.静态方法main()不可以访问本类的非静态成员
System.out.println(n1);//错误
cry();//错误
//3.静态方法main()要访问本类的非静态成员需要先创建对象,再调用即可
Main01 main01 = new Main01();
System.out.println(main01.n1);
main01.cry();
}
}
3.普通代码块
1.普通代码块调用的顺序优先于构造器
2.可以将多个构造器中重复的语句提取到普通代码块中,提高代码的重用性
public static void main(String[] args) {
Move move = new Move("你好,李焕英");
System.out.println("=======================");
Move move1 = new Move("夏洛特烦恼", 100, "沈腾");
}
class Move {
private String name;
private double price;
private String director;
{
System.out.println("电影屏幕打开……");
System.out.println("广告开始……");
System.out.println("电影正式开始……");
}
//3个构造器构成重载
//(1)下面的三个构造器都有相同的语句,这样代码看起来比较冗余
//(2)这时我们可以把相同的语句放入到一个代码块中,即可
//(3)这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
//(4)代码块调用的顺序优先于构造器
public Move(String name) {
/*System.out.println("电影屏幕打开……");
System.out.println("广告开始……");
System.out.println("电影正式开始……");*/
System.out.println("Move(String name)被调用……");
this.name = name;
}
public Move(String name, double price) {
/*System.out.println("电影屏幕打开……");
System.out.println("广告开始……");
System.out.println("电影正式开始……");*/
this.name = name;
this.price = price;
}
public Move(String name, double price, String director) {
/*System.out.println("电影屏幕打开……");
System.out.println("广告开始……");
System.out.println("电影正式开始……");*/
System.out.println("Move(String name, double price) 被调用……");
this.name = name;
this.price = price;
this.director = director;
}
3.普通代码块,每创建一个对象,都会被执行一次
public class CodeBlockDetail01 {
public static void main(String[] args) {
DD dd = new DD();//执行一次
DD dd1 = new DD();//执行一次
}
}
class DD {
//普通代码块
{
System.out.println("DD 普通代码块……");
}
}
4.类加载(调用静态成员)和普通代码块没有关系;
5.普通代码块在创建对象时被调用,和类加载没有关系;
public class CodeBlockDetail01 {
public static void main(String[] args) {
//调用静态成员,类加载后普通代码块不会被调用
System.out.println(DD.n1);//100
}
}
class DD {
public static int n1 = 100;
//普通代码块
{
System.out.println("DD 普通代码块……");
}
}
4.静态代码块
1.静态代码块在类加载时执行,只会被执行一次
public class CodeBlockDetail01 {
public static void main(String[] args) {
DD dd = new DD();
DD dd1 = new DD();
}
}
class DD {
//静态代码块
static {
System.out.println("DD 静态代码块1被执行……");
}
}
4.1类什么时候被加载
1.创建对象实例时(new Dog)
public class CodeBlockDetail01 {
public static void main(String[] args) {
//1.创建对象实例时(new)
AA aa = new AA();
}
}
class AA{
//静态代码块
static {
System.out.println("AA 的静态代码1被执行……");
}
}
2.创建子类对象实例,父类也会被加载,而且是父类先被加载,子类后被加载
public class CodeBlockDetail01 {
public static void main(String[] args) {
//2.创建子类对象实例,父类也会被加载,父类先被加载
AA aa2 = new AA();
}
}
class BB {
//静态代码块
static {
System.out.println("BB 的静态代码1被执行……");
}
}
class AA extends BB{
//静态代码块
static {
System.out.println("AA 的静态代码1被执行……");
}
}
3.使用类的静态成员时(包括静态属性、静态方法)
public class CodeBlockDetail01 {
public static void main(String[] args) {
//3.使用类的静态成员
System.out.println(Dog.n1);
}
}
class Dog {
public static int n1 = 100;
//静态代码块
static {
System.out.println("Dog 的静态代码1被执行……");
}
}
4.2 执行顺序
静态代码块,静态属性,静态方法的优先级都一样,谁在前面谁先被调用
public class CodeBlockDetail02 {
public static void main(String[] args) {
A a = new A();//(1)getN1()被调用……(2)A 静态代码块被执行……
}
}
class A {
//静态属性的初始化
private static int n1 = getN1();
//静态代码块
static {
System.out.println("A 静态代码块被执行……");
}
//静态方法
public static int getN1() {
System.out.println("getN1()被调用……");
return 200;
}
}
1.普通代码块,普通属性,普通方法的优先级都一样;
2.静态成员的优先级高于普通成员;
3.构造器最后被调用;
public class CodeBlockDetail02 {
public static void main(String[] args) {
//(1)getN1()被调用……(2)A 静态代码块被执行……(3)getN2()被调用……(4)A 普通代码块被执行……
//(5)A 构造器被调用……
A a = new A();
}
}
class A {
//普通变量的初始化
private int n2 = getN2();
//普通代码块
{
System.out.println("A 普通代码块被执行……");
}
//普通方法
public int getN2() {
System.out.println("getN2()被调用……");
return 3;
}
//静态属性的初始化
private static int n1 = getN1();
//静态代码块
static {
System.out.println("A 静态代码块被执行……");
}
//静态方法
public static int getN1() {
System.out.println("getN1()被调用……");
return 2;
}
public A() {
System.out.println("A 构造器被调用……");
}
}
4.2.1 构造器中隐藏的语句
构造器中隐藏的语句:
(1)默认super调用父类无参构造器
(2)执行父类的普通代码(包括普通属性初始化,普通代码块)
(3)执行本类的普通代码(包括普通属性初始化,普通代码块)
public class CodeBlockDetail03 {
public static void main(String[] args) {
new BBB();//(1)AAA 普通代码块……(2)AAA 构造器被调用……(3)BBB 普通代码块……(4)BBB 构造器被调用……
}
}
class AAA {
{//普通代码块
System.out.println("AAA 普通代码块……");
}
public AAA() {
//(1)默认super调用父类无参构造器
//(2)调用本类的普通代码块普通属性初始化
System.out.println("AAA 构造器被调用……");
}
}
class BBB extends AAA{
{//普通代码块
System.out.println("BBB 普通代码块……");
}
public BBB() {
//(1)默认super调用父类无参构造器
//(2)调用本类的普通代码块普通属性初始化
System.out.println("BBB 构造器被调用……");
}
}
4.2.2 继承中的顺序
创建一个子类对象,它们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1.父类的静态代码块,静态属性(优先级一样,按定义顺序执行)
2.子类的静态代码块,静态属性(优先级一样,按定义顺序执行)
3.父类的普通属性初始化和普通代码块(优先级一样,按定义顺序执行)
4.父类的构造方法
5.子类的普通属性初始化和普通代码块(优先级一样,按定义顺序执行)
6.子类的构造方法
public class CodeBlockDetail04 {
public static void main(String[] args) {
//执行顺序
//(1)类的加载
//1.1 先加载父类; 1.2 后加载子类
//(2)创建子类对象
//2.1 先调用子类构造器;
new B02();
}
}
class A02 {//父类
//静态属性初始化
private static int n1 = getN1();
//静态代码块
static {
System.out.println("A02 静态代码块……");//(2)
}
//普通代码块
{
System.out.println("A02 普通代码块……");//(5)
}
//普通属性初始化
public int n2 = getN2();
//静态方法
public static int getN1() {
System.out.println("getN1()");//(1)
return 10;
}
//普通方法
public int getN2() {
System.out.println("getN2()");//(6)
return 20;
}
public A02() {
//1.super()
//2.执行本类的普通属性初始化和普通代码块,谁在前谁先执行
System.out.println("A02 构造器……");//(7)
}
}
class B02 extends A02 {
private static int n3 = getN3();
static {
System.out.println("B02 静态代码块……");//(4)
}
public int n4 = getN4();
{
System.out.println("B02 普通代码块……");//(9)
}
public static int getN3() {
System.out.println("getN3()");//(3)
return 30;
}
public int getN4() {
System.out.println("getN4()");//(8)
return 40;
}
public B02() {
//隐藏代码
//1.super();
//2.执行本类的普通属性初始化和普通代码块,谁在前谁先执行
System.out.println("B02 构造器……");//(10)
}
}
4.3 区别
静态代码块只能调用静态成员,普通代码块可以调用任何成员
class C02 {
private int n1 = 100;
private static int n2 = 200;
private void m1() {
}
private static void m2() {
}
static {
//静态代码块,只能调用静态成员
//System.out.println(n1);
System.out.println(n2);
//m1();
m2();
}
{
//普通代码块可以使用任意成员
System.out.println(n1);
System.out.println(n2);
m1();
m2();
}
}