Java杂谈之类和对象 封装 构造方法以及代码块详解
作者:爱内卷的王同学
Java当中的类和对象
1. 类和对象的初步认知
java 是一门面向对象的语言,所谓面向对象有别于面向过程,面向对象是只需对象之间的交互即可完成任务,但是面向过程的话,需要我们将每一个步骤都详细地做出来。比如,以洗衣服为例,如果是面向过程来袭衣服,那么我们首先需要衣服,然后放入盆中,之后加水,放洗衣粉,最后搓揉。但是如果面向对象的话,第一步只需要找对象,找出衣服,洗衣粉,洗衣机,水这些对象,然后全部放到洗衣机里面就行了。这就是对象之间的交互。
java 当中的类是对象的综合,大打个比方,对象是房子,那么类就是设计图纸,每一个对象都是类具体的个体。
2. 类的实例化
总之,通过上面的分析,我们不难得出这样的结论:类似对象的统称,对象就是这个类的具体化实例,一个类可以产生无数个对象。那么但我在写代码的是就要进行类的实例化,即从类(也就是模板)中抽出一个具体的对象(相当于实物)。
基本语法:
//创建类 class <class_name> { field;//属性 method;//成员方法 } //实例化一个对象 <class_name> <对象名> = new <class_name>();
class 为定义类的关键字,ClassName 为类的名字,{}中为类的主体。(注意:java的类的命名是使用大驼峰,此处附上 java 组成部分的命名规则)
在类中 但是在成员方法外面 的元素可以称其为:字段 / 属性 / 成员变量(三种皆可)。
类中的函数称为:成员方法。
类的实例化方法:
class Person { public int age; //字段 public String name; public String sex; public void eat() { //方法 system.out.println("吃饭"); } public void sleep() { system.out.println("睡觉"); } }
3. 类的成员
字段(属性/成员变量)
class Person { //创建一个类 public String name; //成员变量 public int age; public void eat() { int a = 0;//局部变量 System.out.println("吃饭"); } } class Test { //创建一个类 public static void main(String[] args) {//主函数 Person person = new person(); //实例化出来一个具体对象 System.out.println(person.name);//打印出来 System.out.println(person.age); person.eat(); } } //执行结果 null 0
注意事项:
- 如上图的第 13 行和第 14 行代码,使用点号可以访问实例化对象里面的字段
- 如果成员变量没有赋初始值
那么引用类型默认是 NULL,基本类型默认是0
如果是boolean类型的,默认是false
如果是char 类型的,默认是 “\u0000”(其实就是空)
- 访问既包含了读也包含了写,读,即可以用点号找到成员变量 ,写,即可以给他赋值(本人认为这是一句废话,但是教科书看到了就bb一句)
- 此外,如果将引用设为null 那么后面再用点号来引用的话就会发生空指针异常,代码就会报错。(如下图所示)
- 第 11 行实例化时person 是一个引用变量,此时会在计算机的栈空间里面开辟一块空间用于存放 person,在堆上开辟一块空间用于存放对象,person 引用的就是 栈空间上面的对象。
- 同样地,第五行中的 a 因为它处在函数之中所以说它是一个局部变量,所以它是被存到了栈空间当中的。
方法
java 中的方法说白了就是函数,本质上就是 对象做出的一种行为
class Person { public int age = 18; public String name = "张三"; public void show() { System.out.println("我叫 + name,今年 + age + 岁"); } } class test { public static void main(String[] args) { Person person = new Person(); person.show(); } }
如上,就是说张三这个对象他有一个要执行的动作叫做 show
但是若想要想创建一个其他对象,再用show打印的话,需要 person 用点号来引用类里面的相关属性
Person person2 = new Person(); person2.name = "李四"; person2.age = 20; person2.show();
但是要注意的是,此处的代码最上面 那个Person 类在示例化的时候就已经给成员变量赋初值了,这其实是不对的,因为上面已经说过了,类其实是一切对象的总和,他是不可以这样被具体化的(简单来讲其实就是不可能所有人都叫张三)。
注意事项:在真正开发的时候我们总不可能每当要打印的时候都去写show 函数的,所以是有快捷方法的,那就是 toString 方法,鼠标右键点击一下找到generate 点击之后然后就会跳转,之后就可以找到了。
其实原理就是 println 的打印酒气本源其实是调用了一个叫做 object 的类 里面的 toString 方法,这里我们的操作就是重写该方法,这样改完之后下面的代码再用 println 打印的时候就可以直接打出我们想要的效果了。
如上图两处红色的方框便是我们更改的,那么之后每次打印代码输出我们想要的效果。如下图,上面一行是 show()函数输出的结果,而下面一行是 重写 toString 输出的效果
static 关键字
(static 可以修饰的有:字段、方法、代码块、类)
被 static 修饰的东西不需要实例化对象,用对象去点xx 来访问,他是可以直接用类名点xx 来访问。
修饰字段
静态的成员变量(或称:类变量)是独立放在方法区的,只有一份,以下面的例题为例
class TestDemo{ public int a; public static int count; } public class Main{ public static void main(String[] args) { TestDemo t1 = new TestDemo(); t1.a++; TestDemo.count++; System.out.println(t1.a); System.out.println(TestDemo.count); System.out.println("============"); t2 = new TestDemo(); t2.a++; TestDemo.count++; System.out.println(t2.a); System.out.println(TestDemo.count); } }
所以由a 和count 的存储方式就可以很容易得出答案,每当我们新实例化一个对象,a 就会随之重创,所以a 是会变的,但是 count只有一份,只存于方法区,所以 当重新 new 一个对象的时候,count 会继承上一次的值。
修饰方法
- 静态方法还是开辟栈帧的
- 静态方法是可以直接被调用的,不需要像普通方法那样想实例化对象再用对象来引用。也因此主函数的前面是要加 static的 ,因为static 是可以让主函数直接通过jvm 来调用的,如果不用这种方式的话那么将必须在主函数里面 new 一个对象,让对象来调用主函数,但是主函数目前的问题是,new 对象必须在主函数里面,但问题是我现在主函数进都进不来,要想进来就必须调用主函数,要调用就必须在主函数里面 new 对象,很明显,这是一个自相矛盾的事情,要想解决这个矛盾就必须给主函数加上 static。
- 非静态方法可以直接调用静态方法和非静态方法(就是直接在其内部写上函数名加括号就代表调用),但是静态方法不可直接调用非静态方法,能直接调用的只有静态方法,也就是说主函数要想直接调用其他方法,那就必须要让其他函数加上 static ,不然的话还要再创建对象,就很麻烦。
修饰代码块(暂不讲)
修饰类(暂不讲)
4. 封装
本质上是使用private 和 public 和这两个关键字来实现函数的封装。因为我们之前写的代码都是就直接用 public 来修饰的,这样的,我们就必须要特地去了解类里面的情况,这会让代码写起来非常麻烦,并且如果类的创建者篡改了原来类里面成员变量的名字,那么后面的代码也要跟着改,安全系数很低。所以只要我们用 private 来封装成员变量,让使用者不能直接和成员变量产生联系,而是和类里面的函数产生联系。如果成员变量产生变更,类的调用者不需要做出任何修改。
总而言之,当被 private 修饰之后它的权限就被降低了,只能在当前类里面使用。被 private 修饰的只能用类名来引用。
- getter 和 setter
但是当我们修改自己的封装的字段的时候,不可能每次都把 getName()和setName ()写出来,所以就可以直接使用快捷的方式,鼠标右击 选中generate 再选中 自己要操作的项即可。(以下为示例),还有 this 表示当前所在对象的引用。
5. 构造方法
构造方法特点:没有返回值,方法的名字和类名是相同的。
//以下为一个无参数的构造方法示例 public Person() { }
构造方法的作用是用来初始化对象的,即在对象还未创建的时候为对象的成员变量赋初值,因为对象的创建是要分两步走的,先为对象分配内存,再为对象分配合适的构造方法,也就是说当我们想要在构造方法当中提前给对象赋值的时候是可以用 this的,而且由于 this 本质上是在对象创建后 jvm 给该对象分配的相应的指针,但是也正是也因为this 可以在构造函数之中使用(此时的对象还没有完全创建好)这就可以说明 this 其实是对象的引用,并非对象本身。
在我们实例化对象的时候,编译器会默认携带一个无参数构造方法,但是如果同一个类里面已经有了其他构造方法,那么就不会自动携带这种方法。以下三段代码皆为构造方法,并且他们的关系是重载。
6. this 用法
this. 成员变量
this. 成员方法
this ( ) 用 this 来调用构造函数,构造函数里面有几个参数 this 的括号里面就有几个参数(注意,this 调用构造方法必须放在第一行)
另外,之所以说 this 是一个引用对象而不是对象是因为,对象的产生要分两步走,第一步是为对象分配内存,第二步是调用合适的构造方法,这两步完成了之后才能说我们的对象被创建了,但是,如果说我们的 this 在一个构造方法之中创建的,就可以很明显看出 this 不是对象而是引用对象,因为此时的 this 还在构造函数的代码中,也就是说 this 使用时构造函数对象还没有被创建出来,所以说这个时候的 this 仅仅只是对象的引用。
大多数时候类里面使用 this 的时候,对象还没有被创建出来,这里的 this 就是当前类的对象的引用。
此外,静态方法当中不能出现 this (静态只能靠类名来引用)。
关于引用的几个注意事项:
- 引用是否只能存在于栈上?
答:不一定,因为当你在类里面创建一个成员变量是数组的时候,在你的对象实例化之后,数组的那个引用变量就会被放到对象上面,但是数组的引用变量本质上还是引用它会指向自己数组里面的元素的。
class Person { private String name; private int age; private int[] elem = new int[10]; }//以下为原理图
- 引用可以指向引用吗?
答:不可以,引用只能指向对象。
Person person = new person(); person1 = new person(); person1 = new person(); person1 = new person(); person1 = new person();
从上面这串代码可以明显看出,person1 这个引用指向的对象一再被赋予新的对象,但是尽管如此这并不意味着 person1 就同时指向了多个对象,最终有效的对象只有第五行,也就是说,person1 指向了第五行的那个对象,其他的都没用了。
一个引用被赋值null 代表它不指向任何对象
person = null;//示例
7. 代码块
代码块分为
- 本地代码块(定义在方法里面的)//非重点
- 实例代码块(构造代码块)
{ this.age = 19; }//用于初始化成员变量
- 静态代码块
static { }//用于提请准备数据
- 同步代码块(暂不讲)
在程序执行的时候,执行顺序为:静态代码块先执行(即便放在最后面也是如此),之后实例代码块再执行,最后执行构造方法。还有,就是在一个类之中,静态的代码只执行一次。
并且当一段代码之中只有相同类型的,就会安从上往下的顺序执行。例如,如果一个类之中既有静态的字段,又有静态代码块,那么谁在前面,谁先执行。
(构造代码块)
{ this.age = 19; }//用于初始化成员变量
- 静态代码块
static { }//用于提前准备数据
- 同步代码块(暂不讲)
在程序执行的时候,执行顺序为:静态代码块先执行(即便放在最后面也是如此),之后实例代码块再执行,最后执行构造方法。还有,就是在一个类之中,静态的代码只执行一次。
并且当一段代码之中只有相同类型的,就会安从上往下的顺序执行。例如,如果一个类之中既有静态的字段,又有静态代码块,那么谁在前面,谁先执行。
到此这篇关于Java杂谈之类和对象 封装 构造方法以及代码块详解的文章就介绍到这了,更多相关Java 类与对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!