前言
类的定义和使用,类的定义格式,类的实例化,类和对象,这些都是基本的java知识,在这里就不在赘述
this引用
我们大家通常在java中使用this 的情景无非就是当一个类中的成员变量和方法中的局部变量重名时,进行区分用的。就比如:
class Dog{
public String name;
public int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
如果没有this修饰,就会出现 name = name age = age 的情况,根据局部变量就近原则,就只是让两个相同的局部变量相等而已,没有任何意义,更不可能给成员变量赋值
然而this的功能远远不止这些,this引用是另一个功能
this引用
在上一段代码中,大家有没有想过,this.+成员变量,就和类对象 .+成员变量类似,我们可以做一个对比
this.name = name;
dog.name = "lijinhan";
那么这两段代码之间有什么联系呢?
其实 this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
在写类中的方法的时候,其实有一段代码被省略了,编译器可以自动完成,完整的类内方法代码就是
class Dog{
public String name;
public int age;
public void set(Dog this ,String name, int age) {
this.name = name;
this.age = age;
}
}
this引用的特性
1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
2. this只能在"成员方法"中使用
3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法
对象的引用传递给该成员方法,this负责来接收
this还可以使得代码简洁,可以利用this()在构造方法中引用其他构造方法,这就不得不介绍一下构造方法了
构造方法
对象的构造和初始化
在没有构造方法之前,我们给一个对象的成员变量进行赋值,需要采用特定的方法才行
class Data{
public int year;
public int month;
public int day;
public void setall(int year, int month, int day){
this.day = day;
this.month = month;
this.year = year;
}
public void print(){
System.out.println(year + "-" + month + "-" + day);
}
}
public class Main{
public static void main(String[] args) {
Data data = new Data();
data.setall(2022,8,05);
data.print();
}
}
如果有了构造方法,就可以利用构造方法对对象的成员变量赋予初始值,就不必利用冗长的方法对对象进行成员变量的初始化,可以简化代码
构造方法的概念
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
构造方法是一个方法,他的方法名称与类的名称相同,构造方法分为有参构造和无参构造
public class Date {
public int year;
public int month;
public int day;
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
构造方法的特性:
1. 名字必须与类名相同
2. 没有返回值类型,设置为void也不行
3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
构造方法的重载代码演示:
public class Date {
public int year;
public int month;
public int day;
public Date(){}
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public Date(int year, int month){
this.year = year;
this.month = month;
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d2 = new Date(2022,8);//输出Date(int,int)方法被调用了
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}
之前谈到的this关键字,不仅仅可以有之前的两种功能,还可以在构造函数的内部进行其他的构造方法的调用,但是注意,this引用其他构造方法的时候,必须在构造方法内部把this写在第一行
public class Student {
public String name;
public int age;
public Student(){
System.out.println("this调用了无参构造");
}
public Student(String name, int age){
this();
this.name = name;
this.age = age;
}
}
初始化
默认初始化
在C语言中我们了解到,局部变量如果没有赋值,编译器就会给出报错,但是在Java的类中,类成员变量却可以不给他赋值就能编译成功,这是因为类对象在创建之前,在我们“new”一个新的对象之前,会把这个对象中的所有的未被显示定义的成员变量都通过构造方法进行初始化。所以并不是没有初始化,只不过是编译器在我们看不见的地方进行了初始化的操作。
可是有细心的同学会发现,有的类中没有给出构造方法,却也能够初始化,这是因为当类中没给任何的构造方法的时候,编译器就会在创建对象之前默认的生成一个无参构造方法,把对应的变量初始化成为对应的值
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
boolean | false |
float | 0.0f |
double | 0.0 |
char | '\u0000' |
reference | null |
封装
当你用电脑写完程序,点击运行就可以把你的程序跑起来了,不需要明白它能跑起来的底层原理是什么,提供给用户有限的使用方法,在用户看不见的地方创造价值,这就可以看作是封装。
在写一个项目的时候,各个程序员之间互相提供方法,我们只需要知道这个方法能用来干什么,怎么用就可以了,我们不需要知道它的底层实现逻辑,这就是封装。
在我们封装之前,我们需要知道访问限定符的作用
范围 | private | default | protected | public | |
1 | 同一包中的同一类 | 可以 | 可以 | 可以 | 可以 |
2 | 同一包中的不同类 | 可以 | 可以 | 可以 | |
3 | 不同包中的子类 | 可以 | 可以 | ||
4 | 不同保重的非子类 | 可以 |
通常使用public进行成员变量的修饰,这样安全性能比较高,但是在外部类中没有办法通过直接对象引用来调用修改数据,因此就要采用公开的封装方法
class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}//封装成方法进行外部初始化
public void setAge(int age) {
this.age = age;
}
public void getall(){
System.out.println(name + age);
}
}
public class Main3 {
public static void main(String[] args) {
Person person = new Person();
person.setName("zhangsan");
person.setAge(12);
person.getall();//不能直接调用name和age,因此通过封装方法
}
}
重难点!
static成员
在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对
象,是所有对象所共享的。
static修饰成员变量
static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
简单来说就是编译一次,受用终生,如果说每个对象的非静态成员都是该对象特有的,那么静态的就是共有的,改变某一个,所有的都会被改变。代码如下
public class Student{
public String name;
public String gender;
public int age;
public double score;
public static String classRoom = "Bit306";
// ...
public static void main(String[] args) {
// 静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
Student s1 = new Student("Li leilei", "男", 18, 3.8);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
Student s3 = new Student("Jim", "男", 18, 2.6);
// 也可以通过对象访问:但是classRoom是三个对象共享的
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.println(s3.classRoom);
}
}
值得一提的是,对于静态成员变量的访问,最好是用类名进行访问,而不是用对象来引用
Person person = new Person();
Person.Class = "java11";//推荐类名访问
person.Class = "java11";//不推荐对象名访问
static修饰的成员方法
与static修饰的成员变量类似,static修饰的成员方法成为静态成员方法,也叫做类的方法,他是所有对象所共有的,不是某个对象特有的
静态方法里面不同于其他的的方法,静态方法中的变量必须都是静态的。在上面代码中,静态成员变量采用的是直接赋值的方法进行静态成员变量的初始化,现在有了静态的方法,我们就可以在静态的方法里面对外部的静态的成员变量进行初始化
public static String Class;
public static void setClass{
Class = "java106";
}