1.什么是类?什么是对象?
从以上两张图片可以看出类是由“class+类名”组成的类中包含着属性,方法。“person”是一个对象通过上图的代码实例化它。对象可以是人也可以是物,也能表现为一个事件等等这要看你的类去怎么定义它。
所以我们可以知道类与对象的定义:(1)类:具有相同特性和行为的对象组成的集合就是类,也就是里面的成员变量以及方法。(2)对象:万物都可以视作为对象,对象具有状态,可以用值来描述对象,对象具有行为(也就是类里面定义的方法)。
对象与类之间的联系:类是对象的抽象,而对象是类的具体实例。
下面用一段代码来描述类与对象的关系:
类Person里面具有成员变量以及方法,在另一个类的main函数中通过调用类Person并且实例化一个对象person,并对其进行赋值。
需要注意的是:我们实例化的对象person是一个变量,它不是一个地址,这个变量里面存放的是地址,所以被称为引用。既然是变量那就有类型,所以它的类就是Person(以以上代码为例)。
2.一个类可以实例化多个对象
例如再实例化一个类Person的对象person
在实例化这个对象后,person1也具有类Person的属性和方法。
实例化的两个对象person和person1会有分配有两块不同的内存,可以对不同的对象赋值而且两个对象互相不影响
3.类的成员以及方法
分为普通成员变量和静态成员变量
静态成员变量(类变量)
在类中定义一个静态成员变量
接下来我们来看两段代码以及它们各自运行的结果(其中count会报警告)
代码中,实例化了一个对象person1,它对类中静态成员变量进行了count++的操作,而后有建立了一个person2对象也进行了相同的操作,但是两者的结果分别为1,2。
然后,我们来看另一段代码
可以观察到通过一样的操作,这一段代码运行的结果为1,1。
但是从类中属性的定义可以看出count是通过static修饰的静态成员变量,而age则是由int修饰的普通整形变量
count的警告问题解释:
上面我们提到代码会报警告,为什么呢?
这个count不属于对象,它属于类,通过类名可以直接调用
通过类名直接调用,不需要通过new多个对象去调用,这样可以节省对象再堆上开辟的空间。所以访问静态成员变量直接使用类名去访问就行,因为静态成员变量在方法去只存储一份不需要去重复调用。
方法区:它存储已被Java虚拟机(JVM)加载的类信息、字节码文件(.class)、常量、静态变量、即时编译器编译后的代码等
静态成员变量的访问:类名.静态的成员属性/方法。不依赖于对象。
静态成员变量的定义:在普通的方法中不能定义静态的成员变量。
因为:(1)、static定义的变量是属于类变量。(2)、eat方法是普通方法,它需要new一个对象出来调用它,如果eat方法里面定义了static变量的话,直接使用Person来调用类方法的话会和普通方法的变量相互冲突。
在静态的方法中也不能定义静态的成员变量,因为静态成员变量是属于类的它不属于方法。
总结:静态的成员变量是不可以在方法中定义的 。静态方法和实例无关,和类相关
但是在普通方法中可以调用静态的方法,在静态方法中不能调用普通方法(除了在方法中new一个对象就可以调用):
普通方法是依赖对象的,静态方法是不依赖对象的。
(2)、普通成员变量
记住:需要通过new对象调用。
4.什么是null
这个引用它不指向任何对象。
接下来看另一个:
person1这个引用指向person这个引用的所指向的对象。也就是指向同一个person对象。
但是一个引用它不可以指向多个对象!:
person只看的是最后一次指向的对象。
5.println()的调用
如果我们new一个对象直接打印对象会看到如下:
我们可以看到打印的结果中@符号前面的是类的名称,符号后面的是一串哈希值,它表示的是对象person的地址(这不是一个真正的地址它是经过处理过的一个地址,因为java比较安全),通过查看(点击printfln)
person传进去,转化成字符串,点击valueOF(x)查看如何转换成字符串:
如果传进去的不是null,则进入toString()函数:
通过解析源码可以得知,从printfln(person)中把person以x传入,然后再到valueOF,最后传入toString(),在toString中返回值是getName()获取类名+“@”+一个hashCode()(哈希值),通过逐层返回,会通过print(s)方法打印、换行。
如果我们在类方法里面定义toString()方法那么直接通过对象输出person会发什么呢?
输出结果是:
这样子,就没有调用前面源码中的object中的函数,而是自己调用自己的toString函数,但是toString的名字不能变
接下来我们可以对代码做一些改变,可以把类Person里面的输出方法做一些改变,对象可以直接调用toString来作出输出的功能
把上图println()里需要输出的换到toString中:
输出的结果是:
6.封装(private)
把类中的成员变量封装起来,则该类的成员变量只能在当前类中使用,在类外是不能使用被关键字private修饰的成员变量的。
如何访问被封装的成员变量:如果其他的类需要用到该类中被封装的成员变量,我们有以下方法:
(1)、给定一个public的方法去调用成员变量 :
下面是调用函数:
可以看到通过调用类Person中的公开的方法也可以定义name进行赋值,解决了name的问题,使用private封装的属性,方法的好处是更安全了。调用者需要注意的是所调用的该类的公开借口。
我们在类里面的age设置成private,给定一个公开的接口去调用它
里面的this.age代表当前对象的age,也就是被封装的age,意思是当前对象的引用,通过引用去调用类里面的age。
目录
1.什么是类?什么是对象?
2.一个类可以实例化多个对象
3.类的成员以及方法
4.什么是null
5.println()的调用
6.封装(private)
7.构造方法
方法名和类名是相同的,且它比较特殊,没有返回值。
构造方法是干嘛的?
一个对象的产生(对象的实例化) 1.为对象分配内存。2.调用合适的构造方法。构造方法不止一个。
在类中建立一个构造方法:
如何在main里面调用这个构造方法呢?:
这里new的对象person,调用了不带参数的构造方法。但是注意:当我们没有写构造方法的话类会默认帮我们写一个不带参数的构造方法。一个类至少会有一个构造方法。
这里的构造方法不能用private修饰,上面讲过构造方法private修饰的只在能该类中调用。在类外不能实例化对象
一个类里面可以有多个构造方法:
然后通过在main中实例化一个对象调用第二个带有参数的构造方法:
调用的时候注意传递的参数。
注意,如果我们把不带参数的构造方法删除则在main中实例化会报错:
上面我们讲过在类中会自动生成一个构造方法,但是当你在类中已经有构造方法存在,那么你调用的只能是你在类中建立的构造方法 。
我们会发现构造方法的名称是一样的,所以构造方法可以形成重载。