类和对象的概念
类(class)是构造对象的模板或蓝图。可以把类比作书,而对象比作一本本具体的书,比如课本,小说等。类是抽象的概念,对象是具体的实体。
对象的具体特征
- 对象的行为 —— 可以对对象施加哪些操作,或可以对对象施加哪些方法
- 对象的状态 —— 当施加哪些方法时,对象应该任何响应
- 对象标识 —— 如何辨别具有相同行为而状态不同的对象
封装
封装是将数据和行为组合在一个类中,并对对象的使用者隐藏了数据的实现方式。可以想象你在自动取款机中取钱的情形,你并不知道自动取款机是如何取出你所需要的钱的,你也不需要知道。当自动取款机的取款的原理发生改变时(可能原来的有安全隐患),但你所要做的仍然是输入取款金额,然后取钱。这就是封装的好处。
一个Java的类
1 | public class People { |
如上示例是一个表示人的Java类,下面我们来分析这个类:
首先class 类名表示一个类,这个上一篇文章介绍过,不用多说。public是公有的意思,即所以类都看。在这个类中我们定义了两个属性name和age,这个也叫做成员变量。
我们又定义了人的行为sleep和work,这个在Java中叫做方法或函数.
现在我们创建了人这个模板,那么怎么创建具体的人的对象,这就要用到new,具体代码如下:
1 | public static void main(String[] args) { |
Private
下面我们来扩展这个Java类,我们给它再添加一个是否有女朋友的属性,代码如下:
1 | public class People { |
试想一下,如果你问陌生人是否有女朋友,帅哥还好,要是一个肥仔(比如我)就不想理你;但是你可以直接调用people.isHaveGirlFriend来看我是否有女朋友,这就有点侵犯隐私了。可是我们怎么限制别人对对象的调用(即把成员变量声明为私有域)
,这就要使用private关键字,private关键字修饰的属性或方法只能再本类中可见,一般所有的成员变量要用private修饰.(之后会详细介绍Java 访问修饰符)
1 | public class People { |
同理方法用private修饰是私有方法
静态域和静态方法
静态域
有时候我们会想要使用一个概念,而不是一个具体的对象来做一些事情。比如要统计人类的总数,那就必须针对人类这个抽象概念,并且
要有属于这个抽象的变量(如人的总数这个变量),而不是每个对象的成员变量(比如说每个人的年龄,你不能说人类的年龄)。要实现这个
抽象的变量(即静态域),只需添加static关键字
1 | public class People { |
每个对象对于类的成员变量都有自己的拷贝,比如1000个人类对象,就有1000个成员变量name,但是只有一个静态域人类的总数count
注意:静态域只能通过类名.静态域变量名来直接访问,所有也可以称为类域
静态常量
静态常量即可以直接通过类名.常量名直接访问的量,格式如下:
1 | public static final int COUNT = 1; |
静态方法
静态方法是只能通过类名.静态方法名调用的方法;静态方法的定义和静态域一样,只需要加上一个static即可。
注意:静态方法只能访问类中的静态域,而不是类的成员变量
方法
方法的定义访问修饰符 返回值 方法名(参数类型 参数名 ...){ }
1 | public void sleep(){System.out.println("睡觉");}//修饰符为public void表示无返回值 sleep是方法名 System.out.println("睡觉");是方法执行的功能 |
注意:return会结束所在的方法,例如
1 | public void sleep() |
局部变量
- 局部变量声明在方法、构造方法或者语句块中;
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁;
- 访问修饰符不能用于局部变量;
- 局部变量只在声明它的方法、构造方法或者语句块中可见;
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
成员变量(实例变量)
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
- 当一个对象被实例化之后,每个实例变量的值就跟着确定;
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁;
- 访问修饰符可以修饰实例变量;
- 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见;
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定;
- 实例变量可以直接通过变量名访问
重载
如果多个方法有相同的名字,不同的参数,那这多个方法重载。例如:
1 | public boolean equal(int a,int b){ |
注意:Java允许重载任何方法。因此要完整地描述一个方法,需要指出方法名以及参数类型,这叫做方法
的签名。返回类型不是方法签名的一部分。
构造器
1 | public 类名(参数...){ |
构造器的语法:
- 构造器与类名相同
- 每个类可以有一个以上的构造器,如在类中没有显示的声明一个构造器,系统就会提供一个无参数的构造器
- 构造器可以有0个,1个或多个参数
- 构造器没有返回值
- 构造器总是伴随着
new操作一起调用 - 构造器中不能定义与成员变量同名的局部变量
注意:仅当类没有提供任何构造器的时候,系统才会提供一个默认的构造器。如果自己给出了一个构造器,要想使用系统默认的构造器就必须自己
提供一个默认构造器
1 |
|
this
this关键字表示这个对象的引用
作用1:引用方法的隐式参数
1 | public People(String name){ |
作用2:调用构造器
1 | public People(){//默认构造器 |
对象变量(或引用变量)
我们已经知道People people1 = new People();是获取一个对象的引用;实际上一个对象变量有没有包含一个对象,而仅仅是
引用一个对象。在Java中任何对象变量的值都是对储存在另一个地方的一个对象的引用。new操作符的返回值也是一个引用,如图:

注意:People people;没有引用对象
方法参数
按值调用 : 表示方法接受的是调用者提供的值,Java是按值调用
按引用调用 : 表示方法接受的是调用者提供的变量地址
Java中方法参数的使用情况:
- 一个方法不能修改一个基本类型的参数
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象
包
在定义一个类时,要给类取名字,类名一般要根据类的作用来取,而不是毫无意义的字符;不过随着定义的类
越来越多,类名很有可能重复。为了解决这个问题,我们就采用包(package)
类的导入
我们使用别的包中的公有类时,我们有两种方式来访问:第一种是通过每个类前面直接添加完整的包名。如:
1 | java.time.LocalDate localDate = java.time.LocalDate.now(); |
第二种是导入类,导入类的关键字import,语法如下
1 | import 包名.类名;//导入单个类 |
例如:
1 | import java.time.LocalDate; |
注意:如果一个类中出现重名的类,编译器无法确定使用哪个;那就必须在每一个(重名的)类名
前面加上完整的包名
静态导入
import不仅可以导入类,还可以导入静态方法和静态域
例如
1 | import static java.lang.System.*;//之后就可以直接使用System的静态方法和静态变量 |
将类放入包中
要想将一个类放入包中,就必须将包的名字放在源文件的开头,包中定义类的代码之前。例如:
1 | package com.demo.core; |
包的作用域
如果类或类中变量,方法没有被private或public修饰,那么这个部分(类,方法和变量)可以被同一包中所有方法访问
类设计技巧
- 一定要保证数据私有
- 一定要对数据初始化
- 不要在类中使用过多的基本类型
- 不是所有的域都需要独立的域访问器和域修改器
- 将职责过多的类进行分解
- 类名和方法名要能够体现它们的职责
- 优先使用不可变的类