0 面向对象概念
面向对象:把事情交给对象完成(厨师、快递员),对象具备完成某件事情的人或物。
面向过程:自己一条龙完成所有事情
类:描述客观世界里某一类对象的共同特征
对象:类的具体存在,使用类的构造器来创建该类的对象
phone类:
有静态的属性(品牌、价格、尺寸)
有动态的方法(打电话、发短信)
面向对象三大特征:封装、继承、多态
1 类
1 定义类:
[修饰符] class 类名
{
(0-多)个构造器;
(0-多)个成员变量;
(0-多)个方法;
}
修饰符:public/final/abstract/(default)
类名:驼峰原则
static修饰的成员不能访问没有static修饰的成员
大部分时候,定义一个类,就是为了重复创建该类的实例: Date birthday = new Date();
Example:
public class Phone
{
//无参构造方法
public Phone() {
System.out.println("无参构造");
}
//有参构造方法
public Phone(String brand, double price, double size) {
System.out.println("有参构造");
}
//三个局部变量:一定要是private,否则会破坏封装,任何类、任何方法会修改他的值。
private String brand;
private double price;
private double size;
//两个方法
public void sendMessage() {
System.out.println("Phone can send message");
}
public void call() {
System.out.println("Phone can call");
}
}
Example2:
1 Employee.java:
package com.lemon.twentytwentythreejan;
import java.time.LocalDate;
public class Employee
{
private String name;
private Double salary;
private LocalDate hireDate;
public Employee() {
}
public Employee(String n, double s, int year, int month, int day) {
name = n;
salary = s;
hireDate = LocalDate.of(year, month, day);
}
public void setName(String n) {
name = n;
}
public void setSalary(Double s) {
salary = s;
}
public void setHireDate(LocalDate l) {
hireDate = l;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public LocalDate getHireDate() {
return hireDate;
}
public double raiseSalary(double byPercent) {
double raise = salary * byPercent/100;
return salary += raise;
}
}
2 EmployeeTest.java
package com.lemon.twentytwentythreejan;
public class EmployeeTest
{
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("aa", 20000, 2021, 01, 11);
staff[1] = new Employee("bb", 30000, 2022, 02, 12);
staff[2] = new Employee("cc", 40000, 2023, 03, 13);
for (Employee e:staff) {
e.raiseSalary(5);
System.out.println("Name is " + e.getName() + ", new salary is " + e.getSalary());
}
//Name is aa, new salary is 21000.0
//Name is bb, new salary is 31500.0
//Name is cc, new salary is 42000.0
}
}
2 方法:
所有方法必须定义在类里;
方法要么属于类,要么属于对象;
方法不能独立执行,方法必须用类或对象来调用
1 定义方法
1 定义:
[修饰符] 方法返回值类型 方法名(形参列表){
//0-多条可执行语句;
}
2 修饰符:
public/procted/(default)/private/final/abstract/static
其中: public/procted/private:只能三选一;final/abstract:只能二选一,可以与static组合
3 返回值类型:
返回值类型可以是任何数据类型,包括基本类型和引用类型。
如果方法没有返回值:必须使用void声明没有返回值;
如果声明了方法返回值类型:方法体内必须有有效的return语句(返回一个变量或表达式)。
Note: 某方法有返回值,且内部分支结构:必须在每个分支都有返回,或者在最后return;
return后面不能有代码,return意味着结束啦。
4 方法名:
小驼峰,建议以英文动词开头。
2 方法调用:
方法不调用,则方法就不会被执行。
使用static修饰的方法:属于类本身,既可以使用类来调用,也可以使用对象来调用(任何对象来调用将得到相同的执行结果,因为底层仍然通过类来调用);
没有static修饰的方法:只能使用对象来调用,不能用类来调用。
如果两个方法属于同一个类:A调用B,可以直接调用;
如果两个方法属于不同类:必须用对象.方法名()来调用。
3 方法的值传递
方法的形参:只服务于方法内部
传进来的实参:关注参数类型及方法返回值类型
如果方法里包含形参声明,那么调用方法时,必须给这些形参指定参数值,调用方法时,实际传给形参的参数值成为实参。
实参值传递:将实际参数的复制品传入方法内,而参数本身不会受到任何影响。
4 形参个数可变的方法
1.5后:允许为方法指定数量不确定的形参
最后一个形参的类型后加三个点...:该形参可以接收多个参数值,多个参数值被当成数组传入。
一个方法只能有一个形参可变的可变参数。
特点:
形参个数可变的参数本质上是一个数组参数。
相同点:
以下两个方法完全一样:两种方式都包含一个名为books的形参,两种方法都把books当数组处理。
public static void test(int a, String...books)
public static void test1(int a, String[] books)
不同点:调用时候有差异,可变形参的调用方法更简洁。
test(2,"java","python");//调用更简洁
test1(2, new String[] {"java", "python"})//调用时必须传一个数组
注意:个数可变的形参只能位于形参列表的最后,也就是说一个方法中,最多只能有一个个数可变的形参。
例子:
package com.lemon.twentytwentythreejan;
public class TestVarArgs
{
static void printArray(Object...obj) {
for(Object o:obj) {
System.out.print(o + " ");
}
System.out.println();
}
public static void main(String[] args) {
printArray(1,2,3,6,4);//1 2 3 6 4
printArray();
printArray(1,"one","two");//1 one two
printArray((Object[])new Integer[] {1,2,3,4});//1 2 3 4
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/20b8cb244f55a9dc1af3f6ea42d29b9c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a04df713627baaa583a08e13861eb1e9.png)
5 方法重载(两同一不同)
1 定义:
同一个类中&方法名相同,参数列表不同(参数类型不同或参数个数不同)的多个方法,叫做方法重载。
方法的其他部分,如返回值类型、修饰符,与方法重载没有关系。
2 为什么要引入方法重载?
add这个方法要处理加法,int、float、double都要写好多个不同方法名来实现add:这样不方便。
类找方法:主要看方法名和参数。
6 构造方法:主要职责:创建对象;次要职责:对成员变量赋值
一个类没写构造方法:Java自动提供无参构造;
一旦写了任意构造方法:Java不会再提供构造方法。
1 定义构造方法
[修饰符] 构造方法名 (形参列表){
//0-多条语句;
}
修饰符:public/procted/(default)/private
2 Note:
1 构造方法名称和类名完全相同;
2 每个类可以有一个以上的构造器;
3 每个类可以有0个或1个或多个参数;构造方法可重载:类可以同时有无参构造和有参构造。
4 构造器没有返回值:构造方法不能定义返回值类型,也不能使用void;
5构造器总是伴随new操作一起调用:所有的Java对象都是在堆中构造的;
6 不要在构造器中定义与实例域重名的局部变量: 比如下面的截图
7 构造方法只能赋值,不能取值。
![](https://i-blog.csdnimg.cn/blog_migrate/067a9a98d6a9e9e2d1d3fbfae151707a.png)
3 对象
1 创建对象时:发生了什么?Employee emp = new Employee();
将会为对象分配存储空间,并调用相应的构造器。
构造方法:通过new这个关键字来调用某个类的构造方法可以创建这个类的实例。
类名 对象名 = new 类名();
Phone phone = new Phone();
一个对象创建成功后,对象保存在堆上。
栈上:方法、局部变量 (先进后出,就像子弹夹。)
Java 程序不允许直接访问堆内存中的对象,只能通过该对象的引用操作该对象。
堆内存的对象可以有多个引用,也就是说多个引用变量(栈上)指向同一个对象:
Phone p2 = p;//把p变量的值赋给p2,p/p2指向堆内存中的同一个变量
static方法:可以不创建对象,直接用类来调用方法;
非static方法:必须用对象来调用。
2 使用对象
访问对象的实例变量
调用对象的方法
3 this:总是指向调用该方法的对象。(成员变量、局部变量同名的问题)
this作用:让类中一个方法,访问该类里的另一个方法或实例变量。
this可以代表任何对象。
当this出现在某个方法体时候,它代表的对象不确定,但类型确定:
代表的是当前类的实例;
当这个方法被调用时: 代表的对象确定了:
谁调用这个方法,this就代表谁。
Java允许对象的一个成员直接调用另一个成员,可以省略this前缀。
run方法调用本类中的jump方法: this.jump(); 或者直接 jump();
static修饰的方法中不能使用this引用。
静态成员不能直接访问非静态成员。
建议:
Java编程时候,不要使用对象去调用static修饰的成员变量和方法。
如果确实需要在静态方法中访问另一个普通方法,可以重新创建一个对象:
new StaticAccessNonStatic().info();
大部分时候,普通方法调用其他方法、成员变量:不需要this
但有一种场景必须要this:
当方法里有局部变量和成员变量同名,但程序需要在方法里访问这个被覆盖的成员变量,则必须用this
4 静态域与静态方法
1 静态常量:如Math.PI:
public static final double PI = 3.1415926
2 静态方法:是不能向对象实施操作的方法,是没有this参数的方法
可以使用类或者对象来调用静态方法,但是建议使用类名来调用静态方法,以免造成混淆。
3 以下两种情况使用静态方法:
1 一个方法不需要访问对象状态,所需参数都是通过显式参数提供
2 一个方法只需要访问类的静态域
4 成员变量和局部变量
位置不同,作用域不同 [小驼峰]
1 成员变量:在类中定义的变量,有默认值,分为两类:
类变量:有static修饰的:类准备阶段起开始存在,直到类完全销毁;类.类变量;
实例变量:没有static修饰的:类实例创建时候开始存在,直到类实例销毁;实例.实例变量;
2 局部变量:在方法里定义的变量,分为三类:
形参:方法签名中定义的变量;作用域在整个方法内有效;
方法局部变量:在方法内定义;作用域从定义该变量的地方生效,到方法结束时失效;
代码块局部变量:在代码块内定义;作用域从定义该变量的地方生效,到代码块结束时失效。
3 成员变量和局部变量区别:
成员变量有默认值;
局部变量除形参外,都必须显式初始化。也就是说,必须给方法局部变量和代码块局部变量指定初始值,否则不可以访问他们。
形参初始化:调用方法时由系统完成。
5 类设计的技巧
1 一定要保证数据私有:不要破坏封装性
2 一定要对数据初始化:显式的初始化所有的数据