文章目录
1. 概念
- 面向对象(Object Oriented Programming)程序由对象组成,每个对象对用户公开特定功能并隐藏代码实现的部分,其中很多的对象来自Java标准库,也存在一部分对象是开发者自定义,只要当前对象能够满足要求,就不必去关心其功能具体是如何实现的。
- 对象包含数据(属性) 和 函数(动作)
- 面向对象将数据放在第一位,再去考虑操作数据的算法,操作数据的过程也就被称为方法。
- 对象之间的联系通过消息传递实现,也就是函数调用。
- 类是构建对象的模板,由类构造对象的过程称为创建类的实例。创建时使用构造器(构造函数)创建新实例(对象),如果希望构造的对象可以多次使用,那么就会将对象存放在一个变量中,如果声明为一个对象变量,那么它就可以引用后面构造器所构造的对象。
- 对象具有唯一性
2. 包
- Java使用包将类组织在一个集合中,也是确保类名唯一性的主要原因,同名类放置在不同包中就不会产生冲突,为了保证包名的唯一性,一般使用因特网域名的逆序来进行命名。
3. 访问控制
- 缺省(default),同一个包中可见
- private,在本类中可见
- protected,在子类中可见
- public,在任何情况都可见
4. 方法(函数)中参数传递的方式
- 按值调用—接收调用者提供的值
- 按引用调用—接收调用者提供的地址
- Java对对象采用按值调用并不是按引用调用,实际上对象的引用就是按值传递的。
5. 面向对象的特点
- 封装性(数据隐藏)
核心思想,绝不能让其他类直接访问实例字段,程序只能通过对象的方法与对象进行数据交互。
- 继承性
类与类之间的关系,可以基于已存在的类派生新的类,并复用继承的已存在父类的方法
- 多态性
一个对象变量可以指示出多种实际类型的现象,例如一个类中的方法和属性被继承后会有不同的数据类型或行为
6. 构造器特点
- 构造器与类同名
- 每个类可以有多个构造器
- 每个构造器可以有0、1或多个参数
- 构造器总是伴随着new操作符一起调用,通过new命令分配空间且无返回值
String str = new Test().toString();
System.out.println(str);
Test test = new Test();
//所有Java的对象都存储在堆中,此时new Test()的值是对所创建对象的一个引用,存储在对象变量test中
System.out.println(test);
7. 继承
- 父类也被称为超类、基类;子类也被称为派生类、孩子类。
- 一般情况下子类比父类拥有的功能会更多,如果在子类中定义了与父类签名相同的方法,那么这个方法就会覆盖父类中拥有相同签名的方法。
- 子类方法不能低于父类方法的权限。
- Object类:所有类的父类,Java中每个类都扩展了Object类,包括基本数据类型,因为基本数据类型都有一个与之对应的类(并且除了Boolean其它六个类还有一个公共的父类Number)称为包装器,自然Object类型的变量可以引用所有类的对象 ,当然,Object类引用子类对象只是作为一个泛型容器,要想对子类对象进行相应的操作还是要用强制类型转换来进行。
class Animal {
String name = "我是动物";
void shout() {
System.out.println("动物叫!");
}
}
class Dog extends Animal {
String name = "我是小狗";
void shout() {
super.shout();
System.out.println("小狗汪汪叫");
}
}
public class test {
public static void main(String[] args) {
Animal animal = new Dog();
System.out.println(animal.name);
animal.shout();
}
}
7.1. 继承设计技巧
- 将公共字段与方法放在父类中
- 不使用受保护的字段,避免破坏封装性
- 除非所有继承的方法都具有意义,否则不要使用继承
- 覆盖父类方法时不要改变预期的行为
package xyz.tylt.test;
public class Test {
public String name() {
System.out.println("哈哈哈");
return "我是name方法";
}
public static void main(String[] args) {
Object object = new Test();
Test test = (Test) object;
System.out.println(test.name());
}
}
8. 多态
- 对象变量是多态的,一个父类对象既可以引用一个父类对象,也可以引用子类的对象。
8.2. 重载(Overload)
发生在同一个类中
这里注意,重载是静态的,在这里只是实现多态的一种方式,它并不属于多态,也不属于面向对象
-
类可能有多个同名的方法,包括构造方法,它们有相同的方法名,但是却有不同的参数,这时就会根据函数参数传递的参数类型进行匹配,选择适合的相同参数类型的方法。因此要完整的描述一个方法就需要展示其相同方法名以及不同的参数类型,这就叫做方法的签名。
-
对于构造方法,仅当当前类中没有其它有参构造函数时才会得到一个默认的无参构造器,但是只要有一个有参构造函数,但是却没自定义一个无参构造器的话就必须给定有参的初始值。
8.3. 覆盖(重写Override)
发生在父子类中
- 子类继承父类后对父类方法进行重新编写。
静态方法为了区分一般使用类名进行调用,而不是使用与它无直接关系的对象进行调用,虽然也可以,这只是一个建议,常见的例如工厂方法。当然静态方法也可以直接进行调用而不需要任何对象,例如main方法。
9. this、super 与 finally关键字
- this 关键字有两个含义,一是指向当前对象(隐式参数)的引用,二是调用该类的其他构造器。
this
可以调用本类对象所有的方法与属性,用来区分成员变量与局部变量的重名问题。this();
指向本类的构造方法,只能写在构造方法中并且必须是第一句。 - super 关键字也有两个含义,一是调用超类的方法,二是调用超类的构造器。
super
可以调用超类对象所有的方法与属性,super();
指向父类的构造方法,只能在子类构造方法的第一条语句出现,以便参数可以传递到另一个构造器。 - final
- 修饰类后不可被继承
- 修饰方法后子类不能再进行覆盖,但是可以重载
- 修饰变量后就变为常量,不可再更改它的值
- 局部、匿名内部类只能访问局部
final
修饰的变量,因为怕外部类销毁或变动后还要访问外部变量
10. 对象包装器与自动装箱/拆箱
拆箱与装箱是编译器要做的工作,而不是虚拟机的工作,虚拟机用来执行编译器生成的字节码。
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(10);
arrayList.add(Integer.valueOf(10));
if (arrayList.add(10) == arrayList.add(Integer.valueOf(10))) {
//两者等价证明实现了自动装箱
System.out.println("true");
} else {
System.out.println("false");
}
System.out.println(arrayList.get(0).intValue());
System.out.println(arrayList.get(1));
//这里将一个Integer对象赋给一个int值就是自动拆箱
int i = arrayList.get(0);
System.out.println(i);
静态字段属于类,并不属于某个对象,对此类的所有对象进行共享,所以静态方法没有this参数的方法,也就是说它没有隐式参数(方法名前所构造的对象),显示参数指方法传入的形参。
private static final或构造器定义的方法可以让编译器准确的知道是哪一个方法,这样的行为称为静态绑定,而对象调用的方法虚拟机需要先计算方法表,称为动态绑定。
最好将类中的字段定义为private方法定义为public。
package com.tylt.tyltdemo.test;
import java.time.LocalDate;
public class Test {
private String name;
private String sex;
private int age;
private LocalDate localDate;
public Test(String name, String sex, int age, int year, int month, int day) {
this.name = name;
this.sex = sex;
this.age = age;
this.localDate = LocalDate.of(year, month, day);
}
@Override
public String toString() {
return "Test{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
", localDate=" + localDate +
'}';
}
public static void main(String[] args) {
Test test = new Test("小明", "男", 10, 2000, 01, 01);
System.out.println(test.toString() + test.localDate);
}
}