断点调试:
- 断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后可以一步一步往下调试;调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进而分析从而找到这个bug。
- 断点调试是程序员必须掌握的技能。
- 断点调试也能帮助我们查看java底层源代码的执行过程,提高程序员的kava水平。
重要提示:
在断点调试过程中,是运行状态,是以对象的运行类型来执行的。
如:
A extends B;
B b = new A(); //编译类型是B,运行类型是A
b.xx();
编译类型看左边,运行类型看右边
类变量:
引出:
设计一个int count 表示总人数,我们创建一个小孩时,就把count加1,并且count是所有对象共享的。
class Child{ //类
private String name;
//定义一个变量count,是一个类变量(静态变量)
//该变量最大的特点就是会被Child类的所有对象实例共享
public static int count = 0;
public Child(String name){
this.name = name;
}
public void join(){
System.out.print(name + "加入了游戏..");
}
}
----------------------------------------------------------
Child child1 = new Child("小孩1");
child1.join();
child1.count++;
Child child2 = new Child("小孩2");
child2.join();
child2.count++;
Child child3 = new Child("小孩3");
child3.join();
child3.count++;
============================================================
count是共享的,child1.count、child2.count、child3.count都是同一个count
所以child1.count、child2.count、child3.count的输出结果是一样的。
什么是类变量:
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
如何定义类变量:
定义语法:
访问修饰符 static 数据类型 变量名; //推荐
static 访问修饰符 数据类型 变量名;
如何访问类变量:
类名.类变量名
或者 对象名.类变量名
(静态变量的访问修饰符的访问权限和范围和普通属性是一样的)
推荐使用–>类名.类变量名
注意事项:
1. 什么时候使用类变量:
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量):比如:定义学生类,统计所有学生共交多少钱。Student(name,fee)
2. 类变量与实例变量(普通属性)的区别:
类变量是该类的所有对象共享的,而实例变量是每个对象独享的
3. 加上static成为类变量或静态变量,否则为实例变量/普通变量/非静态变量
4. 类变量可以通过 类名.类变量名 或者 对象名.类变量名 来访问
但java设计者推荐我们使用 类名.类变量名 方式访问(前提是 满足访问修饰符的访问权限和范围)
5. 实例变量不能通过 类名.类变量名 方式访问
6. 类变量是在类加载时就初始化了
也就是说,即使没有创建对象,只要类加载了,就可以使用类变量了
7. 类变量的生命周期是随类的加载开始,随类的消亡而销毁。
类方法:
类方法也叫静态方法;
形式:
- 访问修饰符 static 数据返回类型 方法名(){} //推荐
public static void print(){}
-
static 访问修饰符 数据返回类型 方法名(){}
类方法的调用:
使用方式:类名.类方法名 或者 对象名.类方法名(前提是 满足访问修饰符的访问权限和范围)
类方法使用场景:
当方法中不涉及任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。
小结:
在程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用了,比如打印一维数组、冒泡排序、完成某个计算任务 等……
注意事项:
- 类方法和普通方法都是随着类的加载而加载的,将结构信息存储在方法区:
- 类方法中无this的参数
- 普通方法中蕴含着this的参数
- 类方法可以通过类名调用,也可以通过对象名调用;
- 普通方法和对象有关,需要通过对象名调用,比如 对象名.方法名(参数),不能通过类名调用;
- 类方法中不允许使用和对象有关的关键字,比如this和super。
普通方法(成员方法)可以; - 类方法(静态方法)中,只能访问 静态变量 或 静态方法;
- 普通成员方法,即可以访问 普通变量(方法),也可以访问静态变量(方法)。
小结
静态方法,只能访问静态成员;非静态方法,可以访问静态成员和非静态成员(必须遵守访问权限)
代码块:
基本介绍:
代码块又称为初始化块,属于类中的成员(即 是类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。
基本语法:
[修饰符]{
代码
};
注意:
- 修饰符 可选,要写的话,也只能写static;
- 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块;
- 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
- “;”号可以写上,也可以省略
代码块的好处:
- 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作;
- 如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性;
- 例子:
class Movie{
private String name;
private double price;
private String direcotr;
//3个构造器-->重载
public Movie(String name){
System.out.print("电影屏幕打开……");
System.out.print("广告开始……");
System.out.print("电影正式开始……");
this.name = name;
}
public Movie(String name,double price){
System.out.print("电影屏幕打开……");
System.out.print("广告开始……");
System.out.print("电影正式开始……");
this.name = name;
this.price = price;
}
public Movie(String name,double price,String direcotr){
System.out.print("电影屏幕打开……");
System.out.print("广告开始……");
System.out.print("电影正式开始……");
this.name = name;
this.price = price;
this.direcotr = direcotr;
}
}
- 三个构造器都有相同的语句
- 代码比较冗余
- 这时我们可以把相同的语句,放到一个代码块中即可
- 这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
- 代码块的调用顺序优先于构造器
如下:
class Movie{
private String name;
private double price;
private String direcotr;
{
System.out.print("电影屏幕打开……");
System.out.print("广告开始……");
System.out.print("电影正式开始……");
}
//3个构造器-->重载
public Movie(String name){
this.name = name;
System.out.print("构造器-->Movie(String name)被调用");
}
public Movie(String name,double price){
this.name = name;
this.price = price;
}
public Movie(String name,double price,String direcotr){
this.name = name;
this.price = price;
this.direcotr = direcotr;
}
}
输出结果:
电影屏幕打开……
广告开始……
电影正式开始……
构造器-->Movie(String name)被调用
注意事项:
1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行。
- static代码块是类的加载时,执行,只会执行一次
- 普通代码块是在创建对象时调用的,创建一次,调用一次。
2. 类什么时候被加载?
- 创建对象实例时(new)
- 创建子类对象实例,父类也会被加载,而且父类先被加载,子类后被加载
- 使用类的静态成员时,(静态属性,静态方法)
3. 普通的代码块,在创建对象实例时,会被隐式的调用。
- 被创建一次,就会调用一次。
- 如果只是使用类的静态成员时,普通代码块并不会执行。
4. 创建一个对象时,在一个类 调用顺序是(重点难点):
- 第一步:调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
- 第二步:调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通变量初始化,则按他们定义的顺序调用)
- 第三步:调用构造方法
- 代码例子:执行步骤://(1)->(2)->(3)->(4)->(5)
class A{
private static int n1 = getVal();//(1)
private int n2 = getVal2();//(3)
{//(4)
System.out.print("普通代码块执行");
}
static {//(2)
System.out.print("静态代码块执行");
}
public A01(){//(5)
super();
System.out.print("A01的构造器");
}
public static int getVal(){
System.out.print("getVal方法执行");
return 10;
}
public int getVal2(){
System.out.print("getVal2方法执行");
return 30;
}
}
5. 构造器的最前面其实隐含了super()和调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于 构造器和普通代码块在执行的。
代码例子:
class A{
public A(){
super();
//调用普通代码块
System.out.print("ok");
}
}
6. 创建一个子类时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2. 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4. 父类的构造方法
5. 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6. 子类的构造方法
7. 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
Java显示调用与隐式调用:
有一些函数,你主动的调用了,就是显示调用。
如果你没有调用,但是这个函数确实被调用了,那它就是被隐式的调用了。
显示调用:
直接使用类名调用
隐式调用:
基于事件的隐式调用风格的思想是构件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其它构件中的过程在一个或多个事件中注册,当一个事件被触发,系统自动调用在这个事件中注册的所有过程,这样,一个事件的触发就导致了另一模块中的过程的调用。