类与对象

1 基本内容

建模全宇宙,用有限的代码描述无限的世界

类的定义

属性和方法(变量和函数),对象即实例。放到一起就是对象。面相对象的本质就是以类的方式组织代码,以对象组织封装数据。OOP:Object oriented programming

抽象,把共同的部分抽取出来,组成一个类。

一个项目应该只存在一个主启动类。

  • 对象:对象是类的一个实例
  • 类:类是一个模板,它描述一类对象的行为和状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Dog {
String breed;
int size;
String colour;
int age;

void eat() {
}

void run() {
}

void sleep(){
}

void name(){
}
}

五种成分

类中有且仅有5大成分(五大金刚)

  • 成员变量Field:描述类或者对象的属性信息的。
  • 成员方法Method:描述类或者对象的行为的。
  • 构造器(构造方法)Constructor: 初始化类的一个对象返回。
  • 代码块Block:代码块按照有无static可以分为静态代码块和实例代码块。
  • 内部类InnerClass:将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

访问权限修饰符

一个类的成员变量或成员方法

  • 如果被修饰为private,则只能在本类中使用,在子类中不可使用,并且在其他包的类中是不可见的。
  • 如果被修饰为public,则在子类和其他包的类中可以使用。
  • 如果被修饰为protect,则仅在子类中可以使用。
  • 如果没有权限修饰符,默认访问权限为整个包。

2 成员变量Field

变量类型

  • 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
  • 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中的成员方法、构造方法和特定类的语句块访问。只能通过实例化的对象进行访问
  • 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。只能通过类名进行访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.ykl.extentions;

/**
* 验证静态变量能够被类的实例访问
*/

class Book{
private String name;
private int price;
static final String id="BOOK";
public static void main(String[] args) {
Book book = new Book();
System.out.println(book.name);
System.out.println(book.price);
// 事实证明这三种方法都能够访问到类变量
System.out.println(id);
System.out.println(Book.id);
System.out.println(book.id);
}
}

成员变量

在Java中对象的属性称为成员变量。为了了解成员变量,在下面的代码中首先定义一个图书类,成员变量对应于类对象的属性,在Book类中设置3个成员变量,分别为id,name和category,分别对应于图书编号,图书名称和图书类别3个图书属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Book{
private String name; //定义一个String类型的成员变量
public String getName(){ //定义一个getName()方法
int id=0; //局部变量
setName=("java"); //调用类中其他方法
return id+this.name; //设置方法返回值
}
public void setName(String name){ //定义一个setName()方法
this.name=name; //将参数赋值于类中的成员变量
}
public Book getBook(){
return this; //返回Book类引用
}
}

成员变量可以设置初始值,也可以不设置,如果不设置初始值,则会有默认值。

初始化顺序

Java类中各元素的初始化顺序 初始化的原则是:

先初始化静态部分,再初始化动态部分;(先静再动)
先初始化父类部分,后初始化子类部分;(先父再子)
先初始化变量,次初始化代码块,再初始化构造器;(先变量,次代码块,再构造器)
所以依照这个规则可以得出总体顺序是:

1
2
3
4
5
6
7
8
9
10
1.父类的静态成员变量(第一次加载类时):父静成
2.父类的静态代码块(第一次加载类时):父静块
3.子类的静态成员变量(第一次加载类时):子静成
4.子类的静态代码块(第一次加载类时):子静块
5.父类的普通成员变量:父成
6.父类的动态代码块:父块
7.父类的构造器方法:父构
8.子类的普通成员变量:子成
9.子类的动态代码块:子块
10.子类的构造器方法:子构

3 成员方法Method

一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量。同时成员方法有返回值和不返回任何值的选择,如果需要返回值,可以在方法体中使用return关键字,返回值可以是计算结果,也可以是其他想要的数值和对象,无返回值可以使用void关键字表示。

在成员方法中可以调用其他成员方法和类成员变量,例如上述代码中getName()方法中就调用了setName()方法将图书名称赋予一个值。

4 构造方法Constructor

构造方法

用于返回一个类的对象,同时把对象的数据初始化好。

  1. 每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。一旦定义了有参构造,无参构造就需要显示定义。
  2. 在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。
  3. 和类名相同,没有返回值,一般为public。
