272,包基本介绍
-
包的三大作用
1,区分相同的类 2,当类很多时,可以很好的管理类 3,控制访问范围
包基本用法
package com.hspedu; 说明: 1,package 关键字,表示打包 2,com.hspedu,表示包名
-
包的本质分析(原理)
包的本质 实际上就是创建不同的文件夹/目录 来保存类文件
不同包下的Dog类
import com.xiaoqiang.Dog; public class test1 { public static void main(String[] args) { Dog dog = new Dog();//不导入包的话,也可以 com.xiaoqiang.Dog dog = new com.xiaoqiang.Dog(); System.out.println(dog); com.xiaoming.Dog dog1 = new com.xiaoming.Dog();//不能再导入包,否则上面的dog会分不清 System.out.println(dog1); } }
运行结果:
-
包命名
命名规则:只能包含数字,字母,下划线,小圆点.,但不能用数字开头,不能是关键字或保留字
命名规范:一般是小写字母+小圆点。比如:com.公司名.项目名.业务模块名 举例:com.sina.crm.user
-
包的使用细节:
1,package 的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package。比如 package com.hspedu.pkg
2,import指令 位置放在 package 的下面,在类定义前面,可以有多句且没有顺序要求。
3,我们引入一个包的主要目的是要使用该包下的类 import java.util.Scanner 表示只会引入java.util 包下的Scanner;import java.util.* 表示将java.util 包下的所有类都引入(导入)
建议:我们需要使用到哪个类,就导入哪个类即可,不建议使用 * 导入
278,访问修饰符
280,封装介绍
对电视机的操作就是典型封装。
类中的 set, get 方法用 快捷键 fn + alt + insert (笔记本)生成
286,继承原理图
父类 Student 代码
package com.extend_.improve; public class Student { //是Pupil的父类 //共有的属性 public String name; public int age; private double score;//私有需要通过set来访问设置 //共有的方法 public void setScore(double score) { this.score = score; } public void showInfo() { System.out.println("学生名 " + name + " 年龄 " + age + " 成绩 " + score); } }
子类 Pupil 代码
package com.extend_.improve; public class Pupil extends Student{ public void testing() { System.out.println("小学生 " + name + " 正在考小学数学"); } }
主类 Extends 代码
package com.extend_.improve;//导入包就能用包下的所有类了 public class Extends { public static void main(String[] args) { com.extend_.improve.Pupil pupil = new Pupil(); pupil.name = "银角大王"; pupil.age = 11; pupil.testing();//pupil类自己的方法 pupil.setScore(60);//调用父类方法 pupil.showInfo();//调用父类方法 } }
运行结果:
288,继承使用细节
1,子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问
父类代码
package com.extend_.improve; public class Student { //是Pupil的父类 //4个属性 public int n1 = 1; protected int n2 = 2; int n3 = 3; private int n4 = 4; public Student()//无参构造器 { System.out.println("Student()...."); } //父类提供一个public的方法,返回了n4 public int getN4() { return n4; } public void test1() { System.out.println("test1"); } protected void test2() { System.out.println("test2"); } void test3() { System.out.println("test3"); } private void test4() { System.out.println("test4"); } public void callTest4() { test4(); } }
子类代码
package com.extend_.improve; public class Pupil extends Student{ public Pupil()//构造器 { System.out.println("Pupil()...."); } public void sayOk()//子类方法 { //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问 System.out.println(n1 + " " + n2 + " " + n3); test1(); test2(); test3(); //要通过父类提供的公共方法去访问 System.out.println("n4 = " + getN4()); callTest4(); } }
主类代码
package com.extend_.improve;//导入包就能用包下的所有类了 public class Extends { public static void main(String[] args) { Pupil pupil = new Pupil(); pupil.sayOk(); } }
运行结果:
2,子类必须调用父类的构造器,完成父类的初始化
3,当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器;如果父类没有提供无参构造器,则必须在子类的构造器中用 super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
以下是父类没有提供无参构造器的代码
父类代码
package com.extend_.improve; public class Student { //是Pupil的父类 //4个属性 public int n1 = 1; protected int n2 = 2; int n3 = 3; private int n4 = 4; // public Student()//无参构造器 // { // System.out.println("父类Student()构造器被调用...."); // } public Student(int num1, int num2) { System.out.println("父类Student(int num1, int num2)构造器被调用...."); } }
子类代码
package com.extend_.improve; public class Pupil extends Student{ public Pupil()//构造器 { super(10,10); System.out.println("子类Pupil()构造器被调用...."); } public Pupil(int num1) { super(10,10); System.out.println("子类Pupil(int num)构造器被调用...."); } }
主类代码
package com.extend_.improve;//导入包就能用包下的所有类了 public class Extends { public static void main(String[] args) { System.out.println("=====第一个对象====="); Pupil pupil1 = new Pupil(); System.out.println("=====第二个对象====="); Pupil pupil2 = new Pupil(1); } }
运行结果
4,如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表)
5,super在使用时,需要放在构造器第一行
6,super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器。super() 是调用父类构造器的,this()是调用本类构造器的
7,java 所有类都是 Object 类的子类,Object 类是所有类的基类。按 ctrl + h 可以看到类的继承关系。
8,父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
9,子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。
10,不能滥用继承,子类和父类之间必须满足合理的关系
293,继承本质详解
如果要访问 son.age,要按照查找关系来返回信息
(1),首先看子类是否有该属性
(2),如果子类有这个属性,并且可以访问,则返回信息
(3),如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)
(4),如果父类没有就按照(3)的规则,继续找上级父类,直到 Object
297,super 基本语法
298,super 使用细节
如果没有重名,使用super,this,直接访问,这3种方法都能访问到父类的非私有的属性和方法。
this 查找的规则
(1),先找本类,如果有,则调用
(2),如果没有,则找父类(如果有,并可以调用,则调用)
(3),如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object 类
提示:如果查找属性的过程中,找到了,但是不是访问,则保错, cannot access
如果查找方法的过程中,没有找到,则提示方法不存在
300,super使用细节3
1,super 和 this 的比较
301,方法重写介绍
父类 Animal 代码
package com.extend_.improve; public class Animal { public void cry() { System.out.println("动物叫唤...."); } }
子类 Dog 代码
package com.extend_.improve; public class Dog extends Animal{ public void cry()//Dog 类的 cry 方法和 Animal 的 cry 定义形式一样(名称,返回类型,参数),这时我们就说 Dog 的 cry 方法,重写了 Animal 的 cry 方法 { System.out.println("小狗叫唤...."); } }
主类 代码
package com.extend_.improve;//导入包就能用包下的所有类了 public class Extends { public static void main(String[] args) { Dog dog = new Dog(); dog.cry(); } }
运行结果:
302,方法重写细节
303,重写课题练习1
-
方法的重写和重载做一个比较
305,养宠物引出多态
有两个父类:Food类 和 Animal类。其中 Food类的子类是Bone类和Fish类,Animal类的子类是Dog类和Cat类。Master主人类的方法是会用到food类和Animal类的子类,主类是Poly类。
Food类代码
package com.extend_.improve; public class Food { private String name;//私有属性,类外的话需要通过get方法来访问 public Food(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Bone类代码
package com.extend_.improve; public class Bone extends Food{ public Bone(String name) { super(name); } }
fish类代码
package com.extend_.improve; public class Fish extends Food{ public Fish(String name) { super(name);//访问父类 Food的构造器,来完成对name的初始化 } }
Animal类代码
package com.extend_.improve; 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; } }
Dog类代码
package com.extend_.improve; public class Dog extends Animal{ public Dog(String name) { super(name); } }
Cat类代码
package com.extend_.improve; public class Cat extends Animal{ public Cat(String name) { super(name); } }
Master类
package com.extend_.improve;//导入包就能用包下的所有类了 public class Master { private String name; public Master(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void feed(Dog dog, Bone bone) { System.out.println("主人 " + name + " 给 " + dog.getName() + " 吃 " + bone.getName()); } public void feed(Cat cat, Fish fish) { System.out.println("主人 " + name + " 给 " + cat.getName() + " 吃 " + fish.getName()); } }
Poly类代码
package com.extend_.improve; public class Poly { public static void main(String[] args) { Master tom = new Master("汤姆"); Dog dog = new Dog("大黄"); Bone bone = new Bone("大棒骨"); Cat cat = new Cat("猫"); Fish fish = new Fish("鱼干"); tom.feed(dog, bone); tom.feed(cat, fish); } }
运行结果:
从Master类的feed方法看的话,如果动物很多,食物很多,那feed方法就很多,代码复用性不高,而且不利于管理和维护。所以引出多态来解决传统的方法带来的问题。
306,方法的多态
-
多态的具体体现
(1) 重写和重载就体现多态
package com.poly_; public class PolyMethod { public static void main(String[] args) { //方法重载体现多态 A a = new A(); //这里我们传入不同的参数,就会调用不同sum方法,就体现多态 System.out.println(a.sum(1,2)); System.out.println(a.sum(1,2,3)); //方法重写体现多态 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() 方法被调用..."); } }
(2)对象的多态(核心,困难,重点)
Animal类的子类是 Dog类和Cat类,主类是Poly类。
Animal类代码
package com.extend_.improve; public class Animal { public void cry() { System.out.println("Animal cry() 动物在叫..."); } }
Dog类代码
package com.extend_.improve; public class Dog extends Animal{ public void cry() { System.out.println("Dog cry() 小狗汪汪叫..."); } }
Cat类代码
package com.extend_.improve; public class Cat extends Animal{ public void cry() { System.out.println("Cat cry() 小猫喵喵叫..."); } }
Poly类代码
package com.extend_.improve; public class Poly { public static void main(String[] args) { //体验对象多态特点 //animal 编译类型就是 Animal,运行类型 Dog Animal animal = new Dog(); //因为运行时,执行到该行时,animal运行类型是Dog,所以cry就是Dog的cry animal.cry(); //animal 编译类型就是 Animal,运行类型 Cat animal = new Cat(); animal.cry(); } }
运行结果:
308,多态快速入门
在 305,养宠物引出多态 这节的代码里,我们只需要把Master类代码改成如下代码就能实现多态。再运行主类Poly类代码就能得到相同的结果。
package com.extend_.improve;//导入包就能用包下的所有类了 public class Master { private String name; public Master(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } //使用多态机制,可以统一的管理主人喂食的问题 //animal 编译类型是Animal,可以指向(接收)Animal子类的对象 //food 编译类型是Food,可以指向(接收)Food子类的对象 public void feed(Animal animal, Food food) { System.out.println("主人 " + name + " 给 " + animal.getName() + " 吃 " + food.getName()); } }
309,向上转型
因为在编译阶段,能调用哪些成员,是由编译类型决定的
最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,然后调用,规则和前面讲的方法调用规则一致。
310,向下转型
比如 Animal animal = new Cat(); Cat cat = (Cat) animal;
311,属性重写问题
1,属性没有重写之说,属性的值看编译类型
package com.poly_; public class PolyMethod { public static void main(String[] args) { //属性没有重写之说,属性的值看编译类型 Base base = new Sub();//向上转型 System.out.println(base.count); Sub sub = new Sub(); System.out.println(sub.count); } } class Base//父类 { int count = 10;//属性 } class Sub extends Base{ //子类 int count = 20;//属性 }
运行结果:
2,instanceof 用于判断对象的运行类型是否为某某类型 或 某某类型的子类型
package com.poly_; public class PolyMethod { public static void main(String[] args) { B b = new B(); System.out.println(b instanceof B); System.out.println(b instanceof A); } } class A{} //父类 class B extends A{} //子类
运行结果:
314,动态绑定机制
package com.poly_; public class PolyMethod { public static void main(String[] args) { //a 的编译类型 A,运行类型 B A a = new B();//向上转型 System.out.println(a.sum()); System.out.println(a.sum1()); } } class A{ public int i = 10; //动态绑定机制,getI和运行类型B绑定,调用B的getI方法 public int sum() { return getI() + 10; } public int sum1() { return i + 10; //i 是属性,没有绑定机制,在A类里声明了,所以i=10 } public int getI() { return i; } } class B extends A { public int i = 20; public int getI() { return i; } }
运行结果:
315,多态数组1
多态数组:数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
Person类是Student类和Teacher类的父类。
Person类代码
package com.poly_; public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String say() { return name + "\t" + age; } }
Student类代码
package com.poly_; public class Student extends Person { private int id; private int score; public Student(String name, int age, int id) { super(name, age); this.id = id; this.score = score; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } //重写父类say public String say() { return "学生 " + super.say() + " score = " + score; } }
Teacher类代码
package com.poly_; public class Teacher extends Person{ private double salary; public Teacher(String name, int age, double salary) { super(name, age); this.salary = salary; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public String say() { return "老师 " + super.say() + " salary = " + salary; } }
主类代码
package com.poly_; public class PolyMethod { public static void main(String[] args) { Person[] persons = new Person[5]; persons[0] = new Person("jack", 20); persons[1] = new Student("jack",18,100); persons[2] = new Student("smith",19,30); persons[3] = new Teacher("scott",30,20000); persons[4] = new Teacher("king",50,25000); //循环遍历多态数组,调用say for(int i = 0; i < persons.length; i++) { //persons[i] 编译类型是Person,运行类型是根据实际情况由JVM来判断 System.out.println(persons[i].say());//动态绑定机制 } } }
运行结果:
316,多态数组2
在Teacher类里添加teach方法
//特有方法 public void teach() { System.out.println("老师 " + getName() + " 正在讲java课程..."); }
在Student类里添加study方法
//特有方法 public void study() { System.out.println("学生 " + getName() + " 正在学java..."); }
主类代码
package com.poly_; public class PolyMethod { public static void main(String[] args) { Person[] persons = new Person[5]; persons[0] = new Person("jack", 20); persons[1] = new Student("jack",18,100); persons[2] = new Student("smith",19,30); persons[3] = new Teacher("scott",30,20000); persons[4] = new Teacher("king",50,25000); //循环遍历多态数组,调用say for(int i = 0; i < persons.length; i++) { //persons[i] 编译类型是Person,运行类型是根据实际情况由JVM来判断 System.out.println(persons[i].say());//动态绑定机制 if(persons[i] instanceof Student)//判断person[i]的运行类型是不是Student { Student student = (Student)persons[i];//向下转型 student.study(); }else if(persons[i] instanceof Teacher) { Teacher teacher = (Teacher)persons[i]; teacher.teach(); }else if(persons[i] instanceof Person) { //里面不写是因为如果persons[i]是Person类型的话,那就不用管 }else { System.out.println("你的类型有误,请自己检查..."); } } } }
运行结果:
317,多态参数
父类 Employee类 代码
package com.poly_; public class Employee { //员工类 private String name; private double salary; public Employee(String name, double salary) { this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public double getAnnual() { return 12 * salary; } }
子类Worker类 代码
package com.poly_; public class Worker extends Employee {//普通员工类 public Worker(String name, double salary) { super(name, salary); } public void work() { System.out.println("普通员工 " + getName() + " is working"); } @Override public double getAnnual() { return super.getAnnual(); } }
子类Manager类 代码
package com.poly_; public class Manager extends Employee{ private double bonus; public Manager(String name, double salary, double bonus) { super(name, salary); this.bonus = bonus; } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public void manage() { System.out.println("经理 " + getName() + " is managing"); } @Override public double getAnnual() { return super.getAnnual() + bonus; } }
主类代码
package com.poly_; public class Equals { public static void main(String[] args) { Worker tom = new Worker("tom", 2500); Manager milan = new Manager("milan",5000,20000); Equals equals = new Equals(); equals.showEmpAnnual(tom); equals.showEmpAnnual(milan); } public void showEmpAnnual(Employee e)//形参是父类类型Employee类,实参是子类类型Worker类和Manager类 { System.out.println(e.getAnnual());//动态绑定机制,方法看运行类型 } }
运行结果:
318, ==运算符
320,子类重写equals
结论:
Object类的equals 方法默认就是比较对象地址是否相同,也就是判断两个对象是不是同一个对象。
String类的 equals 方法把Object的 equals 方法重写了,变成了比较两个字符串值是否相等。
Interger类也重写了Object的 equals 方法,变成了判断两个值是否相同。
321,equals课堂练习1
1,判断两个Person对象的内容是否相等,如果两个Person对象的各个属性值都一样,则返回true,反之false
思路:Person类中没有equals方法,所以会到默认的父类 Object类找equals方法,而Object类的equals方法默认是比较是否为同一个对象,看地址是否相同,明显和题目要求的不符,所以本题要在 Person 类里重写 Object类的 equals 方法。不用 == ,因为Person是引用类型。
package com.poly_; public class Equals { public static void main(String[] args) { Person person1 = new Person("jack", 10, '男'); Person person2 = new Person("jack", 10, '男'); System.out.println(person1.equals(person2)); } } class Person{ //extends Object private String name; private int age; private char gender; public Person(String name, int age, char gender) { this.name = name; this.age = age; this.gender = gender; } public boolean equals(Object obj)//多态参数 { if(this == obj)//判断如果比较的两个对象是同一个对象,则直接返回true { return true; } if(obj instanceof Person) //是 Person,我们才比较 { Person p = (Person)obj;//进行向下转型,因为我需要得到obj的各个属性 return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender; } return false; } }
运行结果:
324,hashCode
package com.poly_; public class Equals { public static void main(String[] args) { A a1 = new A(); A a2 = new A(); A a3 = a1; System.out.println("a.hashCode() = " + a1.hashCode()); System.out.println("a.hashCode() = " + a2.hashCode()); System.out.println("a.hashCode() = " + a3.hashCode()); } } class A{}
运行结果:
325,toString
1,Object的toString()源码
(1)getClass().getName() 类的全类名(包名+类名)
(2)Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
package com.poly_; public class Equals { public static void main(String[] args) { Monster monster = new Monster("小妖怪", "巡山的", 1000); System.out.println(monster.toString()); } } class Monster{ private String name; private String job; private double sal; public Monster(String name, String job, double sal) { this.name = name; this.job = job; this.sal = sal; } }
运行结果:
2,在Monster类里重写 toString方法,输出对象的属性
快捷键 Fn + Alt + insert
package com.poly_; public class Equals { public static void main(String[] args) { Monster monster = new Monster("小妖怪", "巡山的", 1000); System.out.println(monster.toString()); } } class Monster{ private String name; private String job; private double sal; public Monster(String name, String job, double sal) { this.name = name; this.job = job; this.sal = sal; } @Override public String toString() { return "Monster{" + "name='" + name + '\'' + ", job='" + job + '\'' + ", sal=" + sal + '}'; } }
运行结果:
3,直接输出一个对象时,toString方法会被默认调用
package com.poly_; public class Equals { public static void main(String[] args) { Monster monster = new Monster("小妖怪", "巡山的", 1000); System.out.println(monster.toString()); System.out.println("==当直接输出一个对象时,toString方法会被默认的调用=="); System.out.println(monster);//等价于 monster.toString() } } class Monster{ private String name; private String job; private double sal; public Monster(String name, String job, double sal) { this.name = name; this.job = job; this.sal = sal; } @Override public String toString() { return "Monster{" + "name='" + name + '\'' + ", job='" + job + '\'' + ", sal=" + sal + '}'; } }
运行结果:
326,finalize
327,断点调试
标签:java,String,void,class,面向对象,顺平,com,public,name From: https://www.cnblogs.com/romantichuaner/p/18059704