Java三大特性
1.封装(encaplusation)
官方解释:在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
我的理解:1.对数据进行私有化 起到保护作用 外界不能直接访问 2.对数据进行校验
代码
package Encapsulation; import java.util.Scanner; public class A { private String name; private int age; Scanner scanner = new Scanner(System.in); public A(String name, int age) { // this.name = name; // this.age = age; // 构造器和 setXxx结合 setName(name); setAge(age); } public String getName() { return name; } public void setName(String name) { if (name.length() <= 6 ) { this.name = name; } else { System.out.println("你输入的名字太长了"); } } public int getAge() { System.out.println("请输入您的名字"); String input_name = scanner.next(); //权限校验 if(input_name.equals(input_name)) { return age; }else { return -1; } } public void setAge(int age) { if (age >= 1 && age <= 150) { this.age = age; } else { System.out.println("你输入的年龄不符合规定"); } } }
package Encapsulation; public class Encapsulation { public static void main(String[] args) { // A a = new A("joshua",2000); A a = new A("joshua",18); System.out.println(a.getAge()); System.out.println(a.getName()); // 20 // joshua } }
2.继承(Inherit)
官方解释:继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可
我的理解: 子类继承父类 子类 可以减少 代码量 提高代码的复用率
2.1 继承的具体十大细节:
-
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访
问,要通过父类提供公共的方法去访问
父类 public class Animal { private String name; private double weight; public Animal(String name, double weight) { // this.name = name; // this.weight = weight; // this is encapsulation setName(name); setWeight(weight); } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } } 子类 public class Dog extends Animal { //这里一开始会报错是因为 有 super() 会找默认的构造器 父类的构造器哦被覆盖率 没有了 就报错 //定义 dog 特有 的属性 private String color; public Dog(String name, double weight,String color) { //这里调用父类的构造器哦 super(name, weight); // this.color = color; setColor(color); } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } 测试 public class Test { public static void main(String[] args) { Dog dog = new Dog("汪汪",100,"yellow"); Pig pig = new Pig("哼哼",300,"pink"); //查看属性 System.out.println(dog.getName()+" "+dog.getWeight()+" "+ dog.getColor() ); // 私有化的getColor方法 没有提供public 直接访问就会报错 color' has private access in 'inheritance.Dog' // 汪汪 100.0 yellow 下面的pig 不举列子了 } }
2.子类必须调用父类的构造器, 完成父类的初始化
核心代码 父类 // 默认的constructor public Animal() { System.out.println("我是父类无参constructor"); } public Animal(String name) { System.out.println("我是父类的有参构造器哦"); } 子类 //对应父类的无参constructor public Dog() { System.out.println("我是子类constructor"); } //有参constructor public Dog(String color) { super("joshua");//指定调用父类自定义的有参构造器 // 不指定就会调用父类的无参构造器 this.color = color; System.out.println("我是子类的有参构造器"); } 测试 //2. 子类必须调用父类的构造器, 完成父类的初始化 Dog dog1 = new Dog(); // 我是父类constructor // 我是子类constructor System.out.println("========="); Dog dog2 = new Dog("blue"); // 我是父类的有参构造器哦 我是子类的有参构造器
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译
不会通过(怎么理解。) [举例说明
父类 // 默认的constructor public Animal() { System.out.println("我是父类无参constructor"); } public Animal(String name) { System.out.println("我是父类的有参构造器哦"); } 子类 public Dog(String color) { super("joshua");//指定调用父类自定义的有参构造器 // 不指定就会调用父类的无参构造器 this.color = color; System.out.println("我是子类的有参构造器"); } 测试 Dog dog1 = new Dog(); // 我是父类constructor // 我是子类constructor System.out.println("========="); Dog dog2 = new Dog("blue"); // 我是父类的有参构造器哦 我是子类的有参构造器 很上面一样的 哈哈哈 我的理解是 完成子类的初始化 必须要先完成 父类的初始化 现有爸爸 才有儿子嘛 其中 子类 必须 指定 父类 的 构造器 了 不知道 就是会调用默认的啦 就相当于 儿子 要选择 爸爸 不指定就是默认的爸爸(就是我啦 哈哈哈 坏笑)
4.如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表) 上面有不说辣
5.super 在使用时,必须放在构造器第一行
super语句在 构造器的代码块中的 只能放在 第一行 必须完成对父类的初始化 完成继承
注意 super() 和 this() 不能同时使用在构造器中 这里 简单说明一下 super() 和 this()
super("") 直接调用父类的构造器 this("") 先看自己本类有没有 对应的构造器 再去 父类看有没有对应的构造器 、
6.super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
7.java 所有类都是 Object 类的子类, Object 是所有类的基类
for example String 是 Object 的子类
8.父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
所有对象初始化的时候会先加载Object 再 加载下面的类
9.子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。
思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】
10。 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
父类 person 子类 animal 这是不行的 父类和子类要有逻辑关系
2.继承的本质
package inheritance.theory; //cv hsp java course 眼ヾ(≧▽≦*)oヾ(≧▽≦*)o public class Test { public static void main(String[] args) { Son son = new Son();//内存的布局 //?-> 这时请大家注意,要按照查找关系来返回信息 //(1) 首先看子类是否有该属性 //(2) 如果子类有这个属性,并且可以访问,则返回信息 //(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..) //(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object... System.out.println(son.name);//返回就是大头儿子 //System.out.println(son.age);//返回的就是 39 //System.out.println(son.getAge());//返回的就是 39 System.out.println(son.hobby);//返回的就是旅游 } } class GrandPa { //爷类 String name = "大头爷爷"; String hobby = "旅游"; } class Father extends GrandPa {//父类 String name = "大头爸爸"; private int age = 39; public int getAge() { return age; } } class Son extends Father { //子类 String name = "大头儿子"; }
我的理解: 一开始是从顶级父类Object到父类再到子类 加载的 查找呢 是从 当前类开始查找 没有 向上找 找到为止 找不带就报错了
3.详解 super 关键字
1.super 代表父类的引用,用于访问父类的属性、方法、构造器
2.super. 属性or 方法 可以访问父类的属性和方法 但不能访问父类的private属性
3.super("") 只能放在构造器的第一行 只能出现一句
爷爷类 public class Grandpa { public String name = "牛爷爷"; public int age = 80; public String hobby = "fishing"; public void test() { System.out.println("I am grandpa method"); } } 父类 public class Father extends Grandpa{ public String name = "胡英俊"; public int age = 40; public String hobby = "play game"; private String secret = "hide Private money"; public String getSecret() { return secret; } public void test() { System.out.println("I am father method"); } } 儿子类 public class Son extends Father{ public String name = "胡图图"; public int age = 8; // public String hobby = "feed pet"; // // public void test() { // System.out.println("I am son method"); // } public void showFather() { // System.out.println(super.name+" "+super.age +" "+super.secret());//super不能访问父类 的私有方法和属性 System.out.println(super.name+" "+super.age +" "+super.getSecret()); } public void superMethod() { super.test(); } public void thisMethod() { this.test(); } }
这里区别一下this 和 super 的区别
pm -> property or method
1.先说 this.pm 和 pm 一样 都是调用本类的方法 找不到本类的 再往上找
2.this.pm 和 super.pm this.pm 先查看本类的没有往上找 super 直接看父类的 没有 再往上找
3.this() 和 super( ) cv this() 先查看本类的没有往上找 super() 直接看父类的 没有 再往上找
3.多态(Polymorphisms)
1.方法重写/覆盖(override)
在继承条件下 子类对父类的方法进行内容的改变 返回值 方法名 修饰符都是一样的 形参列表相同
1.细节:/细节: 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类 (子类 String 父类 Object)
2.//细节: 子类方法不能缩小父类方法的访问权限 【演示】//public > protected > 默认>private
2.方法重载
方法在本类 方法名 必须一样 形参列表 类型要 不一样 返回 无要求 修饰符无要求
3.多态的正式介绍
1.什么是多态
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
我的理解:一个事物 类 有多种 表现形式
2.方法 的多态
public static void main(String[] args) { //方法重载体现多态 A a = new A(); //这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态 System.out.println(a.sum(10, 20)); System.out.println(a.sum(10, 20, 30)); //方法重写体现多态 B b = new B(); a.say(); b.say(); }
/方法重写体现多态 B b = new B(); a.say(); b.say(); } } class B { //父类 public void say() { System.out.println("B say() 方法被调用..."); } } class A extends B {//子类 public int sum(int n1, int n2){//和下面 sum 构成重载 return n1 + n2; } public int sum(int n1, int n2, int n3){ return n1 + n2 + n3; } public void say() { System.out.println("A say() 方法被调用..."); } }
3.对象的多态
1.一个对象的编译类型和运行类型可以不一致
2.编译类型在定义对象的时候 就 确定了 不能改变
3.运行类型是可以变化的
4.编译类型 = 左边 运行类型 = 右边
Animal animal = new Cat()
问属性时 看他的编译类型
5.多态的细节
多态的前提是:两个对象(类)存在继承关系多态的向上转型:
Animal animal = new Cat();
public class Test { public static void main(String[] args) { // Cat cat = new Cat("marry","pink"); // cat.hello();//hello marry //向上转型 Animal animal = new Cat("marry","pink"); animal.hello();// 查找自己本类的hello marry 对父类的方法重写了 animal.animal();//可以调用父类的方法 // // animal.hobby();//编译类型是Animal 直接编译Animal类型的属性和方法 运行类型是cat //向下转型 Cat cat = (Cat) animal;// 这里的animal必须是指向当前目标类型的 cat.hobby(); cat.animal();//也可以调用父类 的方法 } } public class Animal { private String name; public Animal(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void hello() { System.out.println("hello"); } public void animal() { System.out.println("animal"); } } public class Cat extends Animal{ private String name; private String color; public Cat(String name, String color) { super(name); this.color = color; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public void hello() { System.out.println("hello "+super.getName()); } public void hobby() { System.out.println("I like fish"); } }
向下转型
Cat cat = (Cat) animal; // 这里把animal的运行类型 转化成了cat cat.catchMouse();//猫抓老鼠
注意点
1.属性没有重写之说!属性的值看编译类
2.只要编译过了才有运行类型
3.方法看 运行类型 向上转型的时候 调用 子类的特有方法是不可行的 因为编译没有过去
可以向下转型
4.instanceof 直接看运行类型是不是相等
4.java 的动态绑定机制(非常非常重要.)
1.当调用对象方法的时候 该方法会和该对象的内存地址 / 运行类型绑定
-
当调用对象属性的时 没有动态绑定 哪里申明 那里使用