1
2
3
4
5
6
7
8
public class Puppy{
public Puppy(){
}

public Puppy(String name){
// 这个构造器仅有一个参数:name
}
}

对象创建

  • 声明:声明一个对象,包括对象名称和对象类型。
  • 实例化:使用关键字 new 来创建一个对象。
  • 初始化:使用 new 创建对象时,会调用构造方法初始化对象。首先分配对象空间,然后使用构造函数,初始化一些列对象的值。

访问对象

  1. 访问对象的成员变量(属性)
  2. 访问对象的函数成员(方法)
1
2
3
4
5
6
/* 实例化对象 */
Object referenceVariable = new Constructor();
/* 访问类中的变量 */
referenceVariable.variableName;
/* 访问类中的方法 */
referenceVariable.methodName();

5 代码块CodeBlock

静态代码块

静态代码块
​ 必须有static修饰,必须放在类下。与类一起加载执行。

格式

1
2
3
static{
// 执行代码
}

特点

  • 每次执行类,加载类的时候都会先执行静态代码块一次。
  • 静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次。
  • 作用:在启动程序之前可以做资源的初始化,一般用于初始化静态资源。注册驱动、加载 native 库、埋监控;

案例演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DaimaKuaiDemo01 {
public static String name ;

// 1.静态代码块
static {
// 初始化静态资源
name = "张三";
System.out.println("静态代码块执行!");
}

public static void main(String[] args) {
System.out.println("main方法执行");
System.out.println(name);
}
}

实例代码块

实例代码块
​ 没有static修饰,必须放在类下。与对象初始化一起加载。且先于构造函数执行。

格式

1
2
3
{
// 执行代码
}

特点

  • 无static修饰。属于对象,与对象的创建一起执行的。
  • 每次调用构造器初始化对象,实例代码块都要自动触发执行一次。
  • 实例代码块实际上是提取到每一个构造器中去执行的。且先于构造函数执行。
  • 作用:实例代码块用于初始化对象的资源。例如:设置复杂的初始值,

案例演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DaimaKuaiDemo02 {

private String name ;

// 实例代码块。 无static修饰。
{
System.out.println("实例代码块执行");
name = "dl";
}

// 构造器
public DaimaKuaiDemo02(){
//System.out.println("实例代码块执行");
}

// 有参数构造器
public DaimaKuaiDemo02(String name){
//System.out.println("实例代码块执行");
}

public static void main(String[] args) {
// 匿名对象,创建出来没有给变量。
new DaimaKuaiDemo02();
new DaimaKuaiDemo02();
new DaimaKuaiDemo02("xulei");
}
}
// 输出三次:实例代码块执行

6 内部类InnerClass

见内部类部分

7 关键字

final

可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写

1
final class 类名 {//类体}

this

this关键字:指向自己的引用。采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。访问当前对象的实例变量。调用重载的构造方法:

  1. 可以在构造方法中,通过this调用本类的另一个构造方法,且必须置于第一行。
  2. 可以通过this调用本类中带参或无参构造方法,调用带参构造方法时,需要按顺序传入设定的参数。
  3. 在一个构造方法内只能调用一个构造方法。
  4. 不能在类中普通成员方法内通过this调用构造方法。

super

super关键字来实现对父类成员的访问,用来引用当前对象的父类。

  • 子类的构造函数会默认调用父类的无参构造函数。而且通过super()方法调用父类的构造器,必须放在子类构造器的第一行。
  • 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。应该注意到,子类一定会调用父类的构造函数来完成初始化工作,一般是调用父类的默认构造函数,如果子类需要调用父类其它构造函数,那么就可以使用 super() 函数。
  • 访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SuperExample {

protected int x;
protected int y;

public SuperExample(int x, int y) {
this.x = x;
this.y = y;
}

public void func() {
System.out.println("SuperExample.func()");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SuperExtendExample extends SuperExample {

private int z;

public SuperExtendExample(int x, int y, int z) {
super(x, y);
this.z = z;
}

@Override
public void func() {
super.func();
System.out.println("SuperExtendExample.func()");
}
}

instanceof

运算符 对象运算符(instanceof)用来判断一个对象是否属于某个指定的类或其子类的实例,如果是,返回真(true),否则返回假(false)