//类 private: 私有 /* 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.系统的可维护性增加了 */ public class Student { //属性私有 private String name;//名字 private int id;//学号 private char sex;//性别 private int age;//年龄 //提供一些可以操作这个属性的方法 //提供一些public的 get set的方法 //get 获得这个数据 public String getName(){ return this.name; } //set给这个数据设置值 public void setName(String name){ this.name = name; } //alt + insert public int getId() { return id; } public void setId(int id) { this.id = id; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { if(age>120||age<0){//不合法 this.age = 3; }else{ this.age = age; } } /* public static void main(String[] args) { Student s1 = new Student(); String name = s1.getName(); s1.setName("zhiyuan"); System.out.println(s1.getName()); s1.setAge(999);//不合法 */ }
子类可以可以通过继承获取父类原有的字段和方法,也可以在父类的基础进行扩展,使用extends来表示子类和父类之间的继承关系,类之间只支持单继承,一个类只能有一个直接父类,可以多重继承
//在JAVA中,所有的类都默认直接或间接继承object //Person 人:父亲 public class Person /*extends object*/{ //public //protected //default //private private int money = 10_0000_0000; public void say(){ System.out.println("说了一句话"); } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } }
//Teacher is 人:子类,派生类 public class Teacher extends Person{ }
//学生 is 人:子类,派生类 //子类继承了父类,就会有父类的全部方法 public class Student extends Person{ //ctrl+h可以查看继承图 }
super
对比this
代表的对象不同
this:本身调用的这个对象
super:代表父类对象的应用
前提
构造方法
public class Student extends Person{ public Student(){ //隐藏代码:调用了父类父类无参构造 //super();调用父类的构造器,必须要在子类构造器的第一行 System.out.println("Student无参执行了"); } private String name = "xu"; public void print(){ System.out.println("xuzhiyuan"); } public void test1(){ print(); this.print(); super.print(); } public void test(String name){ System.out.println(name); System.out.println(this.name); System.out.println(super.name); } }
需要有继承关系,子类重写父类的方法
参数列表必须相同
修饰符:范围可以扩大 但不能缩小:Public>Protected>Default>Private
抛出的异常:范围可以被缩小但不能扩大;
重写,子类的方法和父类必须要一致,方法体不同
为什么需要重写
父类的功能,子类不一定需要,或者不一定满足
重写快捷键:Alt+Insert;override;
public class A extends B{ //Override 重写 @Override//注解:有功能的注释 public void test() { System.out.println("A=>test()"); } }
//重写是方法的重写,和属性无关 public class B { public void test( ){ System.out.println("B=>test()"); } }
public class Application { //静态方法和非静态的方法区别很大 //静态方法:方法的调用只和左边的定义数据有关 //非静态:重写之和非静态有关 //重写和public有关,子类要重写父类方法 , //父类方法不一定必须要public 只要子类重写方法的权限修饰符不必父类更严格就行 public static void main(String[] args) { A a = new A(); a.test(); //父类的引用指向了子类 B b = new A();//子类重写了父类的方法 b.test(); //静态方法时 //用B类新建了A类的对象,把A赋值给了B, //这时候B是A,A又继承了B类,向上转型。 //所以调用B类方法的时候,也就是B=>test //非静态方法时 //即b是A new出来的对象,因此调用了A的方法 //因为静态方法是类的方法,而非静态是对象的方法 //有static时,b调用了B类的方法,因为b是用b类定义的 //没有static时,b调用的是对象的方法,而b是用A类new的 //可参考这句话理解:static修饰的方法归类所有,叫类的成员,不叫对象的成员 } } //重载是同一类里,方法名相同,参数类型不同。 // 重写是子父类间,子类重写父类的方法, // alt+insert,方法名相同,方法内容不同。 // 使用public方式,且不使用static方式
public class Person { public void run() { System.out.println("run"); } /* 多态注意事项 1.多态是方法的多态,属性没有多态 2.父类和子类的联系 3.存在条件:继承关系,方法需要被重写,父类的引用指向子类对象 如:father f1 = new son(); 例外 1,static静态方法,属于类,不属于实例 2,final修饰的属于常量池里 3,private方法没法被重写,也没法实现多态 */
public class Student extends Person{ @Override public void run() { System.out.println("son"); } public void eat(){ System.out.println("eat"); } }
public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student(); //new Person(); //可以指向的引用类型就不确定了:父类的引用指向子类 //1. 使用父类类型的引用指向之类的对象 //2. 该引用只能调用父类中定义的方法和变量(非静态 //3. 如果子类中重写了父类中的一个方法,那么调用这个方法的时候,将会调用子类中的方法; //左边子类Student 能调用的方法都是自己或者继承父类的 Student s1 = new Student(); //左边父类Person,可以指向子类但是不能调用子类独有的方法 Person s2 = new Student(); Object s3 = new Student(); s2.run();//子类没有重写父类,就会调用父类方法, s1.run();//子类重写了父类的方法,就会执行子类的方法 ((Student)s2).eat();//强制转换可以实现子类调用自己的方法 //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大 } }
instanceof 类型转换
public static void main(String[] args) { //Object > Person > Student //Object > String //Object > Person > Teacher Object object = new Student(); //System.out.println(X instanceof Y); //能不能编译通过,取决于X的引用类型和Y有没有父子关系,无则无法编译 System.out.println(object instanceof Student);//true System.out.println(object instanceof Person);//ture System.out.println(object instanceof Object);//true System.out.println(object instanceof Teacher);//false System.out.println(object instanceof String);//false System.out.println("=============================="); Person person = new Student(); System.out.println(person instanceof Student);//true System.out.println(person instanceof Person);//ture System.out.println(person instanceof Object);//true System.out.println(person instanceof Teacher);//false //System.out.println(person instanceof String);//无法编译 System.out.println("==========================="); Student student = new Student(); System.out.println(student instanceof Student);//true System.out.println(student instanceof Person);//ture System.out.println(student instanceof Object);//true //System.out.println(student instanceof Teacher);//无法编译 //System.out.println(student instanceof String);//无法编译 //只要是在引用(比如这里的Object)和实例化对象类型(比如这里的Student)之间的任何一个引用, //都是有联系的。而不在这条线上的,都是无关的 //看=的编译是否通过看=左边的类型,实际判断对象变为=右边的类型。 }
子类父类转换
public static void main(String[] args) { //类型之间的转化:父 子 //子类转换为父类,可能会丢失自己的本来一些方法 //低(子)转高(父)时,由于子已经继承了父的所有,所以删去属于自己的后自然而然就可以转化问父类的; //而父想要转子,则需要重新开辟只属于子的空间,则需用强制转换 //高 低 Person per = new Student(); Student per1 = (Student) per; per1.go(); per1.run(); per.run(); ((Student)per).go(); System.out.println("======================="); Student s1 = new Student(); Person p1 = s1; p1.run(); //p1.go();报错 子转父后,无法再调用自身的独有go方法 Person p2 = new Student(); Student s2= (Student) p2; s2.run(); //简写则可以这样,省略其中的过程 //这里把per对象看作一个人 编译的时候去Person找go方法 运行的时候去执行Stduent的go方法 //但父类Person并没有go方法,必须要转化引用类型 //将这个per对象转换为Student引用类型的per1对象,就可以使用Student类型的方法了 //子类转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分) //只是暂时不可访问,所以能再强制转回来 } /* 1,父类引用指向(=)子类的对象,相反不行 2.把子类转换为父类,向上转型可以直接转换过去(会丢失子类独有的方法), 相反的向下转型的话,需要强制转换才行 3.方便方法的调用,减少重复的代码,简洁 抽象: 封装,继承,多态 */