✨✨欢迎大家来到Celia的博客✨✨
🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉
所属专栏:JAVA
目录
一、关于面向对象
在我们之前的学习过程中,在写代码的时候都需要去考虑一步一步的逻辑过程,也就是面向过程去编写代码。而JAVA的主要思想是面向对象,那什么是面向对象呢?
- 我们可以想象洗衣服的过程,比如倒水、放衣服、加洗衣液、洗衣服、冲洗...等等。这一系列操作都是洗衣服的过程。
- 我们也可以使用洗衣机来洗衣服,这时,我们不需要考虑洗衣机内部是如何完成洗衣服的一系列过程,而是只需要明确把衣服放进洗衣机里,就可以达到我们的目的。
- 以上的思想就是面向对象的思想。
二、类的定义与使用
2.1 认识类
我们对于一个对象的描述一定是多角度、多方面的。比如描述一个人,就需要知道他的身高、体重、年龄、衣着等。类的作用就是把这一系列的信息统一在一起,用于描述一个对象。
2.2 类的定义
在定义类时,需要用到class关键字,具体语法如下:
//定义一个狗类
class Dog {
//字段/属性/成员变量
public String Name;
public int Age;
//可能有一些方法...
}
- class为定义类的关键字,Dog是类名。
- 类中的Name与Age变量叫做字段,或者属性,或者成员变量。
- 在成员变量类型前的修饰符public暂且不用关心,后面会详细介绍。
关于类的一些注意事项:
- 一般一个文件中只定义一个类。
- main方法所在的类一般用public修饰。
- 被public修饰的类的类名必须与文件名相同。
2.3 类的实例化
一个类就像一个模板一样,比如每个人都有名字、年龄。当我们想要描述一个人时,就可以借助类这个模板来创建一个对象,这个对象中会包含类中所定义好的姓名、年龄等成员变量。
假设有以下类的定义:
public class Person { public String Name; public int Age; //这是一个方法,用来输出对象的姓名和年龄 public void show(){ System.out.println(Name + Age); } }这样,一个类就定义好了,我们就可以基于这个类来创建一个对象:
Person man = new Person();
- 通过new关键字创建了一个叫做man的对象,这一过程就叫做类的实例化。
- 在这其中,man是一个引用类型
2.4 类和对象的说明
- 类只是一个模板,用来描述一个实体(对象),限定了类中有哪些成员。
- 类是一种自定义的类型。可以用来创建一个变量。
- 一个类可以实例化出多个对象。实例化的对象占用实际的物理空间,储存类成员变量。
- 可以把类的定义看作一个设计,不会占用物理空间,只有根据这个设计实例化出一个对象时,才会开辟空间来储存成员变量。
【附加】对象在内存中的存储
对象在内存中的存储可以简易理解为:
2.5 类中变量以及方法的访问
如果我们想访问类中的成员变量以及方法时,可以通过 对象名+‘.’来访问,具体过程如下所示:
运行结果:
三、this引用
我们先来看如下代码:
class Dog{
public String name;
public int age;
public void eat(){
System.out.println(name + "正在吃狗粮~~~");
}
}
//测试类
public class Text {
public static void main(String[] args) {
//创建两个对象
Dog dog1 = new Dog();
Dog dog2 = new Dog();
//进行成员变量的赋值
dog1.name = "小黑";
dog1.age = 5;
dog2.name = "汪汪";
dog2.age = 3;
//调用成员方法
dog1.eat();
dog2.eat();
}
}
- 在这其中,我们通过对象对成员变量赋值,并且调用成员方法。但是我们仔细一想,根据之前所学,对象在内存中的存储中,只储存了自己的成员变量等信息,并没有存储方法的相关信息。
- 所以我们调用的应是同一个方法。
- 既然是一个方法,那么这个方法又是如何区别dog1和dog2这两个狗的名字的呢?
答案是:在每一个非静态的方法中,都有一个隐藏的参数:this。this用来指代当前的对象。
(静态与非静态在之后会详细介绍)
public void eat(Dog this){ System.out.println(this.name + "正在吃狗粮~~~"); } //这两个方法的定义是等价的 public void eat(){ System.out.println(name + "正在吃狗粮~~~"); }在正常情况下,this这个参数是隐藏起来的,用来指代当前类,那么这个当前类又是什么意思呢?我们来看一下main方法里调用eat方法的语句:
dog1.eat();//dog1即是this指代的当前类(实际上是传参) dog2.eat();//dog1即是this指代的当前类(实际上是传参)当我们用一个对象来调用非静态的成员方法时,当前对象就会作为一个参数,传参到非静态方法中的this参数上。所以虽然调用的是同一个方法,但是在参数上是有区别的,是不同的两个对象,自然也就能区分不同对象的名字。
【附加】一些建议
- 我们在调用成员变量/方法时,可以省略this,但是不建议
- 一方面是为了让代码看起来更加的严谨,是一个好的编程习惯
- 另一方面可以解决在构造方法中,参数名字和成员变量名字相同而出现赋值失败的问题
四、对象的构造以及初始化
我们在创建一个对象的时候,可以对其中的成员变量进行赋值,如下:
Dog dog1 = new Dog();
Dog dog2 = new Dog();
//进行成员变量的赋值
dog1.name = "小黑";
dog1.age = 5;
dog2.name = "汪汪";
dog2.age = 3;
但是这样是否太过于冗杂呢?我们可不可以在创建类的同时进行成员变量的赋值呢? 这里就涉及到新的知识:构造方法。
4.1 构造方法
构造方法是一类特殊的方法,没有返回类型(包括void也不行),方法名和类名相同,参数可有可无。它会在创建对象的时候自动被调用。如果类中没有对构造方法的定义,JAVA会自动提供一个不带参数的构造方法。
class Dog{
public String name;
public int age;
//构造方法
public Dog(String name,int age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(this.name + "正在吃狗粮~~~");
}
}
public class Text {
public static void main(String[] args) {
//创建两个对象
Dog dog1 = new Dog("小黑",5);//在这里传参
Dog dog2 = new Dog("汪汪",3);
//进行成员变量的赋值
// dog1.name = "小黑";
// dog1.age = 5;
// dog2.name = "汪汪";
// dog2.age = 3;
dog1.eat();
dog2.eat();
}
}
介绍完构造方法,咱们回到之前的问题:
- 为什么建议在非静态方法中调用成员变量建议保留this呢?
如果不保留this,将构造方法写成如下形式:
public Dog(String name,int age){ name = name; age = age; }运行结果:
我们发现成员变量并没有被赋值,原因如下:
- 局部的变量优先使用,如果没有this的引用,且当参数名和成员变量名相同时,会发生成员变量自己给自己赋值的情况,确实赋值了,只不过赋值的对象并不是成员变量,而是参数本身。
4.1.1 this的三种使用方式
- 调用成员变量
- 调用非静态成员方法
- 调用构造方法
前两种之前已经介绍过,接下来将详细介绍第三种用法:调用构造方法。
我们知道,在类中如果没有构造方法的定义,JAVA会自动提供一个不带参数的构造方法:
public Dog(){ }在这个方法中,同样有this引用,this调用构造方法的方式如下:
public Dog(){ this("小黑",9);//必须在第一行 } public Dog(String name,int age){ //实际上调用了这个构造方法 this.name = name; this.age = age; }我们在一个构造方法中可以用this调用另一个构造方法,但是这个this引用必须放在第一行。
五、封装
我们在使用手机的时候,其实并不知道手机内部是如何工作的,但是我们知道充电口可以充电、摄像头可以照相。这种把内部的一些实现方法隐藏起来,使用者不能直接访问,而只提供访问它们的渠道,这种情况就叫做封装。
5.1 private、default、public
- private 修饰的成员变量/方法只能在当前的的类中访问
- default 这种情况是默认权限,不加任何修饰符的情况,成员变量/方法可以在同一个包中被访问
- public 修饰的成员变量/方法/类可以任意被访问
5.2 具体实现方法举例
class Dog{
private String name;//在这个类的外部不能直接被访问
private int age;//在这个类的外部不能直接被访问
public Dog(String name,int age){ //构造方法
this.name = name;
this.age = age;
}
public String getName() { //提供一些方法来获取信息
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void eat(){
System.out.println(this.name + "正在吃狗粮~~~");
}
}
在这段代码中,name和age不能直接被外部访问,但是可以通过调用其他方法来接收返回值得到相应的信息。
六、关于static
被这个修饰符修饰的方法、成员变量,被称为静态方法/变量。它们不依赖于对象的实例化,随着类的加载而被加载。
【附加】关于加载
JAVA语言不依赖于系统,而是有着独立的虚拟机:JVM 。源代码会被加载至JVM中,再由JVM将这些处理过的代码翻译成一条条的机器指令,使不同的系统可以识别并运行。
需要额外注意的是JAVA是具有选择性加载的特性,只有当使用到该类时,这个类才会被加载。
6.1 static修饰方法、成员变量
被static修饰的成员方法,成员变量不需要实例化一个对象来调用,直接使用类名+'.'就可以访问。
class Dog{
public static String name = "汪汪";
public int age = 6;
public static void func(){
System.out.println("测试静态方法");
}
}
public class Text {
public static void main(String[] args) {
Dog.func();//直接用类名就可以访问,不依赖于对象
System.out.println(Dog.name);
}
}
6.2 static修饰需要注意的事项
- static修饰的方法中,不能调用非静态方法。如果非要调用,需要实例化对象,用对象来调用。
- static修饰的方法不依赖于对象,所以没有this引用。
- 非静态方法可以直接调用静态方法,不需要实例化对象。
- stati修饰的成员变量不依赖于对象,一般用类名访问,但是也可以通过对象访问,这里不建议这样做。
七、代码块
代码块是被包含在花括号{}里的代码片段,在JAVA中,多数用来初始化数据。
7.1 静态代码块
static {
name = "小黑"; //静态代码块
}
7.2 实例代码块
{
age = 8; //实例代码块
}
7.3 代码举例
class Dog{
public static String name = "汪汪";//就地初始化
public int age = 6; //就地初始化
static {
name = "小黑"; //静态代码块
}
{
age = 8; //实例代码块
}
}
public class Text {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.age);
System.out.println(Dog.name);//用类名访问
System.out.println(dog.name);//这样写也可以,但是不建议
}
}
在这里还会注意到一点:原本就地初始化的数据被覆盖了,这就涉及到执行顺序的问题。
执行的顺序:

(父类和子类的知识在之后的继承与多态会讲到)
八、对象的打印
我们来看下面的代码:
class Dog{ public String name ; public int age ; public Dog(String name, int age) { this.name = name; this.age = age; } } public class Text { public static void main(String[] args) { Dog dog = new Dog("小黑",12); System.out.println(dog);//直接打印,结果是什么呢? } }
由于dog是一种引用类型,dog里实际上存储的是一个地址,所以输出结果是地址。
Dog 是类名,@是分隔符,在这之后的一串是转换后的哈希值,可以看作是地址。
如果我们查看源码:实际上调用的是toString
如果我们想要输出类中的成员变量,只需要重写这个方法就可以了。
class Dog{ public String name ; public int age ; public Dog(String name, int age) { this.name = name; this.age = age; } public String toString(){ //重写toString方法 return this.name + " " + this.age; } } public class Text { public static void main(String[] args) { Dog dog = new Dog("小黑",12); System.out.println(dog); } }
关于重写,会在之后的继承与多态中讲到,目前只需要明确:
- 直接打印对象名,会输出地址
- 如果想要输出对象的信息,只需要在当前类中重新写一个toString方法
- 重写的要求:除了方法中的内容不同,其他都要求一致(返回值、方法名、参数名、参数顺序)。










被折叠的 条评论
为什么被折叠?



