面向对象的重要特征:封装、继承、多态;
面向对象的语言的语言并不止Java,C++也是面向对象的语言;
访问限定符
- public:在哪里都可以使用(公开的);
- private:仅在当前类可以使用(私有的);
- 不写任何限定符:只能在当前包使用(默认的);
- protected:可以在当前包使用,也可以在不同包的子类中使用(被保护的);
封装:就是将类的实现细节进行隐藏;仅对外公开接口来和对象进行交互;
实现封装后:在当前类外就无法直接拿到某个被封装的字段或方法(被private所修的字段或方法);
被static所修饰的成员变量不属于对象——不能使用对象的引用来访问成员变量;
被static修饰的成员变量属于当前类,是类变量——所以可以通过类的引用进行访问;
静态的只能是成员变量,不能是局部变量(Java中没有全局变量的说法);
static修饰的成员方法叫做静态方法,是类方法,不属于对象;
静态方法可以通过类访问,也可以通过对象访问(不建议);
静态方法中不能访问任何非静态成员变量;
静态方法中不能调用任何非静态方法;
使用大括号{}定义的代码,称之为代码块;
- 普通代码块
- 构造代码块(也叫实例代码块)
- 静态代码块
- 同步代码块(多线程学)
在一个类1的内部有一个类2,则类1称为外部类,类2称为内部类;
内部类和外部类共用一个Java源文件,但是编译后内部类会形成一个单独的字节码文件;
被static所修饰的内部类就是静态内部类;
静态内部类中只能访问外部类中的静态成员;
创建静态内部类对象时,不需要先创建外部类对象;
- 继承的定义:将某些公共性质抽取出来,将这些共性单独写一个类(父类);
- 继承的作用:将这些共性写成一个类实现了代码的复用;
- 继承的使用:当子类与父类之间存在is-a关系时,就可以使用继承;
子类 extends 父类;// extends关键字属于继承关键字;
- class Animal { // 父类->将子类中共有的性质写出来
- private String name;
- private int age;
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void eat(Animal this) {
- System.out.println(this.name + " 正在吃饭");
- }
- public void sleep(Animal this) {
- System.out.println(this.name + " 正在睡觉");
- }
- private void play(Animal this) { // 被private或者static所修饰的无法被继承
- System.out.println(this.name + " 正在玩耍");
- }
- }
- class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
- private String color;
-
- public void setColor(String color) {
- this.color = color;
- }
- public String getColor() {
- return color;
- }
- public void skin(Dog this) { // 这子类中调用了父类的方法getName();
- System.out.println(this.getName() + " 是" + this.getColor());
- }
- }
- public class Test{
- public static void main(String[] args) {
- Dog dog = new Dog();
- dog.setName("二哈");
- dog.setColor("黄色");
- dog.eat(); // 父类的方法
- dog.skin(); // 子类自己的方法
- }
- }
- super关键字:就是告诉编译器指定访问父类的成员属性和方法;
- this关键字:表示访问当前类的成员属性和方法;(子类继承父类,所以拥有了父类的属性和方法,当this访问时先访问自己的,如果自己没有再访问父类的;)
super关键字和this关键字,不能出现在static所修的的方法中;
super.成员变量; // 访问父类成员变量
super.成员方法;// 访问父类成员方法
super(); // 调用父类构造方法
- class Animal { // 父类->将子类中共有的性质写出来
- private String name;
- private int age;
- public Animal(String name, int age) { // 父类的构造方法
- this.name = name;
- this.age = age;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void eat(Animal this) {
- System.out.println(this.name + " 正在吃饭");
- }
- public void sleep(Animal this) {
- System.out.println(this.name + " 正在睡觉");
- }
- private void play(Animal this) {
- System.out.println(this.name + " 正在玩耍");
- }
- }
- class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
- private String color;
- public Dog(String name, int age, String color) { // 子类的构造方法
- super(name, age); // 调用父类构造方法
- this.color = color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- public String getColor() {
- return color;
- }
- public void skin(Dog this) { // 使用super.getName()是调用了父类的方法;
- System.out.println(super.getName() + " 是" + this.getColor());
- }
- }
- public class Test{
- public static void main(String[] args) {
- Dog dog = new Dog("阿黄", 2, "红色");
- dog.eat();
- dog.skin();
- // Dog dog = new Dog();
- // dog.setName("二哈");
- // dog.setColor("黄色");
- // dog.eat(); // 父类的方法
- // dog.skin(); // 子类自己的方法
- }
- }
父类的静态->子类的静态->父类的实例->父类的构造->子类的实例->子类的构造
- 被final所修饰的变量称为常量;
- 被final修饰的类不能被继承;
- 多态的定义:不同的对象去完成同一个行为产生了不同的效果就成为多态;
- 多态的实现条件:继承、向上转型、重写;
- 向上转型:父类引用接收子类对象;(父类引用只能调用自己的方法,不能调用子类的)
- 重写:在子类中写一个和父类一样的方法;(方法名相同、返回值相同、参数列表相同(个数、顺序、类型);)
向上转型: 就是子类对象赋值给父类的引用(父类引用子类对象);
- 子类 对象1 = new 子类(); 父类 对象 = 对象1;
- 向上转型就不能调用子类特有的方法;
- 向上转型的三种:1、直接赋值;2、方法参数的传递;3、方法返回值
向下转型:强制类型转换,需要进行判断,使用instanceof关键字进行判断;
重写(覆盖、覆写):在子类中重写父类中的方法,在这个过程中会发生动态绑定;
- 重写:返回值、方法名、参数列表(个数、顺序、类型)都相同;
- 被static修的方法不能被重写;
- 被private所修饰的方法也不能被重写;(因为这个方法只能在当前类使用)
- 重写权限:子类方法权限大于等于父类方法权限;
动态绑定:在编译的时候不确定调用哪个方法,在运行的时候才知道调用的哪个方法(在方法重写发生);
静态绑定:静态绑定:指的是在编译的时候就已经知道调用哪个方法了(在方法重载发生);
- class Animal { // 父类->将子类中共有的性质写出来
- private String name;
- private int age;
- public Animal(String name, int age) { // 父类的构造方法
- this.name = name;
- this.age = age;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void eat(Animal this) {
- System.out.println(this.name + " 正在吃饭");
- }
- public void sleep(Animal this) { // 在子类中重写一个sleep方法,实现动态绑定
- System.out.println(this.name + " 正在睡觉");
- }
- private void play(Animal this) {
- System.out.println(this.name + " 正在玩耍");
- }
- }
- class Dog extends Animal { // 子类Dog继承了父类Animal的属性和方法
- private String color;
- public Dog(String name, int age, String color) { // 子类的构造方法
- super(name, age); // 调用父类构造方法
- this.color = color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- public String getColor() {
- return color;
- }
- public void skin(Dog this) { // 使用super.getName()是调用了父类的方法;
- System.out.println(super.getName() + " 是" + this.getColor());
- }
- @Override // @Override是注解,起到编译器的作用
- public void sleep(Dog this) { // 这就是在子类中重写的sleep方法(动态绑定在重写时发生)
- System.out.println(super.getName() + " 没有在睡觉");
- }
- }
- public class Test{
- public static void main(String[] args) {
- Animal dog = new Dog("狗蛋", 3, "绿色");
- // 父类引用子类对象,这就是向上转型
- dog.eat(); // 父类调用自己的方法
- //dog.skin(); // 父类无法调用子类的方法,所以这行代码是错的
- dog.sleep(); // 因为sleep方法进行了重写,所以此时调用子类中的sleep
- }
- }
父类构造方法中调用重写方法,也会发生动态绑定;意味着构造方法内也会发生动态绑定;
代码执行顺序:父类实例->父类构造->子类实例->子类构造;
new:1、分配内存空间;2、调用合适构造方法;
在构造方法中调用重写方法,这样可能会导致变量没有实例化;