面向对象
面向对象三个阶段:
- 面向对象分析OOA -- Object Oriented Analysis
- 对象: 张三, 王五, 朱六, 你, 我
- 抽取出一个类 ---> 人类
- 类里面有什么?
- 动词 --> 动态特性 --> 方法
- 名词 --> 静态特性 --> 属性
- 面向对象设计OOD -- Object Oriented Design
- 先有类, 再有对象
- 类: 人类 : Person
- 对象 zhangsan, lisi, zhuliu
- 面向对象编程OOP -- Object Oriented Programming
构造器
- 构造器没有返回值, 也不能写void
- 构造器的名称和类的名称一样
- (String pName, int pAge) 是构造器的形参列表, 规则和成员方法一样
- 一个类可以定义多个不同的构造器, 即构造器的重载
- 构造器是完成对象的初始化, 并不是创建对象
- 在创建对象时,系统自动调用该类的构造器方法
- 如果没有定义构造器, 系统会自动给类生产一个无参构造器 也叫默认构造器, 使用javap指令 反变异看看
- 一旦定义了自己的构造器,默认构造器就会覆盖,如果想使用无参构造器,除非定义一下: Person(){};
public class Constructor01 {
public static void main(String[] args) {
Person p1 = new Person('lvxl', 30)
System.out.println(p1.name) // lvxl
System.out.println(p1.age) // 30
}
}
class Person {
String name;
int age;
public Person(String pName, int pAge) {
System.out.println('完成对象的初始化')
name = pName;
age = pAge;
}
}
对象的创建分析
class Person{
int age = 90;
String name;
Person(String n, int a) {
name = n;
age = a;
}
}
Person p = new Person("小倩", 20)
- 加载Person类信息(Person.class),只会加载一次
- 在堆中分配空间(地址)
- 完成对象的初始化
- 默认初始化 age = 0 name = null
- 显式初始化 age = 90, name = null
- 构造器初始化 age = 20, name = 小倩
- 在对象在堆中的地址,返回给p
this关键字
- this关键字可以用来访问本类的属性,方法,构造器
- this用于区分当前类的属性和局部变量
- 访问成员方法的语法: this.方法名(参数列表);
- 访问构造器语法: this(参数列表); 注意只能在构造器中使用,必须放在第一条语句;
- this不能在类定义的外部使用,只能在类定义的方法中使用;
class Dog{
String name;
int age;
// 如果构造器的形参吗
public Dog(String dName, int dAge) { // 构造器
name = dName;
age = dAge;
}
public void info () {
System.out.println(name + "\t" + age + "\t")
}
}
包
包的本质 实际上就是创建不通的文件夹/目录来保存类 包的命名:只能包含数字,字母,下划线,小圆点,不能用数字开头, 不能是关键字或者保留字
代码块
代码块的分类: 普通块, 构造块,静态块,同步块
public class Test {
// 属性
int a;
static int sa;
// 方法
public void a() {
System.out.println("-----a");
{
// 普通块 限制了局部变量的作用范围
System.out.println("这是普通块");
int num = 10;
System.out.println(num);
}
}
public static void b() {
System.out.println("-----b");
}
// 构造器
public Test(int a) {
this.a = a;
}
public Test() {
System.out.println("这是空构造器");
}
// 构造块
{
System.out.println("-----这是构造块");
}
// 静态块
static {
System.out.println("这是静态块");
// 在静态块中只能访问静态属性 和静态方法 ;
System.out.println(sa);
}
// 代码块
public static void main(String[] args) {
Test t = new Test();
t.a();
Test t2 = new Test();
t2.a();
}
}
总结:
- 代码块执行顺序:
- 最先执行静态块,只在类加载的时候执行,所以一般以后要处理初始化信息都放入静态块;一般用于执行全局的初始化操作;
- 再执行构造块;
- 再执行构造器;
- 再执行方法中的普通块;
修饰符
修饰符 | 同一个类 | 同一个包 | 子类 | 所有类 |
---|---|---|---|---|
private | * | |||
default | * | * | ||
protected | * | * | * | |
public | * | * | * | * |
super
- super指的是父类;
- super可以修饰属性, 可以修饰方法;在子类中去调用父类属性和方法: (通常情况,super省略不写)
public class Student extends Person {
public void a() {
System.out.println(super.age);
super.eat()
}
} - super修饰构造器, 调用父类的空构造器
public class Student extends Person {
public Student() {
super();
}
} - super修饰构造器,super调用父类构造器和this调用子类构造器只能存在一个;因为super修饰构造器要放在第一行,this修饰构造器也要放在第一行。
三大特性
- 封装 --> 将某些东西进行隐藏,然后提供相应的方式进行获取。
- 高内聚: 类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合: 仅对外部暴露少量的方法用于使用;
- 提高代码的安全性;
- 继承
- 提高代码的复用性
- 父类private修饰的内容,子类实际上也继承了,只是因为封装的特性阻碍了直接调用,但是也提供了间接调用的方法;
- 为了以后多态的使用, 是多态的前提;
- 一个子类只能继承一个父类。但是可以间接的继承自其他类型;所有的类都直接或者间接的继承自 Object;
- 多态
- 多态与属性无关, 多带纸的是方法的多态, 而不是属性的多态;
- 同一方法调用,然后由于对象的不同,会产生不同的行为;
- 为了提高代码的扩展性,符合面向对象的设计原则: 开闭原则。 (扩展是开放的,修改是关闭的);
方法的重载
equals 与 ==
- ==: 既可以判断基本类型,有可以判断引用类型
- ==:如果判断基本类型,判断的是值是否相等
int a = 10;
double d= 10.0;
a == d // true; - ==:如果判断引用类型,判断的是地址是否相等,即判断是不是同一个对象
- equals:是Object类中的方法,只能判断引用类型
- equals: 默认判断的是地址是否相等,子类中往往重写该方法,用于判断类容是否相等,比如Integer,String
hashCode
- 提高具有哈希结构的容器的效率!
- 两个引用,如果指定的是同一个对象,则哈希值肯定一样的
- 两个引用,如果指向的是不同对象,则哈希值是不一样
- 哈希值主要根据地址号来的,不能完全将哈希值等价于地址
抽象类
当父类一些方法不能确定的时候,可以使用abstract关键字类修饰该方法,这个就是抽象方法,用abstract来修饰的类就是抽象类。 抽象类的价值更多用于设计,是设计者设计好后,让子类实现的。
细节:
- 抽象类不能实例化;
- 抽象类不一定要包含abstract方法,也就是说抽象类可以没有abstract方法
- 一旦类包含类了abstract方法,这个类必须声明为abstract
- abstract只能修饰类和方法,不能修饰属性和其他;
- 抽象类可以有任意成员(抽象类本质还是类),比如:非抽象方法,构造器,静态属性等等。、
- 抽象方法不能有主体;
- 如果一个类继承类抽象类,则必须实现抽象类的所有抽象方法,除非她自己也声明成类abstract类。