对象和类
对象
Java 是面向对象的编程语言,独立的个体就是对象(Object),对象就是面向对象程序设计的核心。
对象之间相互协作,共同实现程序的功能。
用人话就是对象是真实存在的具体实例
对象具有以下特点:
-
属性:个体的状态信息(数据)
-
行为:个体能够做什么(操作)
如何得到对象?
创建程序中的对象也需要一个“模板”,这个创建对象的“模板”,就叫做 [[#类|类]](class)
对象的创建
对象的创建一般在方法中进行。语法:
类名 对象名 = new 类名();
Student student = new Student();
- 类名表示创建的是何种对象,对象的类型是什么
- 对象名是引用数据类型的引用,命名遵循小驼峰命名法
- new关键字 表示在 堆上 开辟空间创建对象
对象的使用
如果不创建对象,不能直接访问类中的成员变量和成员方法
注意:
- 无论成员变量还是成员方法,都是属于对象的,必须创建对象才能访问他们
- 实际上不同对象,访问类中统一成员变量和成员方法的结果完全可能是不同的
对象创建出来后,可以:
- 直接输入对象名
- 使用对象获取对象的属性和行为
- 访问属性
获取属性值:数据类型 变量名 = 对象.成员变量;
修改属性值:对象名.成员变量 = 某值;
- 调用行为(方法)
对象名.成员方法名(实参);
- 访问属性
类
创建对象的模板就是类,类就是创建对象的模板
类抽取了同类别的所有对象属性和行为上的共性,一个类可以描述千千万万个对象。
对象就是一个一个的实例。类就是模板, 类是创建对象的一个蓝本。
类是共同特征的描述
语法:
[访问权限修饰符] class 类名{
// 类体
}
类中的成员
- 成员变量:描述对象的共有属性
定义在类体中,方法外的变量,就称之为成员变量
[访问权限修饰符] 数据类型 变量名
public String name;
public int age;
public void method(){
}
成员变量在整个类体中生效,在整个类中的成员方法中都可以访问它
- 成员方法:描述对象的共有行为
[访问权限修饰符] 返回值类型 方法名(形参列表){
方法体
}
- 构造方法
- 代码块
- 内部类
引用数据类型
数据类型是 一组数据集合 + 基于该数据集合的一组合法操作
在Java中,除了[[2.1 基本概念#基本数据类型|基本数据类型]]之外,其他的都是引用数据类型。
引用数据类型是 成员变量的集合 + 成员方法的集合 → 类实际上就是定义了一种全新的数据类型
类加载
对于 类这种引用数据类型,是我们自定义的数据类型,JVM并不“认识”他,JVM不知道类中有什么,所以在对某个类做任何操作之前,都需要让JVM来 “认识” 这个类型
在Java中,把JVM “认识” 一个类的过程叫做 类加载
成员变量和局部变量
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置 | 类中,方法外 | 方法内,方法申明(形参位置)上 |
初始化值 | 有默认初始化值 | 没有,使用之前需要完成赋值 |
内存位置 | 堆内存 | 栈内存 |
生命周期 | 随着对象的创建而存在, 随着对象的消失而消失 | 随着方法的调用而存在, 随着方法的运行结束而消失 |
作用域 | 整个类中有效 | 当前方法中有效 |
[[静态成员变量]]: static + 成员变量
[[成员变量的赋值]]
this关键字
当方法中存在同名的局部变量和成员变量时,受到 就近原则 的影响,访问该同名变量时,访问到的必然是距离访问语句更近的局部变量。这时候如果还想访问同名成员变量,就需要 this关键字 来实现
Java类中的每个成员方法的形参列表中都隐含了一个传参(隐式传参),传入的是当前对象,用this关键字指向!
所以:
- this是一个引用,这个引用指向 当前对象
- 什么是 当前对象 ?
this指向的当前对象,是类中成员方法的一个隐式传参
成员方法需要一个对象名来调用,这个调用该成员方法的对象就是当前对象
作用:
- 在成员方法中,用this引用去访问类中成员变量,以及调用类中成员方法。
- 当 成员方法中的局部变量和成员变量同名时,可以用 “this.” 来访问同名成员变量
- 在成员方法中只要使用 “this.” 来访问一个变量,那么该变量一定是成员变量。可以使用 “this.成员变量” 对成员变量进行赋值 (set方法)
构造方法
构造方法也叫构造器、构造函数
语法:
[访问权限修饰符] 类名(形参列表){
方法体
}
public Student(){
}
作用:在创建对象的时候给成员变量进行赋值,完成对对象的初始化
使用:
new 类名(实参列表);
通过实参列表的不同来判断调用哪个构造器,这实际上也是 [[方法重载]] 的应用
注意事项:
- 构造方法的方法名必须与类名相同,大小写也要一致
- 构造方法没有返回值类型,也没有具体的返回值(不由return带回结果数据)
- 一个类中是允许同时定义多个构造方法的,即 [[构造方法重载]] ,多个构造器的形参必须不同
- 实际执行时,创建对象的时候由虚拟机JVM调用,不能手动调用构造方法
- 每创建一次对象,JVM就会调用一次构造方法
static关键字
根据static修饰内容不同分为:
- 静态成员变量
- 静态成员方法
统称为类的 静态成员
Static在工作过程中,一般有两个用途:
- 写方法,一些工具方法
- 写常量,给了值之后不会改的常量
静态成员变量
语法:
[访问权限修饰符] static 数据类型 变量名;
特点:
- 具有默认值
- 静态成员变量属于类,不需要创建对象使用
- 访问和使用静态成员变量不推荐使用 “对象名.” ,应该使用 “类名.”
- 静态成员变量的访问、赋值、使用都只依赖于类、
- 随着类加载完毕,静态成员就存在,并且能够使用了!
- 某个类的某个静态成员变量只有一份,且被所有对象共享
静态成员方法
语法:
[访问权限修饰符] static 返回值类型 方法名(形参列表){
方法体
}
特点:
- 无需创建对象即可直接通过 “类名.” 调用
- 同一个类中的static方法互相调用可以忽略类名直接用方法名调用
- 一个类中,静态方法无法直接调用非静态的方法和属性,静态方法只能访问静态的
静态成员方法能访问:静态成员变量、静态成员方法
成员方法能访问:静态成员变量、静态成员方法、成员变量、成员方法
static & 非static
- 所属不同
- 静态成员变量属于类,所以也称为为类变量
- (普通)成员变量属于对象,所以也称为对象变量(实例变量)
- 在内存中的位置不同
- 静态变量存储于方法区的静态域(堆上的这个类所对应的字节码文件对象,即Class对象中),被所有对象共享
- 成员变量存储于堆内存,每个对象独享自己的成员变量
- 在内存中出现时间不同
- 静态变量随着类的加载而加载,比成员变量出现的要早
- 成员变量随着对象的创建而存在
- 调用方式不同
- 静态变量可以通过类名调用,也可以通过对象调用(不推荐)
- 成员变量只能通过对象名调用,必须创建对象
使用场景
- 静态成员变量:
- 属于全体对象所 共享 而不是独属于某个对象的成员变量
- 在整个类 全局独一份的
- 静态成员方法:
- 调用简单,无需创建对象时
- 当一个类中全部都是静态成员方法时。 → 这就是Java中的 “工具类”
对比
匿名对象
什么是匿名对象
在Java当中,匿名对象指的就是没有名字的对象。
或者,说的更清楚一点,就是:在创建对象时,就没有引用指向的对象,就是匿名对象!
匿名对象的语法很简单,只需要在方法等位置中写下列语法:
// 没有名字指向它,这时候它就是一个匿名对象。
new 类名();
以上语法就得到了一个匿名对象,从实质上看:
该对象没有栈上的引用指向,没有所谓的 “对象名”,是一个匿名对象。
匿名对象的用途
- 使用匿名对象作为方法的实参
当定义以下方法时,表示该方法需要传入一个对象(这个对象必须是"类名"的对象或者子类对象)
[修饰符列表] 返回值类型 方法名(类名 对象名){
//方法体
}
这个时候,常规的做法是创建对象,然后传入引用。但实际上这里可以直接传入匿名对象。
假如一个test方法需要传入一个Student对象,就可以这么写:
test(new Student());
- 使用匿名对象作为方法的返回值
当定义以下方法时,表示该方法需要传入一个对象(这个对象必须是"类名"的对象或者子类对象)
[访问权限修饰符] 类名 方法名(形参列表){
//方法体
return (匿名对象);
}
匿名对象的优缺点
- 优点:
- 使用匿名对象,代码简洁(相当于少写了一些代码)这是匿名对象最主要的优点。
- 匿名对象在使用完毕后会立刻成为"垃圾"等待GC回收,从理论角度上来说,可以提升内存利用率。
但是GC不具有即时性,并不是一个对象更早成为"垃圾"就会更好回收,这个优点仅是理论上的。
- 缺点:
匿名对象由于没有引用指向,所以它是一次性的,用完后就无法再次使用了。
匿名对象使用场景
- 需要一个对象去实现功能,并且该对象仅需使用一次即可,为了代码简洁,推荐使用匿名对象
- 但是,如果一个对象可能会被复用,如果频繁创建匿名对象是得不偿失的
不要滥用匿名对象,创建对象是需要耗时耗费内存空间的,不要为了一时的方便,频繁创建匿名对象。
总之:
如果某个对象,仅使用一次,使用匿名对象简洁方便。
但如果有多次使用某个类的对象的需求时,频繁使用匿名对象会导致频繁创建对象,降低代码性能,得不偿失!
代码块
由若干条Java语句组成,并且用一对大括号括起来的结构,叫做代码块。
根据位置和声明方法的不同可分为:
- 局部代码块(方法)
- 构造代码块
- 静态代码块
导包
package关键字
包就是文件夹,用来管理各种不同功能的java类,方便后期代码维护
类的开头会用 package关键字 指明包名:
package com.cskaoyan.domain
全限定类名
com.cskaoyan.domain.Student
就是全限定类名
如果想要使用其它类时,就需要使用全限定类名
import关键字
使用其他类时,如果每次都写全限定类名太麻烦了,可以在类的开头 用import关键字声明包名,类中即可直接调用:
import com.cskaoyan.domain.Student
这个过程就叫做 导包
使用其它类的规则:
- 使用同一个包中的类时,不需要导包
- 使用 java.lang 包中的类时,不需要导包
- 其他情况都需要导包
- 如果同时使用两个包中的同名类,就需要使用全限定类名
访问权限修饰符
Java的访问权限的级别,是依赖包(package)来实现的。
Java的访问权限级别共分为以下四个级别,访问权限从严格到宽松顺序为:
-
private: 只能够在同一类中能够访问,私有的,外面谁都不能用。
-
缺省(默认): 同一包中的子类或者其它类能够访问,同包中都可以使用。不同包,不能使用。
-
protected: 不同包的子类能够访问。(这个访问级别继承再学习)
-
public: 不同包的其他类能够访问。
在实际开发中,使用类中结构的访问权限修饰符的原则:
- 尽量私有化,方便自己修改代码,隐藏实现细节。
- 如果不能私有化,那也应该尽量少的给予访问权限,先从默认权限开始考虑。
- 只有确定这个结构,一定需要在外部(尤其是不同包下)被访问时,才考虑给public,尽量少给public。
权限这个东西,要吝啬,不要 “大方”!