目录
一、面向对象概念
–面向对象是一种符合人类思维习惯的编程思想。现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
–面向过程就是分析解决问题所需要的步骤,面向对象则是把解决的问题按照一定规则划分为多个独立的对象,然后通过调用对象的方法来解决问题。
–面向对象的特点主要可以概括为封装性、继承性和多态性。
–面向对象的编程思想力图在程序中对事物的描述与该事物在现实中的形态保持一致。为了做到这一点,面向对象的思想中提出两个概念,即类和对象。
–类是对某一类事物的抽象描述,而对象用于表示现实中该类事物的个体。类和对象的关系如同玩具和玩具模型的关系。
可以将玩具模型看作是一个类,将一个个玩具看作对象,从玩具模型和玩具之间的关系便可以看出类与对象之间的关系。类用于描述多个对象的共同特征,它是对象的模板。对象用于描述现实中的个体,它是类的实例,并且一个类可以对应多个对象
二、类的定义
在面向对象的思想中最核心就是对象,为了在程序中创建对象,首先需要定义一个类。
类是对象的抽象,它用于描述一组对象的共同特征和行为类中可以定义成员变量和成员方法,其中成员变量用于描述对象的特征,也被称作属性,成员方法用于描述对象的行为,可简称为方法
三、对象的创建和使用
在Java程序中可以使用new关键字来创建对象,具体格式如下:
类名 对象名 = new 类名();
Person p = new Person();
“new Person()”用于创建Person类的一个实例对象,“Person p”则是声明了一个Person类型的变量p。中间的等号用于将Person对象在内存中的地址赋值给变量p,这样变量p便持有了对象的引用,变量p和对象之间的引用关系如下图所示。
在创建Person对象后,可以通过对象的引用来访问对象所有的成员,具体格式如下:
对象.类成员
例子如下:
class A{ // 类A public int age; // 类属性 public void show() { // 类方法 System.out.println("age = "+age); } } public class MainClass { // 主类Mainclass public static void main(String[] args) { A aa = new A(); // 利用类A创建类对象 aa.age = 50; // 给类属性赋值 aa.show(); // 调用类方法 } }
Java虚拟机赋予成员变量的初始化值
变量类型 | 初始值 |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0 |
char | 空字符,"\u0000" |
boolean | false |
引用数据类型 | null |
四、类的封装
所谓类的封装是指在定义一个类时,将类中的属性私有化,即使用private关键字来修饰,私有属性只能在它所在类中被访问,为了能让外界访问私有属性,需要提供一些使用public修饰的公有方法,其中包括用于获取属性值的getXXX方法和设置属性值的setXXX方法
package 类和对象;
class Person{
// 访问权限private
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class MainClass { // 主类Mainclass
public static void main(String[] args) {
Person p = new Person();
// 给类属性赋值
p.setAge(18);
p.setName("小明");
System.out.println(p.getName()+":"+p.getAge());
}
}
使用private关键字将属性name和age声明为私有getName()方法用于获取name属性的值,setName()方法用于设置name属性的值getAge()和setAge()方法用于获取和设置age属性的值。在setAge()方法中对参数stuAge的值进行检查,
五、构造方法的定义
在一个类中定义的方法如果同时满足以下三个条件,该方法称为构造方法,具体如下:
1.方法名和类名相同
2.方法名的前面没有返回值类型的声明
3.方法中不能使用return语句返回一个值
在一个类中除了定义无参的构造方法,还可以定义有参的构造方法,通过有参的构造方法就可以实现对属性的赋值
class Person{
protected int age;
public Person() { // 无参构造方法
System.out.println("无参构造方法被调用!");
}
public Person(int value) { // 有参构造方法
age = value;
System.out.println("有参构造方法被调用!");
}
}
public class MainClass { // 主类Mainclass
public static void main(String[] args) {
// 创建类对象的同时调用构造方法
Person p1 = new Person();
Person p2 = new Person(50);
}
}
在Java中的每个类都至少有一个构造方法,如果在一个类中没有定义构造方法,系统会自动为这个类创建一个默认的构造方法,这个默认的构造方法没有参数,在其方法体中没有任何代码,即什么也不做。
如果为该类定义了构造方法,系统就不再提供默认的构造方法了
六、this关键字
1、通过this关键字可以明确地去访问一个类的成员变量,解决与局部变量名称冲突问题,具体示例如下:
class Person{ protected int age; public Person(int age) { this.age = age; // 把局部变量的值赋给类属性 } public int Get_age() { return this.age; } }
在上面的代码中,构造方法的参数被定义为age,它是一个局部变量,在类中还定义了一个成员变量,名称也是age。在构造方法中如果使用“age”,则是访问局部变量,但如果使用“this.age”则是访问成员变量。
2、通过this关键字调用成员方法,具体示例代码如下:
在下面的show()方法中,使用this关键字调用open()方法。注意,此处的this关键字可以省略不写,也就是说上面的第6行代码写成“this.open()”和“open()”,效果是完全一样的
class Person{ protected int age; public void show() { this.open(); } public void open() { } }
3、构造方法是在实例化对象时被Java虚拟机自动调用的,在程序中不能像调用其它方法一样去调用构造方法,但可以在一个构造方法中使用“this([参数1,参数2…])”的形式来调用其它的构造方法通过this关键字调用成员方法
class Person{ protected int age; public Person() { System.out.println("无参构造方法被调用!"); } public Person(int value) { this(); // 调用无参构造方法 System.out.println("有参构造方法被调用!"); } } public class MainClass { // 主类Mainclass public static void main(String[] args) { Person p = new Person(50); } }
注意:
1、只能在构造方法中使用this调用其它的构造方法
2、在构造方法中,使用this调用构造方法的语句必须位于第一行,且只能出现一次
3、不能在一个类的两个构造方法中使用this互相调用
七、垃圾回收
当一个对象成为垃圾后仍会占用内存空间,时间一长,就会导致内存空间的不足。针对这种情况,Java中引入了垃圾回收机制
Java虚拟机就会启动垃圾回收器将这些垃圾对象从内存中释放,从而使程序获得更多可用的内存空间
除了等待Java虚拟机进行自动垃圾回收,也可以通过调用System.gc()方法来通知Java虚拟机立即进行垃圾回收。当一个对象在内存中被释放时,它的finalize()方法会被自动调用
class Person{
// 下面方法将会在垃圾回收之前会调用
public void finalize() {
System.out.println("对象将作为垃圾被回收!");
}
}
public class MainClass {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
// 让对象成为垃圾
p1 = null;
p2 = null;
// 调用方法进行垃圾回收
System.gc();
}
}
Person类中定义了一个finalize()方法,该方法的返回值必须为void,并且要使用public来修饰。在main()方法中创建了两个对象p1和p2,然后将两个变量置为null,这意味着新创建的两个对象成为垃圾了,紧接着通过“System.gc()”语句通知虚拟机进行垃圾回收。从运行结果可以看出,虚拟机针对两个垃圾对象进行了回收,并在回收之前分别调用两个对象的finalize()方法。
八、static关键字
静态变量
在一个Java类中,可以使用static关键字来修饰成员变量,该变量被称作静态变量
静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问
static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则编译会报错,下面的代码是非法的。
public class MainClass {
public static void main(String[] args) {
static int num = 10; // error
}
}
静态方法
被static关键字修饰的方法称为静态方法
同静态变量一样,静态方法可以使用“类名.方法名”的方式来访问,也可以通过类的实例对象来访问。
在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时可以不创建任何对象。
class Person{
public static int age; // 静态属性
}
public class MainClass {
public static void main(String[] args) { // 静态方法
Person p = new Person();
p.age = 60; // 通过对象名赋值
System.out.println("age = "+p.age);
Person.age = 18; // 通过类名赋值
System.out.println("age = "+Person.age);
}
}
静态代码块
在Java类中,使用一对大括号包围起来的若干行代码被称为一个代码块,用static关键字修饰的代码块称为静态代码块
当类被加载时,静态代码块会执行,由于类只加载一次,因此静态代码块只执行一次
在程序中,通常使用静态代码块来对类的成员变量进行初始化
package 类和对象;
class Person{
public static int age;
// 静态代码块
static {
age = 50;
System.out.println("Person类的静态代码块被执行!");
}
}
public class MainClass {
// 静态代码块
static {
System.out.println("静态代码块已执行!");
}
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
}
}
从运行结果可以看出,程序中的两段静态代码块都执行了,虚拟机首先会先加载主类,在加载类的同时就会执行该类的静态代码块,紧接着会调用main()方法。在该方法中创建了两个Person对象,但在两次实例化对象的过程中,静态代码块只执行一次,这就说明类在第一次使用时才会被加载,并且只会加载一次
单例模式
设计模式就是针对这些问题和需求,在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式
单例模式是Java中的一种设计模式,它是指在设计一个类时,需要保证在整个程序运行期间针对该类只存在一个实例对象
看一个实现了单例模式的类
class Person{
private static Person INSTANCE = new Person();// 自己创建一个对象
private Person() { // 私有化构造方法
}
public static Person getINSTANCE() { // 提供返回该对象的静态方法
return INSTANCE;
}
}
类的构造方法使用private修饰,声明为私有,这样就不能在类的外部使用new关键字来创建实例对象了。
在类的内部创建一个该类的实例对象,并使用静态变量INSTANCE引用该对象,由于变量应该禁止外界直接访问,因此使用private修饰,声明为私有成员
为了让类的外部能够获得类的实例对象,需要定义一个静态方法getInstance(),用于返回该类实例INSTANCE。由于方法是静态的,外界可以通过“类名.方法名”的方式来访问