定义:实现信息隐藏,在java中经过关键字private,protected和public实现封装,利用抽象数据类型将数据和基于数据的操做封装在一块儿,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽量地隐藏内部的细节,只保留一些对外接口使之与外部联系。外部对象只能经过已经受权的操做来与这个封装的对象进行交流和交互。java
好处:良好的封装可以减小耦合;安全
类内部结构能够自由修改;this
能够对成员进行更精确的控制;code
隐藏信息,实现细节;对象
不封装的时候一个实体类是这么写的继承
public class Husband { public String name ; public int age ; public Wife wife; }
咱们在使用的时候是这么使用的:接口
public Demo{ public static void mian(String[] args){ Husband husband = new Husband(); husband.age = 30; husband.name = "张三"; } }
问题来了,若是哪一天个人年龄须要的是String类型,那么此时若是有几十个上百个类在引用这个实体类,是否是意味着这要修改这几十个类的年龄为String,累不累?开发
那么封装之后能够怎么作的呢,先看看封装后的这个实体类是怎么样的:get
public class Husband { /* * 对属性的封装 * 一我的的姓名、年龄、妻子都是这我的的私有属性 */ private String name ; private int age ; private Wife wife; /* * setter()、getter()是该对象对外开发的接口 */ 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 void setWife(Wife wife) { this.wife = wife; } }
如今解决修改年龄为String的解决办法只须要修改一处编译器
public class Husband { /* * 对属性的封装 * 一我的的姓名、年龄、妻子都是这我的的私有属性 */ private String name ; private String age ; private Wife wife; /* * setter()、getter()是该对象对外开发的接口 */ public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(int age) { this.age = String.valueOf(age); } public void setWife(Wife wife) { this.wife = wife; } }
又好比输入的年龄是1000岁,真把本身当成太子爷(千岁爷)了,这是不符合常识的,这也能够在这个实体类中进行控制,又好比,咱们存的是0和1显示的结果是男和女,就能够在get方法里面进行控制。
继承描述的是“is a”的关系,若是有两个对象A和B若能够描述为“A是B”,则能够表示A继承B,其中B是被继承者称之为父类或者超类,A是继承者称之为子类或者派生类。
关于继承必需要说的三个概念:构造器,protected关键字,向上转型
构造器,除了private的方法和属性之外,父类的构造器也是子类继承不了的。对于构造器而言,它只可以被调用,而不能被继承。调用父类的构造方法咱们使用super()便可。
构造器的构建过程是从父类开始向子类一级一级地完成构建。编译器会默认给子类调用父类的构造器。可是这个调用父类的构造器是有前提的:父类有默认构造器。若是父类没有默认构造器,咱们就要必须使用super()来调用父类构造器(必须在子类构造器第一行代码中声明),不然编译会报错。
protected访问修饰符,在范文范围中是比private,默认大,比public的修饰符小,同包中能够访问,不一样包的子类亦可访问。
向上转型,将子类转换成父类,在继承关系上面是向上移动的,因此通常称之为向上转型。因为向上转型是由一个叫专用类型向较通用类型转换,因此它老是安全的,惟一发生变化的可能就是属性和方法的丢失。
继承也是存在缺陷的:父类变,子类就必须变;继承是破坏了封装,对于父类而言,它的实现细节对于子类来讲是彻底透明的;继承是一种强耦合;
指向子类的父类引用因为向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,一定是使用子类中定义的这些方法(动态链接、动态调用)。实现形式能够是继承也能够是接口,还能够是内部类
public class Wine { public void fun1(){ System.out.println("Wine 的Fun....."); fun2(); } public void fun2(){ System.out.println("Wine 的Fun2..."); } } public class JNC extends Wine{ /** * @desc 子类重载父类方法 * 父类中不存在该方法,向上转型后,父类是不能引用该方法的 * @param a * @return void */ public void fun1(String a){ System.out.println("JNC 的 Fun1..."); fun2(); } /** * 子类重写父类方法 * 指向子类的父类引用调用fun2时,一定是调用该方法 */ public void fun2(){ System.out.println("JNC 的Fun2..."); } } public class Test { public static void main(String[] args) { Wine a = new JNC(); a.fun1(); } } ------------------------------------------------- Output: Wine 的Fun..... JNC 的Fun2...
编译时多态,指的是方法的重载,这是静态的重载,而运行时的多态,是经过动态绑定实现的,也就是咱们说的多态。
实现多态必要条件:继承(实现)、重写、向上转型,下面是一个很好体现了继承的特色的示例,继承链条末端的优先权最高,越往上越低
public class A { public String show(D obj) { return ("A and D"); } public String show(A obj) { return ("A and A"); } } public class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } public class C extends B{ } public class D extends B{ } public class Test { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("1--" + a1.show(b)); System.out.println("2--" + a1.show(c)); System.out.println("3--" + a1.show(d)); System.out.println("4--" + a2.show(b)); System.out.println("5--" + a2.show(c)); System.out.println("6--" + a2.show(d)); System.out.println("7--" + b.show(b)); System.out.println("8--" + b.show(c)); System.out.println("9--" + b.show(d)); } } ---ouput 1--A and A 2--A and A 3--A and D 4--B and A 5--B and A 6--A and D 7--B and B 8--B and A 9--B and A