前言
在关于Java学习中我们一直在强调类和对象,那么到底什么是类,什么是对象?类和对象是Java语言的精髓之所在,也是Java的一大特色,我们在学习Java务必要了解这一点。
1.面向对象的初步认识
1.1什么是面向对象
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向的对象的世界里,一切皆为对象。**面向对象是解决问题的一种思想,主要靠对象之间的交互来完成一件事。**面向对象的思想涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常好。
1.2面向对象和面向过程
🤔我们举两个例子来简单说明一下面向过程和面向对象
在面向过程的时候,需要你自己去完成吃饭的每一个步骤,离开宿舍,去食堂打好饭,再带回宿舍吃饭,但是面向对象的时候,在整个打饭的过程中你都没有参与,只需要在宿舍等待室友打好饭回来即可。是不是你的对象也就是你的室友已经帮你完成了所有的步骤,此对象非男女朋友对象。
在面向对象的方式来处理,就不需要关注打饭的过程,室友是跑着去食堂还是走着去食堂,他是去几号窗口打的饭,我们都不需要关心。
2.类的定义和使用
面向对象程序设计关注的是对象,而对象是现实生活中的实体,比如洗衣机,但是计算机不认识洗衣机,需要我们告诉计算机这个洗衣机到底长什么样。
上图就是对一个简单洗衣机的简单描述,这个过程就是对洗衣机对象(这个实体)进行抽象的描述,但是我们说的再仔细,计算机也不认识,这个时候我们就需要用到Java这个编程语言来进行描述,要想拿到一个对象就得先有类👇🏾
2.1简单认识类
类是用来对一个实体(对象)进行描述的,例如洗衣机,我们描述它多大,怎么用,产自哪里,功率是多少,描述完成后,计算机就能识别到洗衣机。
那我们怎么定义一个类呢?👇🏻
2.2类的定义格式
在定义一个类时,就需要用到关键字class
class WashingMachine{
members;//成员变量或者是属性
method;//方法
}
//class是定义类的关键字,WashingMachine是类的名字,在{}中的部分就是类的主体
🦈 属性:主要是用来描述类的,成为类的成员变量或者成员属性
🐋方法:主要是用来说明类有哪些功能,成为类的方法
class WashingMachine{
public String brand;//品牌
public String type;//型号
public double weight;//重量
public double length;//长
public double width;//宽
public double height;//高
public double color;//颜色
}
------------------------------------
//以上是成员变量
public void washClothes(){ //洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){ //脱水
System.out.println("脱水功能");
}
public void setTime(){ //定时
System.out.println("定时功能");
}
-------------------------------------
//以上是成员方法
}
🕹注意事项:
1.类名采用大驼峰来定义🐫
2.成员前统一用public来修饰
3.此处写的方法不带static修饰
2.3练习
2.3.1定义一个狗类和一个猫类
class Dog{
public String name;//名字
public String color;//颜色
//狗的属性
public void bark(){
System.out.println(name+"汪汪叫");
}
public void eat(){
System.out.println(name+"在吃饭");
}
}
class Cat{
public String name;
public String color;
public void bark(){
System.out.println(name+"喵喵叫");
}
public void eat(){
System.out.println(name+"在吃饭");
}
}
}
🧳注意事项:
1.一般一个文件当中只定义一个类
2.main方法所在的类一般要使用public修饰
3.public修饰的类必须和文件名相同
4.不要轻易修改public修饰的类名
5.一个.java文件中只能有一个public类
3.类的实例化
3.1什么是实例化
🧳 定义一个类,就相当于在计算机中定义了一个新的类型,例如Dog和Cat就用户自己定义的类,有了这些自定义的类型后,就可以使用这些类来定义实例(也就是对象)
💼用类类型创建对象的过程,称为类的实例化,在Java中采用new关键字,配合类名来实例化对象
我们利用代码来实现一下
public class Main {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="旺财";
dog.bark();
dog.eat();
Cat cat=new Cat();
cat.name="布丁";
cat.bark();
cat.eat();
}
我们在对对象进行实例化之后,就可以来访问对象中的成员以及方法,通过new这个关键字来创建属于这个对象的实例,通过.号这个符号来访问对象中的成员以及方法。结合以上两个代码块,我们一开始定义了狗和猫这两个对象,但是计算机不知道他们具体的情况,我们就需要来实例化这两个小动物,他们有名字吗,会说话吗,会写字吗?
⬇️
那是否同一个类可以创建多个实例呢,答案是yes
⬇️
我们定一个Person类,通过new创建多个实例,这样完全是OK的
class Person{
public String name;
public int age;
public void eat(){
System.out.println("吃饭!");
}
public void sleep(){
System.out.println("睡觉!");
}
}
public class Test {
public static void main(String[] args) {
//一个类可以实例化多个对象
Person person1=new Person();
person1.name="本内特";
person1.age=37;
person1.sleep();
person1.eat() ;
System.out.println(person1.name+" "+person1.age);
Person person2=new Person();
person2.name="里弗斯";
person2.age=27;
person2.eat() ;
System.out.println(person2.name+" "+person2.age);
}
我们总结3点💬
- new关键字用于创建一个对象的实例
- 使用.来访问对象的成员和方法
- 同一个类可以创建多个实例
3.2类和对象的说明
🤔类和对象到底哪里不同
我们将类比作是一张房屋设计图,我可以设计出不同的房型,不同的房型就是不同的对象,至于这些房子里的卧室,厨房,洗手间是什么样的,就需要我们自己来设计,也就是类的实例化。
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员
- 类是一种自定义的类型,可以用来定义变量.
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
👤我们还是拿Person类来说明
我们实例化了两个对象,person1和person2。
他们是在main方法中创建的,方法内部创建的变量叫做局部变量,局部变量是存在栈上的,会在栈上开辟属于他们的空间,我们把person1和person2称为引用变量或者引用。引用变量:这个引用存储的是对象所在空间的地址。
new Person(),通过关键字new创建的对象都是在堆上保存的,所以person1和person2就存储了属于他们对象的地址,引用一定是指向对象的。
3.3补充
- 当一个引用赋值为null时,代表这个引用不指向任何对象,也就是空指针异常。
public static void main(String[] args) {
Person person1=null;//这代表 person1不指向任何对象,会造成空指针异常
person1.name="里弗斯";
person1.age=28;
person1.show();
}
2.引用不能指向引用,这个说法是错误的
person1=person2;
这个代表person1这个引用指向了person2这个引用指向的对象
3.一个引用能否同时指向多个对象?不能
最后person1只指向了一个对象
4.this引用
4.1为什么要有this引用
public class DateUtil {
public int year;
public int month;
public int day;
public void setDate(int year,int month,int day){
year=year;
month=month;
day=day;
}
public void show(){
System.out.println("年:"+year+" 月:"+month+" 日:"+day);
}
public static void main(String[] args) {
//创造3个日期类型的对象
//对3个对象进行设置
DateUtil dateUtil1=new DateUtil();
dateUtil1.setDate(2022,10,11);
dateUtil1.show();
DateUtil dateUtil2=new DateUtil();
dateUtil2.setDate(2022,11,12);
dateUtil2.show();
DateUtil dateUtil3=new DateUtil();
dateUtil3.setDate(2022,12,13);
dateUtil3.show();
}
}
我们仔细观察上面的代码,定义了一个日期类,然后在类方法中创建了三个对象,并通过setDate和show两个成员方法进行设置以及打印,代码的逻辑正确,看上去没有任何问题,我们运行一下来看下结果。
🤔年月日全是0,这不是我们想要的结果
答:因为形参和局部变量名字重复。而局部变量优先使用,自己给自己赋值,并没有给对象的 year month day赋值,int的默认初始值为0,所以出现的是上述的结果
🤔三个对象都调用了setDate和show方法,但是这两个方法压根不知道是谁调用了他们
为了避免这种情况的发生,就需要用到this引用
4.2什么是this引用
目前为止我们知道的是,方法前面是哪个引用就调用哪个对象的方法⬇️
public void setDate(DateUtil this,int year,int month,int day){
//这里会隐藏一个参数this,可以不加上,但是必须要知道
//每一个成员方法第一个参数默认是this
year=year;
month=month;
day=day;
}
那这个this代表的是什么?可以理解为代表的是当前的对象,我们调试来看下
⬇️
⬇️
⬇️
⬇️
总结:this代表的是当前对象的引用,当前对象是谁,就看谁调用了这个方法,谁就是this
现在我们给成员加上this看看,形参中的 this可以不加,这里只是提示。
加上this表示给当前的对象属性赋值,所以这个时候就不用担心会出现赋值混乱的情况了。
我们总结一下什么是this引用
this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问(所有的操作对用户都是透明的,即用户不需要传递,都是由编译器自动完成)
1.this的类型:对应类型引用,即哪个对象调用就是那个对象的引用类型
2.this只能在成员方法中使用,离开了成员方法,this就无法再使用
3.在成员方法中,this只能引用当前对象,不能再引用其他对象
4.this是成员方法第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责接收
⬇️
public class DateUtil {
public int year;
public int month;
public int day;
public void setDate(DateUtil this,int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
}
public void show(DateUtil this){//here
System.out.println("年:"+this.year+" 月:"+this.month+" 日:"+this.day);//here
}
public static void main(String[] args) {
DateUtil dateUtil1=new DateUtil();
dateUtil1.setDate(2022,10,11);
dateUtil1.show();
DateUtil dateUtil2=new DateUtil();
dateUtil2.setDate(2022,11,12);
dateUtil2.show();
DateUtil dateUtil3=new DateUtil();
dateUtil3.setDate(2022,12,13);
dateUtil3.show();
}
}
⬇️
除了引用成员变量之外,this还能引用成员方法以及构造方法
5.对象的构造以及初始化
5.1如何初始化对象
在Java方法内部定义一个局部变量时,必须要初始化,否则就会编译失败
public class test {
public static void main(String[] args) {
int a;
System.out.println(a);
}
}
例如我们在上个例子中实现的,在通过访问成员变量的同时直接给成员变量设置初始值
DateUtil dateUtil1=new DateUtil();
dateUtil1.setDate(2022,10,11);
dateUtil1.show();
1.此时代码不会报错,如果我们每次设置日期都需要设置具体日期,这样很麻烦,对象如何初始化。
2.局部变量必须初始化才能使用,为什么字段声明之后,没有赋值并没有报错。
public int year;
public int month;
public int day;
//字段声明之后并没有报错
这就需要我们用到构造方法⬇️
5.2构造方法
5.2.1概念
构造方法也称为构造器,是一个特殊的成员方法,名字必须与类名相同,有编译器自动调用,并且没有返回值在整个对象的声明周期内只调用一次
可以认为构造方法就是为成语变量以及成员方法赋值使用
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("带有3个参数的构造方法");
}
public void show () {
System.out.println(year + " " + month + " " + day);
}
public static void main (String[]args){
Date d = new Date(2021, 6, 9);
d.show();
}
}
这就是构造方法的基本形式,不过大家仔细想想,我们在之前的代码中,没有给过构造方法啊,不是也没有报错吗?
⬇️
📓1.如果你没有写任何的构造方法,此时Java会提供一个不带任何参数的构造方法。
public class DateUtil {
public int year;
public int month;
public int day;
public void show(DateUtil this){
System.out.println("年:"+this.year+" 月:"+this.month+" 日:"+this.day);
}
public static void main(String[] args) {
DateUtil dateUtil=new DateUtil(2020,9,1);
dateUtil.show();
}
}
📔2.但是如果你自己写了构造方法,就会调用你自己的那份构造方法,而且只会调用一次。
public class DateUtil {
public int year;
public int month;
public int day;
public DateUtil(){
System.out.println("不带参数的构造方法,如果没有写,java会默认提供");
}
public DateUtil(int year,int month,int day){
this.year=year;
this.month =month;
this.day=day;
System.out.println("带有3个参数的构造方法");
}
public void show(DateUtil this){
System.out.println("年:"+this.year+" 月:"+this.month+" 日:"+this.day);
}
public static void main(String[] args) {
DateUtil dateUtil=new DateUtil(2020,9,1);
dateUtil.show();
}
}
📒3.无论是什么构造方法,Java都不会给你提供不带参数的构造方法了。
📕4.构造方法可以重载
⬇️(一个无参一个有参)
🕹重载:方法名必须相同,参数列表不同,返回值没有影响
📗5. 可以通过this调用其他构造方法来简化代码(this必须是构造方法中的第一条语句)
public class DateUtil {
public int year;
public int month;
public int day;
public DateUtil(){
this(1999,9,9);
}
public DateUtil(int year,int month,int day){
this.year=year;
this.month =month;
this.day=day;
System.out.println("带有3个参数的构造方法");
}
public void show(DateUtil this){
System.out.println("年:"+this.year+" 月:"+this.month+" 日:"+this.day);
}
public static void main(String[] args) {
DateUtil dateUtil=new DateUtil();
dateUtil.show();
}
public DateUtil(){
this(1999,9,9);//可以通过this来调用当前对象的其他构造方法
//也就是利用无参构造方法来调用有参构造方法
}
📘 6.this调用构造方法不能形成闭环
public class DateUtil {
public int year;
public int month;
public int day;
public DateUtil(){
this(1999,9,9);//这里调用this
}
public DateUtil(int year,int month,int day){
this();//这里也调用this
this.year=year;
this.month =month;
this.day=day;
System.out.println("带有3个参数的构造方法");
}
public void show(DateUtil this){
System.out.println("年:"+this.year+" 月:"+this.month+" 日:"+this.day);
}
public static void main(String[] args) {
DateUtil dateUtil=new DateUtil();
dateUtil.show();
}
闭环调用会问题
⬇️
5.3默认初始化
上文我们已经知道该如何给对象初始化,第二个问题还没有解决,为什么局部变量必须要初始化,成员变量可以不用初始化呢?🤔
public class test {
public static void main(String[] args) {
int a;
System.out.println(a);//这样输出就会有报错,原因是因为没有对局部变量a进行初始化
}
}
public class Date {
public int year;
public int month;
public int day;
public Date(int year, int month, int day) {
// 成员变量在定义时,并没有给初始值, 为什么就可以使用呢?
System.out.println(this.month);
System.out.println(this.day);
System.out.println(this.year);
}
public static void main(String[] args) {
Date d = new Date(2022, 1, 9);
}
}
要清楚整个过程就需要了解new关键字背后发生的一些事情
Date d = new Date(2022, 1, 9);
这看上去虽然只是一条简单的代码,但是在JVM中需要做很多事
- 检测对象对应的类是否加载了,如果没有加载就需要加载
- 为对象分配内存空间
- 处理并发安全问题(例如多个线程同时申请对象,JVM要保证给对象分配的空间不冲突)
- 初始化所分配的空间⬇️
即:对象空间申请好之后,对象中包含的成员已经设置好初始值,所以我们声明字段之后并没有出现错误
5.调用构造方法,给对象中的成员赋值
5.4就地初始化
public class Date1 {
public int year=1900;
public int month=1;
public int day=1;
public Date1(){
}
public Date1(int year,int month,int day){
}
public static void main(String[] args) {
Date1 d1=new Date1(2021,1,2);
Date1 d2=new Date1();
}
}
这种初始化的方式没有意义,不建议使用
🦈代码编译完成后,编译器会将所有给成员初始化的这些语句添加到构造函数中
至此,this访问成员方法,成员变量和其他构造方法已经使用过,总结一下
💵this.data访问当前对象的成员变量
💴this.func()访问当前对象的成员方法
💶this()调用当前对象的其他构造方法
6.封装
6.1封装的概念
面向对象三大特性:封装,继承,多态,现阶段我们需要认识的是封装,什么是封装?
就是套壳屏蔽细节
这是一台电脑,对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。 对于使用者而言我们不去关心主板上的线路是如何布置的,键盘是如何连接的。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
🗣封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互
6.2访问限定符
比如:
public可以理解为一个人长什么样子大家都知道
default一个公司或者一家人都知道的秘密,对于集体之外的人来说就是隐私了
private只有自己知道,除你之外任何人都不知道
public class Computer {
private String cpu;
private String memory;
public String screen;
String brand; // 品牌---->default属性
public Computer(String brand, String cpu, String memory, String screen) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Boot() {
System.out.println("开机~~~");
}
public void PowerOff() {
System.out.println("关机~~~");
}
public void SurfInternet() {
System.out.println("上网~~~");
}
public static void main(String[] args) {
Computer p = new Computer("HW", "i7", "8G", "13*14");
System.out.println(p.brand);//default属性:只能在包中才能访问
System.out.println(p.screen);// public属性: 可以任何其他类访问
System.out.println(p.cpu);// private属性:只能在Computer类中才能访问,不能被其他类访问
}
}
注意:一般情况下成员变量设置为private,成员方法设置为public
6.3封装扩展之包
6.3.1包的概念
为了更好的管理不同的类,把多个类收集在一起成为一组,称为软件包
例如下图,为了更好的管理电脑中的书籍,我们将不同种类的书籍放在相同的文件夹中。在Java中引入了包这个概念,包是对类,接口等封装机制的体现,是一种对类或者接口等的很好的组织方式,以及在一个工程中允许存在相同名称的类,只要在不同包中即可
6.3.2导入包中的类
Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类。
public class Test {
public static void main(String[] args) {
java.util.Date date=new java.util.Date();
// 得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
可以直接使用import直接导入包
⬇️
import java.util.Date;
public class Test {
public static void main(String[] args) {
Date date=new Date();
// 得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
import java.util.*;
public class Date {
public static void main(String[] args) {
java.util.Date date=new java.util.Date();
// 得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
这里要注意的是import java.util.*;并不是把里面所有的都导出来,随用随取,用到哪个类就会导哪个类
6.3.3自定义包
1️⃣
2️⃣
3️⃣
以上就是我们自定义创建的包
在目录中也可以查找
⬇️
6.3.4包的访问权限
package demo1;
public class TestDemo1 {
private String name;
public int age;
String work;
public void care(){
System.out.println("her name is "+name);
}
public void talk(){
System.out.println(name+" "+"where are you");
}
}
将成员以及方法放在demo1中的TestDemo1的类中
package demo1;
public class TestDemo2 {
public static void main(String[] args) {
TestDemo1 demo1=new TestDemo1();
demo1.name="橘子";
System.out.println(demo1.age);
demo1.talk();
demo1.work="hangzhou";
}
}
将main方法放在demo1中的TestDemo2的类中,名字是由private修饰,只能在当前类中访问
package demo2;
public class TestDemo3 {
public static void main(String[] args) {
System.out.println(demo1.work);
}
}
work是默认权限,不允许被其他包中的类访问
6.3.5常见的包
🤖
- java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
- java.sql:进行数据库开发的支持包。
- java.lang.reflect:java 反射编程包;
- java.net:进行网络编程开发包。
- java.io:I/O编程开发包。
- java.util:是java提供的工具程序包。(集合类等) 非常重要
7.static成员
7.1再谈学生类
public class Student {
public String name;
public String gender;
public int age;
public double score;
public Student(String name, String gender, int age, double score) {
this.name = name;
this.gender = gender;
this.age = age;
this.score = score;
}
public static void main(String[] args) {
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);
}
}
我们假设这三位同学都需要在同一间教室上课,既然是在同一间教室上课,能否加上一个成员变量来保存同学们在一件教室上课?答案是无法做到。
7.2static修饰成员变量
在Java中,被static修饰的成员称为静态成员,静态成员变量最大的特性:不属于具体的对象,而是所有对象共享
成员变量:
1.静态成员变量/类变量/类成员
2.非静态成员变量/普通成员变量
public class Student {
public String name;
public String gender;
public int age;
public double score;
public String classRoom="5b08";//这里的成员变量没有使用static修饰
public Student(String name, String gender, int age, double score) {
this.name = name;
this.gender = gender;
this.age = age;
this.score = score;
}
public static void main(String[] args) {
// System.out.println(Student.classRoom);
Student s1 = new Student("Li leilei", "男", 18, 3.8);
System.out.println(s1.classRoom);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
System.out.println(s2.classRoom);
Student s3 = new Student("Jim", "男", 18, 2.6);
System.out.println(s3.classRoom);
}
}
🏣以上是没加staic修饰的情况
public class Student {
public String name;
public String gender;
public int age;
public double score;
public static String classRoom="5b08";
public Student(String name, String gender, int age, double score) {
this.name = name;
this.gender = gender;
this.age = age;
this.score = score;
}
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);
}
}
🏣以上是加了static修饰的情况
我们从调试的窗口中看到,static修饰的成员变量并没有存储到具体的某个对象,静态成员变量是共享的。
📟静态成员变量属性:
1.不属于某个具体的对象,**是类的属性,所有对象共享,**不存储在某个对象的空间中
2.一般使用推荐类名进行访问
3.类方法存储在方法区当中
4.声明周期伴随类的一生(即:随着类的加载而创建,随类的卸载而销毁)
5.静态的不依赖对象,这点要记住⬇️
7.3static修饰成员方法
如果我们把成员变量设置为private,成员方法设置为public,之前被我们设置为static的静态成员变量classRoom怎么在类外访问呢?🤔
成员方法:
1.静态成员方法/类方法
2.非静态成员方法
🗣我们需要关注3个点
1️⃣在静态方法内部不能直接调用非静态成员方法。在静态方法内部,不能直接使用非静态的数据成员
2️⃣只要是非静态的数据成员都需要通过对象的引用才能调用
public class Student {
public String name;
public String gender;
public int age;
public double score;
public static String classRoom = "5b08";
private static int size=9;
public static int getSize() {
return size;
}
public static void setSize(int size) {
Student.size = size;
}
public void mainStaticFunc(){
System.out.println("非静态成员方法");
}
public static void func(){
System.out.println("静态成员方法");
}
public static void main(String[] args) {
Student test=new Student();
System.out.println(test.size);
}
}
我们在声明成员变量的阶段定义了一个静态成员变量的size,通过实例化对象的方式进行访问并输出⬇️
是不是很麻烦,所以我们建议获取静态成员变量或者是设置静态的成员变量,此时的方法最好是静态的,如果是非静态的,还需要实例化对象,等于说是画蛇添足没有意义。
3️⃣静态方法可以通过对象调用,也可以通过类名.静态方法名来调用,不过切记,不能在静态方法中使用this
7.4static成员变量初始化
注意:静态成员变量初始化一般不会放在构造方法中来初始化,构造方法中初始化是与对象相关的实例属性
静态成员变量的初始化分两种:就地初始化和静态代码初始化
1️⃣就地初始化
就地初始化是指:在定义的时候给出初始值
public class Student{
private static String name="lisi";
private static String gender="女";
private static String classRoom="5b08"
//这是直接赋值的方法
}
还有一种就是通过get和set的方法来进行初始化,我们在刚刚的size也提到过,顺序是如下:
这样就是对一个静态成员变量进行初始化
ps:Constructor是构造方法初始化,注意区别
这里可以选择对设定的成员变量使用构造方法的方式进行初始化。
静态代码块初始化又是什么意思呢,往下看⬇️
8.代码块
8.1代码块概念以及分类
使用中括号{}定义的一段代码称为代码块,根据代码块定义的位置以及关键字,可分为4种
- 普通代码块
- 构造块
- 静态块
- 同步代码块(这里不做详细解释,后续会介绍)
8.2普通代码块
普通代码块:定义在方法中的代码块。
public class Main {
public static void main(String[] args) {
int x=10;
System.out.println("x="+x);
}
}
8.3构造代码块
构造块:定义在类中的代码块(不加任何修饰符)也叫做:实例代码块。构造代码块一般用于初始化实例成员变量。
public class Student {
//实例成员变量
private String name;
private String gender;
private int age;
public Student(){
System.out.println("成员方法");
}
//实例代码块:对成员变量进行初始化
{
this.name="Jason";
this.age=21;
this.gender="man";
System.out.println("构造代码块");
}
public void show(){
System.out.println("name: "+name+" "+"age: "+age+" "+"gender: "+gender);
}
public static void main(String[] args) {
Student stu=new Student();
stu.show();
}
}
注意:如果都是非静态代码块那么看定义的顺序
8.4静态代码块
如果静态的,非静态的,构造方法都在一起,运行起来的顺序是如何?
public class Student {
//实例成员变量
private String name;
private String gender;
private int age;
private static String classRoom;
//实例代码块:对成员变量进行初始化
{
this.name="Jason";
this.age=21;
this.gender="man";
System.out.println("非静态代码块/实例化代码块/构造代码块->初始化非静态的数据成员");
}
//静态代码块
static {
classRoom="5b08";
System.out.println("静态代码块->初始化静态的数据成员/提前准备一些数据");
}
public Student(){
System.out.println("不带参数的构造方法");
}
public void show(){
System.out.println("name: "+name+" "+"age: "+age+" "+"gender: "+gender);
}
public static void main(String[] args) {
Student s1=new Student();
System.out.println("=====================");
Student s2=new Student();
}
// public static void main1(String[] args) {
// Student s1=new Student();
// Student s2=new Student();
//
//
//
//
// }
}
通过上述代码我们不难发现静态的代码是最先执行的,并且只执行了一次,然后到我们的非静态代码块,最后是构造方法。
- 静态代码不管生成多少个对象,只会执行一次
- 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
- 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后顺序执行
- 实例代码块只有在创建对象时才会执行
⬇️
在面向对象的学习中深感愚钝,静态方法部分内容讲解若有偏差,望指正。