面向对象和面向过程
面向过程:强调的是功能行为,以函数为最小单位,考虑的是怎么做,第一步、第二步...
面向对象:将功能封装进对象,强调的是具备了功能的对象,以类、对象为最小单开,考虑的时谁来做...
面向对象核心概念
接下来,我们以造汽车为例子,介绍一下面向对象的几个重要概念
类:是对一类事物的抽象描述。就是汽车图纸
属性:定义了对象的基本熟悉。比如汽车颜色、尺寸等
方法:定义了对象具有的行为。比如汽车能发动、行驶等
构造器:字面意思,就是构造对象的一个方法。你要根据图纸 生产 汽车。图纸(类)中就必须要带上这个方法。每次生产汽车的时候,都会执行这个方法,构造(创建)一辆汽车。
对象:根据类创建出来的某个实际存在的个体。也叫实例。就是根据图纸造出来的汽车本车。
类的创建和实例化
创建类(定义图纸)
修饰符 class 类名{
成员属性列表
成员方法列表
}
根据类实例化对象
类名 对象名 = new 类名()
案例:
package com.imooc;
public class Cat {
String name; //类的属性和基本数据类型变量不同,属性会自动初始化
int age;
public void eat() {
System.out.println("小猫吃东西");
}
//默认会自带一个无参构造方法(构造器)的
}
package com.imooc;
public class TestCat {
public static void main(String args[]) {\
//实例化
Cat cat = new Cat();
cat.eat();
System.out.println("小猫的年龄:" + cat.age); //int类型的属性,默认初始化为0
}
}
对象的实例化,严格来说,分为以下两个步骤
1.声明对象
类名 对象名;
只是在栈空间中开辟了一个区域,将这个区域命名为对象名,这个空间目前什么也没有
⚠️:如果创建了一个类的多个对象,那么,每一个对象都独立的拥有一套类的非static修饰的属性。如果修改一个对象的属性A,那么不影响另外一个对象的属性A。
2.实例化对象
new 类名()
在堆空间开辟了一个空间,并完成了初始化操作。
之后通过赋值符号,把这个堆空间的地址赋值给了栈空间的对象名所指的内存中
成员变量和成员方法
就是类的属性和方法。
成员变量(属性)
大家看到成员变量时,有的时候会和方法的局部变量傻傻分不清。这两个概念之间确实有些模糊地带。都是变量,两者有啥区别呢?
| 成员变量(属性) | 局部变量 |
|---|---|
| 直接定义在类的大括号内 | 声明在方法内、构造器内、代码块内、形参内 |
| 有权限修饰符 | 不可以使用权限修饰符(public, private,protected) |
| 根据类型,有相应的默认初始化值。调用之前,可以不用赋值。 | 无默认初始化值,调用之前,必须要先为其赋值(行参在调用时赋值即可)。 |
| 堆空间(非static) | 栈空间 |
成员方法(方法)
用来解决一类问题的代码的有序组合,是对象的一个功能模块。
访问修饰符 返回类型 方法名(参数列表){
方法体
}
方法调用: 在主方法或其他类中:
对象.方法名(参数);
在同一类的普通方法中:
直接用方法名就可以调用
-
基本数据类型作为参数是值传递(复制,内容数据)
-
数组,类等引用类型作为参数是地址传递(传递的是指向存储内容的内存地址)
成员方法不允许嵌套定义。
方法重载
方法重载指的是,两个方法,名字完全一致,但实现的功能却不一样,而且调用的时候,编译器能够区分出来你想调用的到底是谁。
同一个类内,方法名相同,参数列表不同,或参数类型不同、或参数顺序不同的方法,构成重载。
这个和继承没关系,说的是多个方法,名字相同,参数列表不同。用于解决虽然是同一类,但有细节区别的问题
⚠️:重载不表现为多态性,重载具体调用哪个方法,在编译期就可以确定
可变参数
方法修饰符 返回值类型 方法名(参数类型... 参数名)
public int sum(int... n){
for(int i:n){
sum += i;
}
System.out.println(sum);
}
可变参数必须放在参数列表的最后
方法修饰符 返回值类型 方法名(参数类型 参数名,参数类型... 参数名)
可以直接给可变参数传一个类型匹配的数组
public int sum(int... n){
for(int i:n){
sum += i;
}
System.out.println(sum);
}
-----------
int a[] = {1,2,3,4,5};
sum(a);
如果遇到方法重载,那么,在都匹配的方法中,优先调用不带可变参数的方法。
构造方法
任何一个类,都有构造方法,顾名思义,其负责给类开辟一段内存空间并进行初始化,即创建对象。
方法名与类名相同,没有返回值,不能被对象单独调用,只能在对象实例化时配合new进行使用。例如:
new Cat();
当没有在类中显示的声明一个构造方法时,系统会自动创建一个无参的构造方法。便于对象的实例化操作。
如果自己定义了一个带参数的构造方法,那么,系统就不会再提供默认的无参构造了。除非自己再显示定义一个无参构造。一个类中,允许有多个构造器,多个构造器之间彼此构成重载。
public Cat(String name){
//带参数构造方法
}
Cat cat = new Cat();//错误
Cat cat = new Cat("小猫");//正确
注意:构造函数中给属性赋值时,名字不要冲突
public class Cat{
String name;
public Cat(String name){
name = name;//冲突
}
}
-------------------
//这时可以改参数名,或者如下
public class Cat{
String name;
public Cat(String name){
this.name = name;
}
}
构造方法不能被普通方法调用,但是可以被同一类中的其他构造方法调用,调用方式:
public 构造方法(){ //无参构造
this(参数);//调用了一个有参构造
}
代码块
没有名字,没有返回值等信息(唯一能修饰代码块的就是static),只是用{}括起来的一段代码,称之为代码块。其主要的作用是用来初始化类或者对象的,所以,又称之为初始化块。
public class Student{
private int age;
public Student(){
}
{
//非静态代码块 或叫 初始化代码块 或叫 构造代码块
//每创建一个对象时,都会执行一次,也可以在这里对属性初始化
}
static{
//静态代码块
//只有在类加载时执行一次
}
}
如果定义了多个代码块,同级别的代码块,按照声明的先后顺序执行