# 面向对象
你是上帝,创造对象,让对象干活。
优点:减少代码量、可扩展性强、维护成本低
缺点:上帝视角、上手难度相对大
# 类
设计方案:属性(class 里的变量,即成员变量) + 动作(public 不加 static,即成员方法)
# 对象
类的实例。
创建方法: new
// 类 引用 = new 类 (); | |
car c = new car(); |
# this 关键字
当前正在执行这个方法的对象。
- 在调用方法的时候,Java 会自动地把对象传递给方法,在方法中由
this
来接收对象。 - 不加
this
的变量的查找顺序:自己方法内找(局部变量)>this
里面找(成员变量)。 this
还可以调用当前类中的其他构造方法(通过this(参数)
,而不是this.xxxx
)。
# 构造方法
- 没有返回值。
- 在执行
new
的时候自动调用构造方法。
public 类名(参数){ | |
} |
# 构造方法重载
- 构造方法也是方法,也可以进行重载。
- 方法名称相同,参数个数不同。
- 从而可以有更多的方式创建对象。
# static
- 静态的内容在内存中只保留一份。
- 其内容由各个对象共享。
- 推荐使用类名访问静态内容。
# 通用构造器 & 静态构造器
(都不常用)
创建对象的过程:先执行静态构造器,再执行通用构造器,最后执行构造方法。因此,在静态方法里不能使用 this
,因为 this
还没生成。
public class test{ | |
{ | |
System.out.println("这里是通用构造器"); | |
} | |
static { | |
System.out.println("这里是静态构造器"); | |
} | |
} |
# 包
- 所有程序都平铺在
src
里不好维护。 - 包名一般用公司域名的翻转 (如
com.baidu.tieba
)。
package com.baidu.tieba; |
# 导包
不需要导包:
- 在自己包里不需要导包;
java.lang
包下的所有内容不需要导包。
导包格式:
import com.baidu.tieba.person; | |
import com.baidu.tieba.*; |
# 访问权限
public
公共的,所有人可访问(常用)。default
包访问权限,自己包内可以随意访问。private
私有的(常用)。
# setter
- 给
private
成员变量赋值,可以添加保护。 - IDEA 可以右键
generate -> getter and setter
自动生成。
# getter
- 从
private
成员变量获取数据。 - IDEA 可以右键
generate -> getter and setter
自动生成。
# 继承
子类可以自动拥有父类中除了私有内容外的其他所有内容。
作用:简化代码的开发。
当出现 x 是一种 y 的时候,x 就可以继承 y(黑熊怪是一种妖怪)。
public class HeiXiongGuai extends YaoGuai{ | |
} |
# super 关键字
this
先找自己类再找父类,super
表示父类中的内容。- 可以用
super
和this
来区分父类和子类中重名的内容。 - 可以用
super()
来调用父类构造方法,需要写在子类构造方法的第一行。 - 如果父类构造方法不包含参数,可以不写;如果包含参数,一定要写。
- 在调用子类构造方法时,会在进入子类构造方法时调用父类构造方法,再回到子类的构造方法。
public class zilei extends fulei{ | |
public zilei(){ | |
super();// 即使不加这行代码,这里也会默认调用 super () | |
System.out.println("我是子类构造方法"); | |
} | |
} |
# 方法的重写
子类对父类中提供的方法进行重新定义。
语法:子类和父类中的方法的声明完全一致。
# 多态
同一个对象拥有多种形态。
作用:把不同的数据类型进行统一,但真正执行的时候依然会按照每个数据类型进行执行。
- 向上转型:把子类的对象赋值给父类的引用 (会屏蔽掉子类中特有的方法,因此还需要向下转型)。
- 向下转型:把父类的变量转换回子类的变量(向下转型有风险,需要写强制类型转换)。
// 向上转型 | |
animal ani1 = new cat(); | |
animal ani2 = new dog(); | |
// 向下转型 | |
cat cc = (cat)ani1; | |
ani1.eat(); // 可执行 | |
ani1.CatchMouse(); // 不可执行 | |
cc.CatchMouse(); // 可执行 |
# final
- 被
final
修饰的变量不可被改变,又被称为常量。 - 被
final
修饰的方法不可被重写。 - 被
final
修饰的类不可被继承,即不能产生子类。
# 抽象
只声明,不实现。
- 用
abstract
修饰方法,直接用分号结束。 - 如果一个类中有抽象方法,那么这个类一定是一个抽象类。
- 抽象类不可以造对象,即不可以
new
。 - 抽象类的子类必须重写抽象类中的抽象方法(通过抽象类可以强制要求子类中有哪些方法)。
- 抽象类中可以有正常的方法。
public abstract class animal{ | |
public abstract void eat(); | |
public void smell(){ | |
// …… | |
} | |
} |
# 接口
接口实际上是一种特殊的抽象类,其中所有的方法都是抽象方法。
- 使用
interface
声明。 - 能继承接口的只能是接口。
- 接口和类只能是实现关系。
- 接口同样具有多态性。
- 方法可以省略
abstract
。 - 接口中所有方法默认都是
public
的,所有变量都是全局静态最终常量。 - 类只能单继承,而接口支持多实现。
作用:接口可以把很多不相关的东西进行整合。
public interface valuable{ | |
public abstract void getMoney();// 接口中所有的方法都是抽象方法 | |
} | |
public class Gold implements valuable{ | |
// 必须要重写抽象方法 | |
public void getMoney(){ | |
System.out.println("类实现接口,重写抽象方法"); | |
} | |
} |
public class Panda extends animal implements valuable, protectable{ | |
// 类可以继承一个类,实现多个接口 | |
} | |
public static void main(){ | |
// 接口同样具有多态性 | |
panda p = new Panda(); | |
animal ani = new Panda(); | |
valuable v = new Panda(); | |
protectable p = new Panda(); | |
} |
# 成员变量的初始值
- java 中所有的变量必须先声明再赋值才可使用
- java 中的成员变量在创建对象的时候都会执行一次初始化操作,给一个默认值:
- byte:0
- short:0
- int:0
- long:0
- float:0.0
- double:0.0
- char:0
- boolean:false
- string (string 是 java 提供的一个类):null
- child (自己写的类):null
- 即基本数据类型默认都是 0,包括 boolean;引用数据类型都是 null
# object
所有的东西都是对象
- object 是一个类,是所有类的根
- 在 java 中,所有的类都要继承 object;我们写的类,即使不写继承关系,默认也会继承 object
- equals(object 提供的方法):用来判断两个对象是否相等
- equals 和 ==
- == 一般用于基本数据类型,不用于对象
- equals 默认用法与 '==' 相同,但可以通过重写添加自己的判断逻辑
- equals 用法:
System.out.println(c1.equals(c2)); |
- 字符串的判断一定要用 equals:
String str1 = "lessone"; | |
String str2 = "lessone"; | |
// 重用了同一块内存 | |
System.out.println(str1==str2); //true 地址相同 | |
System.out.println(str1.equals(str2)); //true 内容相同 | |
String str3 = new String("111"); | |
String str4 = new String("111"); | |
System.out.println(str1==str2); //false 判断的是地址,地址不同 | |
System.out.println(str1.equals(str2)); //true String 中重写了 equals,用于判断内容是否相同 |
- toString(object 提供的方法):对一个对象字符串的表示形式,JAVA 官方推荐重写这个方法
- 直接打印对象会默认执行 toString 方法
- 默认的 toString 返回:包名 + 类名 @内存地址
# instanceof
- instanceof 关键字:判断 xxx 对象是否是 xxx 类型的
- 用法:
if(ani instanceof cat){ | |
// ... | |
} |
# 参数传递
参数传递包括值传递和引用传递,java 使用的是值传递
# 值传递
把变量的值作为参数传递
public class Test { | |
public static void change(int b){ | |
b = 20; | |
} | |
public static void main(){ | |
int a = 10; | |
change(a); | |
System.out.println(a); // 结果为 10 | |
} | |
} |
把变量作为参数传递
public class Test { | |
public static void change2(Cat c){ | |
c = new Cat("NewName"); // 创建一个新的猫,change.c 指向新猫的地址,外面的 c 仍指向原来的猫的地址 | |
// 运行完后 change.c 被回收,新猫被回收 | |
} | |
public static void main(){ | |
Cat c = new Cat("OriginalName"); | |
change2(c); // 传入 c 的值,即原来的猫的地址 | |
System.out.println(c.name); // OriginalName | |
} | |
} |
public class Test { | |
public static void change3(Cat c){ | |
c.name = "NewNewName"; //c 为原来猫的地址,故修改成功 | |
} | |
public static void main(){ | |
Cat c = new Cat("OriginalName"); | |
change3(c); // 传入 c 的值,即原来的猫的地址 | |
System.out.println(c.name); //NewNewName | |
} | |
} |