day08
-
构造方法
1.1 构造方法的概述
Person 类,需要创建一个Person对象
Person p = new Person(); // ()表示调用Person类的构造方法 -
构造方法 : 构造器,构造函数,Constructor
-
构造方法的作用: 就是给对象的成员变量进行赋值,当创建一个对象时,JVM虚拟机自动的调用一次构造方法,运行构造方法中的内容,构造方法内部逻辑就是对成员变量进行赋值. 对象创建完毕,对象中的成员变量就有值的
-
构造方法的定义:
修饰符 构造方法名(参数列表){
// 主要逻辑就是给对象的成员变量进行赋值
return; // return 因为方法没有返回值类型,所以可以不写
}
解释:
- 修饰符,多数情况下都使用public,表示公共的,最大的使用范围
- 构造方法没有返回值,连void都不写
- 构造方法名,必须与类名严格保持一致,必须与类名一模一样
文件名------>必须与文件中的类名保持一致-----> 构造方法名与类名必须一致 - return , 一般在构造方法中,不写,如果你实在想写,那就写成return;
- 构造方法执行机制(什么时候调用运行)
- 构造方法在创建对象时,由JVM主动调用并且运行
- 构造方法在每次创建一个对象时,只能执行一次
- 构造方法不能主动调用,只能在创建对象时,JVM主动调用
代码
// 构造器的定义案例
public class Person{
// 定义成员变量
private String name;
private int age;
// 1. 定义一个构造方法
/*
修饰符 构造方法名(参数列表){
// 主要逻辑就是给对象的成员变量进行赋值
return; // return 因为方法没有返回值类型,所以可以不写
}
*/
public Person(){
System.out.println("我是空参数的构造方法");
}
// 提供私有成员对应的set和get方法
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
// 测试person类中的构造方法
public class TestPerson{
public static void main(String[] args) {
// 创建一个Person类
/*
当创建Person对象时,()就表示调用了Person类的一个空参数的构造方法
,构造方法在创建对象同时,由JVM主动地调用,执行了
*/
Person p = new Person();// 我是空参数的构造方法
System.out.println(p);// Person@15db9742
System.out.println(p.getName() + "----" + p.getAge());// 张三---20
// p.Person();// 不能主动调用构造方法
Person p2 = new Person();
System.out.println(p2);
}
}
1.2 通过构造方法给成员变量赋值
// 构造器的定义案例
public class Person{
// 定义成员变量
private String name;
private int age;
// 1. 定义一个构造方法
/*
修饰符 构造方法名(参数列表){
// 主要逻辑就是给对象的成员变量进行赋值
return; // return 因为方法没有返回值类型,所以可以不写
}
*/
public Person(){
System.out.println("我是空参数的构造方法");
// 给成员变量进行赋值
name = "张三";
age = 20;
}
}
1.2构造方法的注意事项
- 构造方法有参数列表
- 构造方法没有参数,那么调用构造方法时,就不需要传递参数
- 构造方法有参数,那么调用构造方法时,需要传递实际参数
- 如果类中没有手动的定义任何的构造方法,那么系统会默认的添加一个空参数的构造方法
如果类中,已经手动的定义了构造方法,那么系统就不会再默认添加任何构造了 - 构造方法的重载
方法重载: 在同一个类中, 方法名相同 , 方法的参数列表不同 , 与方法的返回值类型无关
构造方法重载 : 构造方法的名字必须与一致,肯定一致; [方法的参数列表不同]自己实现
, 构造方法根本没有返回值类型
说明 : 通常情况下,如果你给类中添加了有参数的构造方法,那么请你将空参数的构造方法也添加上
代码
// 构造方法使用的注意事项
public class Animal{
private String color ;
private int age;
/*
1. 定义一个有参数的构造方式
*/
public Animal(String color , int age){
this.color = color;
this.age = age;
}
// 2. 构造方法重载
public Animal(){
System.out.println("我是Animal空参数的构造方法");
}
public Animal(String color){
this.color = color;
}
public void setColor(String color){
this.color = color;
}
public String getColor(){
return color;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
代码
public class TestAnimal{
public static void main(String[] args) {
// 1. 创建Animal对象,调用有参数的构造方法
Animal a = new Animal(“cat”,2);
System.out.println(a.getColor() + “—” + a.getAge());
Animal a1 = new Animal(“dog”,3);
System.out.println(a1.getColor() + “—” + a1.getAge());
Animal a2 = new Animal();
System.out.println(a2.getColor() + "---" + a2.getAge());// null---0
// 2. TestPerson中没有定义任何的构造方法,那么系统为TestPerson
// 添加一个默认的空参数构造方法
TestPerson tp = new TestPerson();
System.out.println(tp);
}
}
1.3构造方法和set方法的赋值比较
- 构造方法和set方法都是为了给对象的成员变量进行赋值
- 构造方法给成员变量赋值 : 写法上相对比较简单,但是构造方法只能调用一次,只能给对象进行一次赋值,后期想要通过构造方法给成员进行二次赋值,做不到,灵活度不够
- set方法赋值: 创建对象成功之后,调用set方法进行赋值,每次调用set方法都可以给成员进行赋值,比较灵活
总结: set方法进行赋值更加常见和使用率高
1.4创建对象在内存中的运行过程
- 当创建对象时,针对于对象中成员变量赋值场景有3个
- JVM虚拟机,会将所有的成员变量进行一个默认的赋初值动作
- JVM检测,如果有显示的赋值,那么显示赋值会替代掉默认赋值
- JVM自动的调用了构造方法,给成员变量进行赋值
1.5 this关键字在构造方法中的使用
this 关键字 : 表示本类对象的引用
this关键字的使用场景:
- this关键字,区分成员变量和局部变量, 在变量之前添加this关键字,就表示调用的变量是成员变量
- this关键字可以在构造方法之间进行调用,使用方式: this(构造方法参数列表);
说明: this() 必须写在构造方法的第一行
代码
// this关键字在构造方法中的使用
public class ConstructorDemo {
private String id ;
public String getId(){
return id;
}
/*
1. 构造方法在创建对象时,JVM只主动调用一次
2. 构造方法不能主动调用
3. 构造方法之间可以互相调用,使用this关键
this.变量 : 表示调用成员变量
this.方法() : 表示调用类中方法
怎么使用 ?
this();// 表示调用空参数构造方法
this(参数列表); // 表示调用指定参数列表的构造方法
*/
public ConstructorDemo(){
System.out.println("ConstructorDemo的构造方法被调用了");// 1
}
public ConstructorDemo(String id){
// this() 必须写在构造方法的第一行
this();// 表示调用空参数构造方法
this.id = id;
System.out.println("id赋值成功");//2
}
public static void main(String[] args) {
ConstructorDemo cd = new ConstructorDemo("123");
System.out.println(cd.getId());//3
}
}
- static静态
2.1静态的引入
创建一个学生类Student,类中有成员变量name,age,schoolName
现在有三个学生,于是需要创建出3个学生对象,每个学生对象中,都需要给出name,age,schoolName对应的属性值
问题 :
- 每个学生有属于自己的姓名和年龄,但是所有学生都有相同的学校名称,如果每个学生对象都定义一次校名,太麻烦,也浪费内存空间
- 如果要修改校名,那么每个学生对象中的校名属性都需要修改,太麻烦,也不好维护修改
需要:
能让所有的学生对象,都拥有同一个变量schoolName,让所有学生对象都可以使用这个schoolName属性
static关键字可以做到,static关键字具有共享性,定义 static String schoolName ,就可以让所有学生对象共享使用这个属性
2.2静态的共享性
代码
public class StudentStatic{
// 每一个学生都有属于自己的姓名和年龄
String name;
int age;
// 所有学生具有相同的校名,schoolName这个属性就可以
// 被Student的所有对象共有使用
static String schoolName = “北京”;
public static void main(String[] args) {
StudentStatic s1 = new StudentStatic();
System.out.println(s1.schoolName);// 北京
// 将s1对象中的变量schoolName的值修改为"上海"
s1.schoolName = "上海";
StudentStatic s2 = new StudentStatic();
System.out.println(s2.schoolName);// 上海
}
}
静态的共享性:
静态变量在内存中的存储过程:
- StudentStatic这个类中的main方法要运行,因此StudentStatic类对应的.class文件被加载进内存,进入到方法区或数据共享区域
- JVM虚拟机检测,StudentStatic类中,是否有静态static修饰的成员,有,将static修饰的静态成员加载进入到数据共享区域,与StudentStatic的.class文件在同一块内存区域
- JVM给数据共享区域中的静态成员进行默认的赋初值动作,以及显示赋值动作
- JVM将main方法加载进入栈内存中运行,main中的代码从上到下依次运行
- StudentStatic s1 = new StudentStatic() ;
1)在堆内存中,开辟空间,JVM将StudentStatic 中的非静态成员变量加载进入到堆内存中
2)JVM为堆内存中的成员变量进行默认的赋初值
3)将静态成员变量的地址关联到对象中
4)调用StudentStatic空参数构造方法
5)将堆内存中的地址,返回给变量s1
2.3静态的特点
- 静态使用static关键字,static就表示静态的含义
- 静态具有共享性, 静态属于类,不属于任何一个对象
- 静态的加载时机(静态什么时候进内存)
当类的.class文件加载进内存时,类中的所有static修饰的成员(成员变量,方法),都随着类的加载一起进入到内存中,存储在与.class文件相同的内存空间中,叫着数据共享 - 静态优先于对象存在的
- 静态修饰的成员可以被所有对象共享使用
- 静态的调用方式:
静态属于类 : 1) 可以使用类名.直接调动(推荐) 2)可以创建对象,通过对象名调用(不推荐)
代码
public class StudentStatic{
// 每一个学生都有属于自己的姓名和年龄
String name;
int age;
// 所有学生具有相同的校名,schoolName这个属性就可以
// 被Student的所有对象共有使用
static String schoolName = “北京”;
public static void eat(){
System.out.println("吃饭");
}
public static void main(String[] args) {
StudentStatic s1 = new StudentStatic();
System.out.println(s1.schoolName);// 北京
// 将s1对象中的变量schoolName的值修改为"上海"
s1.schoolName = "上海";
StudentStatic s2 = new StudentStatic();
System.out.println(s2.schoolName);// 上海
// 静态成员的调用方式 : 最推荐的----->类名.直接调用
System.out.println(StudentStatic.schoolName);// 上海
StudentStatic.eat();
}
}
2.4静态使用的注意事项
静态中不能使用非静态
孔子(静态)游学,孔子游学,带你(非静态)去,你还没出生,去不了
- 静态方法中不能使用非静态的变量
- 静态方法中不能使用非静态的方法
- 静态方法中,不能使用this关键字
this关键字 : 表示本类对象的引用 , 静态优先于对象存在
代码
// 静态的注意事项 : 静态中不能使用非静态
public class StaticZhuYi{
// 非静态成员变量
int i = 9;// 当创建StaticZhuYi对象的时候,JVM将成员变量加载进堆内存
public void eat(){
System.out.println(“吃饭”);
}
public static void main(String[] args) {
// 1. 错误代码,静态方法中不能使用非静态的变量
//System.out.println(i);
// 2. 错误代码,静态方法中不能使用非静态的方法
// eat();
// 3. 错误代码,静态方法中,不能使用this关键字
// this关键字 : 表示本类对象的引用
// System.out.println(this.i);
}
}
2.5静态变量和非静态变量的区别
- 所属不同
- 静态变量 : 属于类
- 非静态变量 : 对象
- 在内存中存储空间不同
- 静态变量 : 方法区或数据共享,与类.class文件在同一块区域
- 非静态变量 : 堆内存中
- 生命周期不同
- 静态变量 : 跟随着类进内存而进内存,随着类的死亡才结束
- 非静态变量 : 随着对象的创建进内存,随着对象不再使用死亡
- 静态的生命周期长于非静态
- 访问方式不同
- 静态变量 : 1) 类名.直接调用(推荐) 2) 创建对象,通过对象名.调用 (不推荐)
- 非静态变量 : 创建对象,通过对象名.调用
- 帮助文档和工具类
3.1 工具类
工具类 : 表示一些类,主要功能是为了提供一些工具方法
举例 : 日期类,类中包含很多的方法,每一个方法都能表示一个独立的日期计算功能,用于满足不同开发场景下的功能使用,如此可以方便开发人员进行代码开发.
3.1.1 Arrays工具类
Arrays工具类 : 针对于数组进行的操作,来自于JDK中src.zip压缩包
Arrays工具类来自于 : java.util.Arrays;
Arrays类中的所有方法,都是静态的,可以使用Arrays.直接调用
- sort(int[] arr) : 能对数组进行排序,升序
- toString(int[] arr) : 将arr数组的内容以字符串的方式打印出来
- binarySearch(int[] arr , int key):折半查找(二分查找法)
将key数组在arr数组中的索引值获取到
要求 : 参数中提供的数组arr必须是升序排列
代码
// Arrays工具类的使用
import java.util.Arrays;
public class ArraysDemo{
public static void main(String[] args) {
int[] arr = {7,6,45,89,-9,23,1};
// 1. 将arr数组的内容以字符串的方式打印出来
String s = Arrays.toString(arr);
System.out.println(s);
// 2.能对arr数组进行排序,升序
Arrays.sort(arr);
String s1 =Arrays.toString(arr);
System.out.println(s1);
// 3. 折半查找 : 将key数组在arr数组中的索引值获取到
/*
二分查找的规则:
[-9,1,6,7,23,45,89]
1) 向将数组的1/2索引值获取到,6/2 = 3
2) 获取折半索引位置上的元素,7,与给出的数据进行比较,23大,向后继续折半查找
*/
int index = Arrays.binarySearch(arr,23);
System.out.println(index);
}
}
3.2生成帮助文档(了解)
// 单行注释
/*
多行注释
/
/*
文档注释
*/
文档注释: 可以生成操作文档,未来你的代码需要生成操作手册的,例如 ; 代码功能,使用注意事项等等
如何写作文档注释:
/**
@author 作者的含义
@version 版本,每一个代码都有版本,1.0 1.1 2.0
@param 参数,通常写在方法之上
@return 返回值,通常写在方法之上
*/
代码
/**
@author lyl
@version 1.0
*/
public class WenDangZhuShi{
public static void main(String[] args) {
System.out.println(“Hello World!”);
}
/**
求两个整数类型的和
@param x,int类型的参数
@param y,int类型的参数
@return x+y, 两个参数的和
*/
public static int getSum(int x , int y){
return x+y;
}
}
通过dos命名来进行操作手册文档的创建(了解):
javadoc -d api -author -version 源文件
javadoc ----> javadoc表示生成操作文档
-d -------> directory 目录的含义
api----> 随意的一个名字,就表示操作文档会存在的文件夹名字
-author-----> 在文档中生成作者
-version----->在文档中生成代码版本
源文件---->将那个文件中的内容生成操作文档(.java)
生成的api文件夹中,双击打开一个叫做index.html的网页文件,就是操作文档