Java 入门基础篇15 - java构造方法以及认识新的关键字

时间:2024-10-23 06:57:18

一 今日目标

  • 构造方法
  • static关键字
  • 代码块
  • math类
  • package关键字
  • import关键字

二 构造方法概述

2.1 构造方法描述

构造方法是一个特殊方法,作用是创建对象,对对象进行初始化。 ​ 如:

  对对象中的成员进行初始化值

2.1 构造方法的特征

1、方法名与类名相同 ​ 2、 不声明返回值类型(与声明为void不同,不能有void) ​ 3、不能被static、final、synchronized、abstract、native修饰 ​ 4、方法上可以定义参数列表,定义参数列表方式与成员方法相同 ​ 5、创建对象时执行 ​ 6、权限修饰符与成员方法定义一致

2.3 构方法格式

无参数构造方法:

权限修饰符 类名() {
    初始化语句;
}
public class Person {
    private String name;
    private int age;
    // 无参构造器
    // 创建Person对象时,会调用构造器,将name初始化为"Tom",将age初始化为10
    public Person() {
        name = "Tom";
        age = 10;
    }
}

有参数构造方法:

格式:

权限修饰符 类名(参数列表) {
    初始化语句;
}

代码实现:

public class Person {
    private String name;
    private int age;
    
    //有参构造器
    public Person(int age,String name) {
        this.age = age;
        this.name = name;
    }
}

面试:一个类中成员变量私有后,外部有几种方式对私有变量赋值?

2.4 构造方法与成员方法区别

构造方法 成员方法
作用 对对象进行初始化 封装现实事物的行为
执行 创建对象即执行 需调用再执行
格式 没有返回值、方法名和类名相同 按照标准的方法定义格式

2.5 构造方法重载

2.5.1 构造方法重载描述

构造方法支持重载,在类中可以定义多个参数列表不同的构造方法,在创建对象时传递参数,根据参数列表调用对应的构造方法。

2.5.2 构造方法重载演示

Student

class Student{
   private int age;
   private String name;
    
   public Student(){
      System.out.println("我是无参数构造方法.....");
   }
    
   public Student(int age,String name){
     System.out.println("我是两个参数构造方法......int .... String ");
     this.age = age;
     this.name = name;
   }
    
    public Student(String name,int age){
     System.out.println("我是两个参数构造方法.....String...int ");
     this.age = age;
     this.name = name;
   }
}

StudentTest

public class StudentTest{
    public static void main(String[] args){
         new Student();//创建对象不传参数,无参数构造方法就会执行
         new Student(18,"花花");//创建对象时传递了两个参数,第一个类型int,第二个类型String
         new Student("小明",60);
    }
}

构造方法总结 1.每个类默认会有一个无参构造,权限修饰符与当前类一致。 2.显示定义了构造器(构造方法)不论是有参还是无参默认无参将会消失,没有无参构造方法将不能通过无参构造方式创建对象。

2.6 构造方法相互调用

2.6.1 构造方法相互调用描述

构造方法支持相互调用,借助this关键字。 ​ 格式:this(参数)

2.6.2 构造方法相互调用实现

 public Student(){
     this(18,"张三");
     System.out.println("一个参数构造器......");
 }
 public Student(int age,String name){
      this(age,name,"女");
      System.out.println("两个参数构造方法.....");
 }
 public Student(int age,String name,String gender){
      System.out.println("三个参数构造方法.....");
 }

以上三个构造方法都会执行。

2.6.3 构造方法相互调用注意事项

1.构造方法不能出现循环调用。 ​ 2.构造方法不能自己调用自己。 ​ 3.每个构造方法中只能出现一次调用其他构造方法。

三 程序初始化过程

3.1 创建一个Student对象

学生类

public class Student{
    private int age = 16;
    private String name = "李四";
    
    public Student(int age,String name){
        this.name = name;
        this.age = age;
    }
}

测试类

public class StudentTest{
    public static void main(String[] args){
       Student s = new Student(12,"zhangsan");
    }
}

3.2 对象在JVM中初始化步骤

(1)、测试类中main方法是程序的入口,先加载StudentTest.class字节码加载进方法区中生成一个java.lang.Class (2)、将main方法压栈:在栈内存中开辟一块内存空间为运行main方法服务 (3)、在栈内存中为局部变量s申请一块空间,为s变量赋值会创建Student对象 (4)、先加载Student.class文件加载进内存的方法区中生成一个java.lang.Class对象 (5)、在栈内存为s开辟空间 (6)、在堆内存为学生对象开辟空间 (7)、对学生对象的成员变量进行默认初始化 (8)、对学生对象的成员变量进行显示初始化 (9)、通过构造方法对学生对象的成员变量赋值 (10)、学生对象初始化完毕,把对象地址赋值给s变量

3.3 内存图

四 static关键字

4.1 什么是static

static在权限修饰符的后面出现,表示静态修饰,可以修饰成员变量和成员方法以及内部类

4.2 static演示

4.2.1 static修饰成员变量

修饰成员变量: 权限修饰符 静态关键字 数据类型 变量名 = 变量值;

class Student{
     public static int classNo;
}

静态成员变量赋值:类名.变量名 = 值

 Student.classNo = 1201;

静态成员变量取值:数据类型 变量名 = 类名.变量名

//用一个变量存起来
int classNo = Student.classNo;
//直接输出
System.out.println(Student.classNo);

4.2.2 static修饰成员方法

修饰成员方法: 权限修饰符 静态关键字 返回值类型 方法名(参数列表){ 方法体}

class Student{
  
    public static void method(){
        System.out.println("我是无参数返回值静态方法,通过类名.方法名就可以调用我啦");
    }
    
