文章目录
什么是面向对象?
Java是一门面向对象的语言(Object Oriented Program,简称OOP)。而面向对象呢,则是一种解决问题的思想:它主要依靠对象之间的交互来完成一件事情。我们平时解决问题时通常会采用面向过程的思想,即:依靠一步步完成具体步骤来完成一件事情。那这两者有什么区别呢?
我们以洗衣服为例:
注: 面向对象和面向过程都只是解决问题的方法,没有好坏之分,都有其对应的应用场景。 只是Java采用了面向对象的思想罢了。
认识类
既然我们是要面向对象编程,那么什么是对象呢? 对象就是现实生活中存在的实体(具体的东西,比如 洗衣机)。现实中我们操作洗衣机就需要知道它的各项参数,像最大容纳数、电压、功率等待;而我们在面向对象编程的时候同样也需要知道这些参数,那这些参数保存在哪里呢? 保存在类里! 类就是用来对一个实体对象进行描述的
类的定义格式
//创建类
class ClassName{ //ClassName是类名,可以根据场景自己定义
field; //属性,也叫做成员属性
method; //行为,也叫做成员方法
}
//以洗衣机为例,具体完整的定义一个类
class WashMachine{
public String brand; //品牌
public String type; //型号
public String color; //颜色
public double weight; //重量
public double length; //长度
public double height; //高度
public void washClothes(){ //洗衣服的行为
}
public void dryClothes(){ //甩干衣服的行为
}
}
注: 类名使用大驼峰定义。
类的实例化
定义了一个类,就相当于在计算机中自定义了一种新的类型,与int、double这样的基本数据类型相似。要想使用就要借助变量来存储数据,只不过在使用类时这里的变量叫做“对象”罢了。
类的实例化:就是用类 类型来创建对象的过程。
public static void main(String[] args) {
WashMachine washMachine = new WashMachine(); //用new来创建对象 类似于创建变量的过程
String brand = washMachine.brand; //使用对象来获取到属性
washMachine.washClothes(); //使用对象来使用类中的方法
}
注:
- new关键字用于创建一个对象的实例。
- 使用 . 来访问对象中的属性和方法。
- 一个类可以创建多个对象,每个对象都包含这个类完整的属性和方法。
理解this引用
什么是this引用呢? this引用的是调用成员方法的对象,在成员方法中所有成员变量的属性,都是通过该引用去访问的。
class WashMachine{
public double weight; //重量
public double length; //长度
public double height; //高度
public void setValue(double weight,double length, double height){
this.weight = weight;
this.length = length;
this.height = height;
}
}
public class test {
public static void main(String[] args) {
WashMachine washMachine = new WashMachine();
washMachine.setValue(20.0,100.0,80.0);
}
}
注:
- this只能在成员方法中使用;
- 在成员方法中,this只能引用当前对象,不能引用其他对象。
对象的构造及初始化
通过new创建出对象后,对象内的属性值是空值,我们一般使用时都需要对其赋值。那怎样赋值呢? 就会用到构造方法。
什么是构造方法?
构造方法是一个特殊的成员方法,它的作用是对 对象中的成员进行初始化,并不负责给对象开辟内存空间。
public WashMachine(double weight, double length, double height){
this.weight = weight;
this.length = length;
this.height = height;
}
注:
- 构造方法名字必须与类名相同。
- 没有返回值类型,设置成void也不行;
- 构造方法在创建对象时,由编译器自动调用,并且在对象的生命周期内只调用一次。
- 构造方法可以重载:用户可以根据自己的需求提供不同参数的构造方法
public WashMachine(){ } //带有一个参数的构造方法 public WashMachine(double weight){ this.weight = weight; } //带有俩个参数的构造方法 public WashMachine(double weight, double length){ this.weight = weight; this.length = length; } //带有三个参数的构造方法 public WashMachine(double weight, double length, double height){ this.weight = weight; this.length = length; this.height = height; } ``` 5. 如果用户没有显示定义,编译器会默认生成一个无参的构造方法。 6. 在构造方法中可以通过this调用其他的构造方法来简化代码。 ```java //无参的构造方法 public WashMachine(){ // 在无参的构造方法中通过this调用有三个参数的构造方法 this(20.0,100.0,80.0); } ``` + 在这种情况下,this(...)必须是构造方法的第一条语句,不然会报错。 + 不能形成环,即嵌套调用: ```java //无参的构造方法 public WashMachine(){ // 在无参的构造方法中通过this调用有三个参数的构造方法 this(20.0,100.0,80.0); } //带有三个参数的构造方法 public WashMachine(double weight,double length,double height){ // 在带有三个构造方法中调用无参的构造方法 this(); } ``` 7. 大部分情况下构造方法用public修饰,特殊情况下用private修饰(单例模式)
如何进行初始化?
默认初始化
在搞清楚默认初始化是怎样执行前,我们需要先明白new操作到底是怎样执行的(干了些什么事儿)?
-
检测对应的类是否加载了,如果没有则加载。
-
为对象分配内存空间
-
处理并发安全问题
-
初始化所分配的空间,这就是我们这里的默认初始化
-
设置对象头信息
-
调用构造方法给对象中的每个成员赋值
就地初始化
在声明成员变量时,就直接给出初始值。 (不常用)
class WashMachine {
public double weight = 20.0; //重量
public double length = 100.0; //长度
public double height = 80.0; //高度
}
认识static
在Java中,被static修饰的成员称为静态成员,也可以称为类成员。其不属于某个具体的对象,而是所有对象共享的(所有对象都公有的一个属性)。
static修饰成员变量
class WashMachine{
public double weight = 20.0;
public double length = 100.0;
public static double height = 80.0;
}
public class test {
public static void main(String[] args) {
//可以直接通过类名访问
double height = WashMachine.height;
//也可以通过对象访问
WashMachine washMachine = new WashMachine();
double height1 = washMachine.height;
}
}
注:
- 既可以通过对象访问,又可以通过类名访问。更推荐用类名访问。
- 生命周期伴随类的一生:随类的加载而创建,随类的卸载而销毁。
static修饰成员方法
class WashMachine{
public static double height = 80.0;
public static void sayHi(){
System.out.println("hi");
}
}
public class test {
public static void main(String[] args) {
//通过类名访问静态方法
WashMachine.sayHi();
//通过对象访问静态方法
WashMachine washMachine = new WashMachine();
washMachine.sayHi();
}
}
注:
- 可以使用对象调用,也可以使用类名调用。更推荐使用类名调用。
- 不能在静态方法中访问任何的非静态成员变量。因为静态方法是随着类加载而加载的,而非静态的成员变量得创建对象时才有加载的时机较晚,在使用静态方法时还没有非静态的成员变量
认识代码块
使用{}定义的一段代码称为代码块。根据代码块定义的位置和关键字,可以分为以下四种。
普通代码块
普通代码块:定义在方法中的代码块 (使用较少)
public static void main(String[] args) {
{
int a = 10;
System.out.println(a);
}
System.out.println("执行了普通代码块");
}
构造代码块
构造代码块:定义在类中的代码块(也叫实例代码块),一般用于初始化成员变量。
class WashMachine{
public double weight;
public double length;
public double height;
{
this.weight = 20.0;
this.length = 100.0;
this.height = 80.0;
}
}
静态代码块
静态代码块:在类中使用static定义的代码块,一般用于初始化静态成员变量。
class WashMachine{
public double weight;
public double length;
public static double height;
{
this.weight = 20.0;
this.length = 100.0;
}
static {
height = 80.0;
}
}
注: 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并成一个静态代码块。
同步代码块
后续多线程介绍。
认识内部类
当一个事物的内部还有一个部分需要一个完整的结构来进行描述,而这个完整的结构又只为外部事物提供服务,那么这个内部的完整的结构最好使用内部类。
在Java中,内部类可以定义在一个类内部或者一个方法内部。
注:
- 定义在class 类名{} 花括号外部的,即使在一个文件里都不能称为内部类。
- 内部类和外部类共用同一个Java源文件,但是经过编译之后,内部类会形成单独的字节码文件。
实例内部类
实例内部类:在外部类里,未被static修饰的成员内部类(成员位置确定)。
class OutClass{
public int a = 1;
class InnerClass{
public int a = 1;
public static final int data = 5;
}
}
注:
- 要想在实例内部类里定义静态的成员变量,则 这个静态成员变量必须被final修饰。
- 不能在实例内部类中定义静态的成员方法。
- 在实例内部类中可以直接访问外部类里:任意访问限定修饰符修饰的成员。
- 如果内部类和外部类中具有相同名称成员时,内部类访问时优先访问的是自己的;要想访问外部类同名成员时,必须:外部类名称 . this . 同名成员名字。如果这个同名成员还时静态的,则直接:外部类名称 . 同名成员名字。
- 创建内部类的两种方式: 都必须依赖外部类
1> 直接创建 ```java
OutClass.InnerClass innerClass = new OutClass().new InnerClass();```java OutClass outClass = new OutClass(); OutClass.InnerClass innerClass = outClass.new InnerClass(); ``` 6. 外部类中不能直接访问实例内部类中的成员,如果要访问必须要先创建外部类的对象。
静态内部类
静态内部类:在外部类里,被static修饰的成员内部类。
class OutClass{
public int a = 1;
static class InnerClass{
public int a = 1;
}
}
注:
- 在静态内部类中只能访问外部类中的静态成员。
- 创建静态内部类对象时不需要先创建外部类对象
OutClass.InnerClass innerClass = new OutClass.InnerClass();
局部内部类
局部内部类:定义在外部类的方法体或者{}中,该内部类只能在其定义的位置使用。(一般使用非常少)
class OutClass{
public int a = 1;
public void method(){
class InnerClass{
public void print(){
System.out.println(a);
}
}
InnerClass innerClass = new InnerClass();
innerClass.print();
}
}
注:
- 局部内部类只能在其定义的方法体内部使用。
- 不能被public等修饰符修饰。
- 编译器也会生成自己的独立的字节码文件 命名格式:外部类名字$内部类名字.class
匿名内部类
匿名内部类:定义在外部类的方法体或者{}中,没有明确的类名。
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("这是匿名内部类");
}
};
}