一 构造器
1 构造器解释
1.1 new关键字做的事情:
1.在堆中为对象开辟空间,成员变量跟随对象进入到堆内存并附默认值
2.调用构造器为对象初始化信息
3.将地址返回给引用
1.2 构造器|构造函数|构造方法 :
-
是一种特殊的方法
-
作用: 为对象初始化信息,为对象的属性赋值,不是用来创建对象的,new能够创建对象
调用: 只能跟随new一起使用
定义:
修饰符 类名(参数){
初始化信息代码;
} -
注意:
构造方法名一定与类同名
构造方法无返回值类型(void 也不行)
构造器可以实现重载
如果没有显示定义任何构造器,编译器会自动默认提供一个空构造(没有参数)
如果存在显示定义构造器,编译器都不会再提供任何构造器
至少实体类中自定义一个空构造,根据需求提供带参 构造方法不能被继承
构造方法不能手动调用,在创建类实例的时候自动调用构造方法。
1.2构造器实例
1.2.1 Dog类
public class Dog{
public String name;
public String type;
public String color;
//空构造
public Dog(){
System.out.println("空构造...");
}
public Dog(String dogName){
System.out.println("带1个参构造...");
name = dogName;
}
public Dog(String dogName,String dogType,String dogColor){
System.out.println("带3个参构造...");
name = dogName;
type = dogType;
color = dogColor;
}
public void show(){
System.out.println(name+"-->"+type+"-->"+color);
}
}
1.2.2 测试类
public class Class001_Constructor {
public static void main(String[] args) {
//创建对象
Dog dog = new Dog();
//为属性赋值
dog.name="点点";
dog.type="泰迪";
dog.color="白色";
//带构造实现创建对象的同时为对象的属性赋值
Dog dog2 = new Dog("二狗子");
dog2.show();
Dog dog3 = new Dog("三狗子","萨摩耶","白色");
dog3.show();
}
}
二 this关键字
- this指代当前new的对象
1 作用
-
在构造器的首行通过this(实参)调用本类中其他构造器
构造器不能相互调用 -
区分同名成员与局部变量问题
默认会发生就近原则
可以通过this.调用成员,否则默认找局部
如果不存在局部与成员同名问题,指代成员的this.可以省略
2 注意
1.this在构造器中使用,默认指代当前new的对象
2.在成员方法中的this,默认指代调用成员方法的对象
3.this不能使用在static方法中
3 实例
public class Class001_This {
public static void main(String[] args) {
/*Person p = new Person("张三",18,true);
p.show();*/
Person p = new Person("张三");
System.out.println("p--->地址--->"+p);
p.show();
}
}
class Person{
//属性
public String name;
public int age;
public boolean gender;
//构造器
public Person(){
System.out.println("-----空造器.....");
}
//带参构造
public Person(String name){
System.out.println("-----1个参数构造器.....");
this.name = name;
}
public Person(String name,int age){
System.out.println("-----2个参数构造器.....");
this.name = name;
this.age = age;
}
public Person(String name,int age,boolean gender){
this(name,age);
this.gender = gender;
System.out.println("-----3个参数构造器.....");
}
//功能
public void show(){
System.out.println("this------->"+this);
String name = "str";
System.out.println(this.name+"--->"+age+"--->"+this.gender);
}
}
三 static关键字
1 static 静态的
成员修饰符,可以修饰成员内容,不可以修饰局部
修饰成员变量–> 静态变量|类变量
修饰方法 --> 静态方法|类方法
修饰块
修饰类
2 使用方式
2.1 使用方式
static修饰的成员变量与成员方法使用方式:
1.对象.静态变量名
对象.静态方法名(参数列表)
2.类名.静态变量名
类名.静态方法名(参数列表)
2.2 实例代码
public class Class001_Static {
//类中方法外
int i = 1; //实例变量
static int j = 2; //静态变量
public static void main(String[] args) {
//局部
//测试调用
System.out.println(Class001_Static.j);
Class001_Static cs = new Class001_Static();
System.out.println(cs.i);
System.out.println(cs.j);
Class001_Static.testStatic();
cs.testStatic();
cs.test();
}
//成员方法
public void test(){
System.out.println("成员方法");
}
//静态方法
public static void testStatic(){
System.out.println("静态方法");
}
}
3 注意事项
成员是属于对象的,需要跟随对象使用
静态的是属于类的,根据可以随类名使用
4 区别
成员 :
被static修饰的–> 类的成员
变量-> 静态变量|类变量
方法-> 静态方法|类方法
没有被static修饰 --> 实例成员
变量-> 实例变量
方法-> 实例方法
5 静态内存图
静态内容是属于类的,在类第一次加载完成之后就初始化
初始顺序 : 先静态后成员
成员存在与对象的堆内存中,new对象了才开辟堆内存,才在对象的堆内存中存在成员
静态变量会给加载到静态区中,每个类的静态变量只有一份
静态内容是当前类所有对象共享的,独一份的
成员内容是属于每一个对象的,有几个对象就存在几份
6 静态的使用注意
6.1 注意事项
-
成员方法中的this默认指代当前调用成员方法的对象
-
成员方法中可以直接使用成员可以直接使用静态
-
静态方法中可以直接使用静态内容需要通过对象使用成员
-
在静态方法中不能使用this,因为冲突
6.2 实例代码
public class Class002_Static {
static int i = 20;
int j = 100;
public static void main(String[] args) {
testStatic();
Class002_Static cs = new Class002_Static();
cs.test();
}
//成员方法
public void test(){
System.out.println("成员方法");
System.out.println(i);
System.out.println(this.j);
}
public static void testStatic(){
System.out.println("静态方法");
System.out.println(i);
System.out.println(new Class002_Static().j);
}
}
7 静态练习
7.1 代码
public class Class003_StaticTest {
public static int id;
public int age;
public static void main(String[] args) {
Class003_StaticTest class003_StaticTest = new Class003_StaticTest();
System.out.println(Class003_StaticTest.id); //0
System.out.println(class003_StaticTest.age); //0
class003_StaticTest.change(); //id= 1 age= 0 //id=1 class003_StaticTest.age=1
System.out.println(Class003_StaticTest.id); //1
System.out.println(class003_StaticTest.id); //1
System.out.println(class003_StaticTest.age); //age=0
class003_StaticTest.change(); ///2 0 //2 1
System.out.println(id); //2
System.out.println(class003_StaticTest.age); //0
}
public void change() {
Class003_StaticTest class003_StaticTest = new Class003_StaticTest();
class003_StaticTest.age++; //
Class003_StaticTest.id++; //
System.out.println("In change(): id = " + id + " age = " + age); //id= age= //
System.out.println("In change(): id = " + id + " Class003_StaticTest.age = " + class003_StaticTest.age);
//id= Class003_StaticTest.age= //
}
}
7.2 分析图
四 block块
1 块 {}
-
自成作用域
-
{}定义在方法中|语句块中 : 局部代码块|普通语句块 执行时机 : 跟随方法
-
{}定义在类中方法外 : 构造块 |成员代码块 执行时机 : 跟随new
-
static{}定义在类中方法外 : 静态块 执行时机 : 类第一次加载
-
同步代码块 : 多线程时候讲
2 注意
-
构造块中的代码先于构造器代码之前执行,因为在编译期间构造块代码会被编译到要执行的构造器内部,构造器代码之前
-
如果存在多个构造块,从上到下依次执行
-
静态块中的内容在类第一次加载完成之后就执行,并且只执行一次,先与main方法执行
-
如果存在多个静态块,从上到下依次执行
3 执行顺序
静态块 --> main —> 构造块 --> 构造器
4 实例
4.1 代码1
public class Class001_Block {
static int i = 10;
int j;
//静态块
static{
System.out.println("我是静态块1");
}
static{
System.out.println("我是静态块2");
}
static{
System.out.println("我是静态块3");
}
public Class001_Block(){
System.out.println("构造器...");
}
public Class001_Block(int j){
System.out.println("构造器...");
}
//构造块
{
j = 10;
System.out.println("构造块1");
}
{
System.out.println("构造块2");
}
{
System.out.println("构造块3");
}
public static void main(String[] args) {
i = 1;
//局部代码块|普通语句块
{
System.out.println("局部代码块");
int i = 5;
System.out.println(i); //5
}
System.out.println(i); //1
Class001_Block cb = new Class001_Block();
Class001_Block cb2 = new Class001_Block();
}
}
4.2 结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B5ogqgu6-1646917564594)(E:\program\安装资料\笔记工具\Markdown\Pictures\面向对象\第六章4.2.png)]
4.3 代码2
//找到打印顺序+结果
//注意: 构造块会被编译到要执行的构造器代码的内部的最上面,如果this(),先执行this()
public class Class002_BlockTest {
public static int a = 0;
{
a = 10;
System.out.println(" 3、非静态代码块执行a=" + a); //10
}
static {
a = 6;
System.out.println(" 1、静态代码块执行a=" + a); //6
}
public Class002_BlockTest() {
this(a); //
System.out.println(" 6、"+a); //10
System.out.println(" 7、无参构造方法执行a=" + a); //10
}
public Class002_BlockTest(int n) {
System.out.println(" 4、"+n); //6
System.out.println(" 5、"+a);//10
}
public static void main(String[] args) {
System.out.println(" 2、main"); //main
Class002_BlockTest tsc = new Class002_BlockTest();
}
}
4.4 结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-krmNNTaO-1646917564595)(E:\program\安装资料\笔记工具\Markdown\Pictures\面向对象\第六章4.4.png)]
4.5反编译
public class Class002_BlockTest {
public static int a = 0;
public Class002_BlockTest() {
this(a);
System.out.println(" 6、" + a);
System.out.println(" 7、无参构造方法执行a=" + a);
}
public Class002_BlockTest(int n) {
a = 10;
System.out.println(" 3、非静态代码块执行a=" + a);
System.out.println(" 4、" + n);
System.out.println(" 5、" + a);
}
public static void main(String[] args) {
System.out.println(" 2、main");
new Class002_BlockTest();
}
static {
a = 6;
System.out.println(" 1、静态代码块执行a=" + a);
}
}
五 debug
1作用
1.追踪程序的执行流程
2.定位异常问题出现的位置
3.执行过程中方便观察变量的变化
4.通过追踪程序的执行流程学习一些第三方框架的源码
2 步骤
1.设置断点
debug模式运行的时候停在第一个断点位置,后续的执行有程序员手动控制
2.debug模式运行
3.各个键的功能
Step over F8 : 下一步跳过|略过
如果下一步是方法的调用,直接略过,不跟随方法内部执行
Step into F7 : 下一步如果是方法的调用,进入方法跟随一起执行
要求是自定义方法才会进入跟随,jdk提供方法不会进入
Force Step into alt+shift+F7 : 强制进入,如果下一步是jdk方法的调用,进入跟随执行
Step out shift+f8 : 跳出到方法调用的下一步
Run to Cursor : 运行的到光标所在位置