🌱博主简介:大一计科生,努力学习Java中!热爱写博客~预备程序媛
📜所属专栏:爪洼岛冒险记【从小白到大佬之路】
✈往期博文回顾: 【爪洼岛冒险记】第5站:多图解,超详细讲解Java中的数组、二维数组–建议收藏
🕵️♂️近期目标:成为千粉小博主。
🌺“再牛的程序员也是从小白开始,既然开始了,就全身心投入去学习技术”
👩🎨write in the front:
- 这篇文章将带领大家从0开始,学会Java中的类&对象~看不懂找我!!!在线教你🙇♀️
JavaSE:类与对象
Part1:引入:
🤹♀️相信很多了解过C和Java/C++的,一定对面向对象编程、面向对象编程、万物皆对象都早已耳闻了,那到底什么是面向对象,什么是面向过程呢?接下来会举一个生动的例子,让大家切身感受一下~
1.1:人类的生活在面向对象化
🍳古人饿了vs现代人饿了:
- 古人饿了:
- 现代人饿了:
对比: - 古代人:古代人饿了,他们要从打猎、生火、做饭再到吃,要亲自把每一步都实现:
//伪代码:
public static void hunt(){
hunt a woolf;
}
public static void makeFire(){
...
}
cook(){
食材:woolf;
....
}
eat(){
吃狼肉;
}
public static void main(String[] args){
hunt();//打猎
makeFire();//生火
cook();//做饭
eat();//吃
}
- 现代人:饿了,可以叫个外卖,快递小哥接单,厨师做菜,快递小哥送单,最后吃。每个人各司其职,叫外卖的人不必知道外卖小哥是怎么送单,也不必知道厨师是如何做菜;同样,外卖小哥不必知道年轻人是如何打的电话,厨师又是如何做的菜…
//伪代码
//一:抽取出3个类
class youngMan{
public void call();
public void eat();
}
class manForTakeaway{
public void takeOrders();
public void delivery();
}
class cook{
public void cooking();
}
class Demo{
public static void main(String[] args){
//二:创建对象
youngMan Ming = new youngMan();//创建明同学
manForTakeaway Hua = new manFortakeaway();//创建出华这个外卖员
cook Wang = new cook();//创建出厨师王
//三:使用对象
Ming.call();
Hua.takeOrders();
Wang.cooking();
Hua.delivery();
Wang.cooking();
}
}
🙇♀️总结:
- 面向过程:对于一个问题,分成几个步骤,逐步解决。
- 面向对象:对于一个问题,把问题中的每一个事物都看成是一个对象,每个对象是唯一的,有属于自己的功能。只需要发挥每一个对象自己的功能,就能将问题解决。
1.2:深入—万物皆对象
🤷♀️虽然根据上面这两个例子,面向过程和面向对象,可见一斑。但是,你能说古人饿了这个问题,完全是面向过程的嘛?我其实认为不然。
- 打猎:古人使用弓箭,但古人并不知道弓箭的箭与弓之间是如何受力,如何发射的,因为古人有射箭的属性,而发射是弓箭的属性。所以古人和弓箭二者就是对象。
- 生火:古人有钻木取火的功能,但是木头因为摩擦而与空气发生燃烧,这是木头的性质与功能,古人并不具备。所以,这也能看成两个对象。
- …
🦉综上,万物其实皆对象~
1.2:面向对象编程三大关键:
- 找对象
- 🌙对象从哪里来?对象由类而来。而类,就是具体事物的抽象.所以找对象的关键就是把具体事物抽象为类.
eg:上面”现代人饿了“例子中,我们把具体的一个年轻人抽象为一类:youngMan;把具体的外卖员抽象为一个类:manForTakeaway;把具体的一个厨师抽象为一类:cook。
- 🌙对象从哪里来?对象由类而来。而类,就是具体事物的抽象.所以找对象的关键就是把具体事物抽象为类.
- 创建对象
- 使用对象
Part2:为什么会有”类与对象”?
当然,通过上面所讲,我们大概能参悟点对象&类的概念。我个人始终认为,要理解好一个概念,一个知识,如果能明白它为什么存在,存在的意义是什么?则能更好去理解和运用
2.1:现有技术无法满足需求
🙇♀️所有的技术,最后还是和现实生活接轨的,我们不可能只是简简单单的用编程来完成一些整数的运算,求最大公约数诸如此类…而且,只靠那些内置类型,是完全不够的。比如,你如何表示”人“这个类型?又如何表示”动物“这个类型?这些与现实生活相关,一些复杂的问题,仅仅靠int char Strin…是无法解决的,也许能,但是我想对开发人员也不友好吧,如果一开始就有”人“/”动物“这个类型,那得多方便~开发效率也会提高。
当然这也是我目前的一种理解,也许每个人有自己的理解,只要合理即可。
Part3:初识类&对象
3.1:类的构成
- 字段/属性/成员变量
- 普通成员变量
- 静态成员变量(被static修饰)
- 方法/行为
- 普通成员方法
- 静态成员方法
3.2:类的定义:
- 👩💼👨✈️👩⚖️👨🚒👩🏫👨⚕️👨🍳👩💻引子:现实生活中有各个职位的人,每一个具体职业的人,或者说每一个具体的人抽象起来,都有共同的属性(如:年龄,性别)和共同的行为(如:吃饭),可以形成一个类–人类。
class Person{
String name;
int age;
public void eat(){
System.out.print(name+"eating");
}
}
- 字段/属性/成员变量:定义在类的里面,方法的外面。
注意:类的命名采用大驼峰
3.3:对象的实例化
- 🧘♀️由类来创建对象,我们叫做对象的实例化。
class Person{
String name;
int age;
public void eat(){
System.out.print(name+"eating");
}
}
public class Demo{
public static void main(){
Person XiaoWang = new Person();//创建小王这个对象
}
}
- 类也可看作一种类型
- 类是引用类型
3.4:类&对象的关系:
3.5:成员变量的访问方式:
- 通过引用来访问成员变量/方法.person1是Person类变量(引用类变量)
class Person{
String name;
int age;
public void eat(){
System.out.print(name+"eating");
}
}
public class Demo{
public static void main(){
Person person1 = new Person();
//通过引用变量person1.来访问对象的属性
person1.name="XiaoWang";
person1.age=18;
}
}
3.5.1:成员变量的默认值
3.6:深入内存分析-对象在内存中如何存在⭐:
3.6.1:对象实例化过程图解:
class Person{
String name;
int age;
public void eat(){
System.out.print(name+"eating");
}
}
public class Demo{
public static void main(){
Person person1 = new Person();
Person person2 = new Person();
}
}
- 首先
Person person1
的时候,Person类就会被加载进JVM的方法区</font》 - 其次
new Person()
的时候,会在JVM的堆区中开辟一个空间,用来存储对象。 - 最后再把该对象空间在堆区上的
地址
赋给栈区上的引用变量(类类型变量)person1.
3.6.2:访问成员变量过程图解:
class Person{
String name;
int age;
public void eat(){
System.out.print(name+"eating");
}
}
public class Demo{
public static void main(){
Person person1 = new Person();
person1.name = "XiaoWang";
}
}
- 首先通过
对象名.属性
找到该引用所指向其在堆内存上的对象,并访问其name属性 - 由于name属性是引用类型,则会先在方法区常量池开辟空间来存储该常量字符串
- 最后将该方法区处理字符串地址赋值给属性,即name
3.6.3:总结:
- 对象存储在堆区上。
- 普通成员变量依赖于对象存在,即每一个对象都有自己的普通成员变量。
- 类其实也是一种类型,类类型变量是引用类型变量,存放的是所指向对象在堆区上的地址.
- 类,在计算机视角只是一个代码片段,放在JVM的方法区。不占用栈和堆的空间。
3.7:静态成员变量:
3.7.1:静态成员变量的定义:
class Person{
String name;
int age;
//定义一个静态变量
static int count=0;
}
public class Demo{
public static void main(){
Person person1 = new Person();
}
}
3.7.2:内存分配:
- 当类被加载进内存时,静态成员变量随着类一起进入方法区,并常驻方法区
- 静态成员变量是依赖于类而不依赖与对象的
3.7.3:
class Person{
String name;
int age;
//定义一个静态变量
static int count=0;
}
public class Demo{
public static void main(){
Person person1 = new Person();
Person person2 = new Person();
//通过类直接访问静态变量(不依赖于对象)
System.out.println(Person.count);
//通过对象访问
person1.count++;
person2.count++;
System.out.println(count);
//2
}
}
- 无论有多少个对象,静态变量只占一份空间。对象对静态变量的修改都是对这一份空间的修改。
Part4:详谈成员方法
4.1:成员方法介绍
成员方法根据有无static
修饰分为以下两个:
- 实例方法
non-static method
- 静态方法
static method
4.2:成员方法定义:
class Person{
String name;
int age;
//如下,定义的eat()是一个成员方法
public void eat(){
System.out.print(name+"eating");
}
}
public class Demo{
public static void main(){
Person person1 = new Person();
person1.name = "XiaoWang";
}
}
- public:表示方法是公开的(后期细讲)
4.2:成员方法内存分配问题:
- 一般认为,其实无论是static方法还是non-static方法,都是常驻内存空间的,即当类被加载进JVM的时候,方法信息(方法的指令数据,第一步干什么,第二步干什么)就被存储在了方法区中,不过此时的方法处于。—–方法的静态表现
- 但是我们经常听说某某方法在栈区开辟内存,难道方法是存在与栈区上?no,no,no!我们通常所说方法在栈区开辟内存,其实是为这个方法开辟空间,或者说开辟方法的栈帧,来存方法中的局部变量、形参,这些数据,随着方法的调用而生成,随着方法的调用结束而销毁—–函数栈帧的创建&销毁。——方法的动态表现
4.2.1:实例方法
- 实例方法其实就是普通成员方法(non-static method),上面说到,当类被加载进内存时,类中所有方法信息都被保存进了方法区。普通成员方法也在方法区,但是处于睡眠状态。你只有new对象来,用对象去调用该实例方法,该方法才会处于苏醒状态,并且该实例方法会记住它们属于哪个对象~,并指向此对象.实例方法运行过程中的形参、局部变量存储在栈区上。
- 综上,能调用实例对象的前提是—有对象!!!
4.2.3:静态方法:
- 静态方法(static method),内存分配上也是随着类的加载,永驻方法区。与实例对象不同的是,它们不需要对象!!!即,静态方法和类绑定不需要创建对象,即可调用静态方法!
- 但是静态方法被调用时,其局部变量&形参还是要在栈上开辟空间—方法栈帧。
- 静态方法的意义:让该类所有对象共享方法。
4.2.4:总结:
- 实例方法&静态方法均常驻内存.它们都是在类被加载进内存时分配了空间—加载时机、分配内存相同
- 方法是作为代码(指令数据)加载进JVM方法区(不可写),方法占多少内存与static无关。与属性不同,不论有多少对象,方法的代码都是一样的,所以只需要一份内存来存放方法即可。
- 实例方法运行起来表现不同,原因有二:1,所传形参不同;2,对象成员变量的值不同(属性不同)
- 方法运行时,其临时变量、形参,会在栈区开辟内存存储—-方法的栈帧
- 实例方法可以理解为一个静态方法,只是多了个参数
this
.通过对象去调用实例方法,可以理解为调用该类的”静态方法”,把该对象传给this参数.
Part5:不容小觑的细节
5.1:实例方法内不能定义静态变量
- 💥错误代码
class Person{
String name;
int age;
//如下,定义的eat()是一个成员方法
public void eat(){
static int test;//erro!!!
System.out.print(name+"eating");
}
}
- 首先实例方法是依赖对象,没有对象调用就不会运行。而static变量是随着对象的加载而在内存方法区中储存。
- 把static变量定义在实例方法中,没有对象来调用方法使其运行,是无法为static变量开辟内存空间的。
- 最后你要明白的是,实例方法属于对象,你把static定义在实例方法内部,就说明static变量属于对象,这是不对的。因为static变量属于类。
5.2:静态方法内不可定义静态变量
- 💥错误代码
class Person{
String name;
int age;
//如下,定义的eat()是一个成员方法
public static void eat(){
static int test();//erro!!!
System.out.print(name+"eating");
}
}
- 上面讲成员方法使,已经很详细说了,static方法会保存进方法区,但是保存的是代码。
- 其次,只有方法被调用,才会在运行,其内部变量才能开辟空间(局部变量&形参)
- 把static变量定义在方法内部,方法不被调用,是不会未其开辟空间。这就导致类在加载进内存时无法储存static变量。故代码错误。
5.3:静态方法内部不可调用实例方法
- 💥错误代码
class Person{
String name;
int age;
int test(){
}
//如下,定义的eat()是一个静态成员方法
public static void eat(){
test();//erro!!!
System.out.print(name+"eating");
}
}
- 实例方法永远依赖对象而存在。而静态方法依赖于类而存在。当用类去调用静态方法当然Ok,但当静态方法中有实例方法,此时没有对象,是无法调用此方法的!只有对象才可”唤醒“沉睡的实例方法啊!
5.4:总结:
-
判断此类型,就要弄清楚先来后到!
类加载进内存。方法区存储:类的信息、方法信息(non-static&static方法的代码)、静态变量。–永远的第一步 -
判断static修饰时,可以想想:如果没有对象,只用类名调用,行得通嘛?
🏄♀️下期预告–详细讲解Java中最重要的语法–封装
🙆♀️专栏系列文章:
🙈原创不易,如果对你有所帮助,还请三连+关注!我是瑶瑶子,持续输出优质文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142459.html