    public static int max(int num1,int num2){
        System.out.println("我是有返回值有参数方法,通过类名.方法名调用我时需要传值");
        int max = num1 > num2 ? num1 : num2;
        return max;
    }
}

静态成员方法调用:类名.方法名();

//无参直接调用
Student.method();
//有参有返回值调用
int max = Student.max(10,20);
System.out.println(max);
//直接输出调用
System.out.println(Student.max(20,30));

4.3 static关键字修饰特点

1、static修饰的成员只会加载一次 ​ 2、static修饰的成员在内存中的方法区的静态共享区中 ​ 3、static修饰的成员(成员方法和成员变量)可以直接通过类名.调用也可以通过对象名.调用 ​ 4、static修饰的成员被类的所有对象共享 ​ 5、static修饰的内容随着类的加载而加载

4.4 static内存图

4.5 注意事项

① 静态不能访问非静态

public class Test{
    int a = 10;
    public static void show(){
       System.out.println(a);//报错:因为静态不能访问非静态
    }
}

② 非静态能够访问静态和非静态

public class Test{
    int a = 10;
    static b = 100;
    public  void show(){
       System.out.println(a);//非静态方法中访问非静态成员变量
       System.out.println(b);//非静态方法中访问静态成员变量
    }
}

③ 静态中不能有this关键字

public class Test{
    int a = 10;
    public static void show(){
       this.a  = 18;
       System.out.println(this);
    }
}

思考:什么情况下使用静态修饰?

面试题: 1.静态成员变量与普通成员变量的区别?

生命周期、内存中的位置、调用方式

2.静态成员方法与普通成员方法的区别?

生命周期、内存中的位置、调用方式

五 代码块

5.1 代码块介绍

{ .. }就叫代码块,java中的代码块分为构造代码块、静态代码块、局部代码块、同步代码块(多线程内容)。

5.2 各类代码块演示

5.2.1 构造代码块

定义在类中方法外{},每次构造方法执行前都会先执行构造代码块,可将多个构造方法中相同的代码抽取封装到构造代码块中,这样多个构造方法中无需重复定义这些代码。

class Student{
    {
       //构造代码块
    }
    public Studnet(){
       //构造方法
    }
}

5.2.2 静态代码块

静态代码块只是在构造代码块前面加上一个static关键字就变成了静态代码块,静态代码块用于类加载时进行初始化,只会执行一次。

public Student{
     static{
        //静态代码块
     }
     
     public Student(){
        //构造方法
     }
}

面试题 1.构造代码块和静态代码块有什么区别?

5.2.3 局部代码块

局部代码块可以定义在一个局部范围,限定变量的生命周期,提高jvm内存利用率。

public class Student{
  public void print() {
     
	{
		System.out.println("我是局部代码块");
	}
      
  }
}

5.2.4 同步代码块(了解)

为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块。

synchronized(obj){
    // 需要被同步的代码块
}

5.3 代码块面试题

  1. 类中包含构造代码块、静态代码块、构造方法,创建对象时请问执行顺序是?创建两个对象时,执行结果是?

六 链式编程

6.1 链式编程

6.1.1 链表编程介绍

简化代码编写,通过 “.” 连接不同的函数调用。 链式编程前提:

方法的返回值类型必须为引用类型。

如果返回对象中有可调用的方法,可以通过链式连续调用。

6.1.2 链式编演示

public class Demo01{
     public Demo02 getDemoo2(){
         return new Demo02();
     }
}

class Demo02{
     public Demo03 getDemo03(){
        return new Demo03();
     }
}

class Demo03{
     public String getStr(){
         return "java编程!";
     }
     
     public void println(){
        System.out.println("java!");
     }
}

传统方式调用

Demo01 d1 = new Demo01();
Demo02 d2 = d1.getDemo02();
Demo03 d3 = d2.getDem03();
String str = d3.getStr();
d3.println();

链式调用

String str = new Demo01().getDemo02().getDemo03().getStr();
new Demo01().getDemo02().getDemo03().getStr().toString();
new Demo01().getDemo02().getDemo03().println();

七、package关键字

7.1 package关键字介绍

package理解为包,包相当于windows系统里面的文件夹。 作用:

用来解决同一个路径下不能存在同名文件的问题(分类管理)。

包划分方式:

按照功能划分。 按照模块划分。

定义包的格式

package 包名。 多级包用.分开即可。

定义包的注意事项

package语句必须是程序的第一条可执行的代码。
package语句在一个java文件中只能有一个。
如果没有package,默认表示无包名。

7.2 带包的类编译和运行

手动式

javac编译当前类文件。
手动建立包对应的文件夹。
把a步骤的class文件放到新建的最终文件夹下。
通过java命令执行。注意了:需要带包名称的执行。
java com.java.HelloWorld。

自动式

javac编译的时候带上-d即可。
javac -d . HelloWorld.java。
通过java命令执行需要带上包名称执行。

案例

package com.java.demo01;
class HelloWorld{
	public static void main(String[] args){
		System.out.println("HelloWorld!");
     }     
 }

八 不同包下类之间的访问

8.1 带包名访问

定义类

功能类com.java.demo包下。
Calculate类,有个sum()方法求两个数相加相加。
测试类com.java.test包下。
CalculateTest类main方法中调用Caculate的sum方法。

访问

com.java.demo.Calculate  calculate = new com.java.demo01.Caluclate();
                                 calculate.sum(28,80);

8.2 import关键字

8.2.1 import关键字介绍

用于解决不同包之间类相互访问,A类访问B类的方法,需要加上A类的包类路径。这种方式比较麻烦,java提供了导包功能。

导报格式:

import 包名;

注意事项:

这种方式导入是到类的名称。 虽然可以最后写*,但是不建议。

面试题:

package,import,class有没有顺序关系?