5、继承
1 //Java中所有对象都显式/隐式的继承子Object类 2 class fu{ 3 fu(){ 4 System.out.println("fu..."+getNum()); 5 show(); 6 } 7 private int num=3; 8 public void setNum(int num){ 9 this.num=num; 10 } 11 public int getNum(){ 12 return num; 13 } 14 public void show(){ 15 System.out.println("这是fu类的show方法"); 16 } 17 } 18 /*0、继承表示两个类之间产生关系,用extends标示。注意子类不能继承父类中私有的属性,但是也可以通过公开方法访问 19 * 继承中有三个部分的问题: 20 * 1、成员变量的继承 21 * 2、成员方法的继承 22 * 3、构造函数的继承 23 */ 24 class zi extends fu{ 25 zi(){ 26 /*3、java中在子类的构造函数开始有一个隐藏操作:super(),这是为了对父类进行初始化操作,便于操作继承来的属性 27 * 和this()调用本类(无参)构造函数相似,super()可以调用父类的(无参)构造函数 28 * !!!注意默认情况下调用父类的无参构造函数 29 * !!!如果没有无参构造函数/需要传入参数,必须显式的使用super(args),调用对应有参构造函数 30 * !!!且super(args)必须定义在子类构造函数的第一句(this()也同样需要定义在第一行) 31 */ 32 System.out.println("zi"); 33 } 34 private int num=4; 35 int num2=5; 36 public void show(){ 37 int num=6; 38 /*1、变量的继承:一个函数块中使用的变量会在三个地方查找 39 * 1、函数块内,是局部变量 40 * 2、当前类内,成员变量 41 * 3、继承的类内,继承变量 42 * 如果没有指明,则以上面的顺序查找到的变量为准;当然也可以指明(this->本类对象,super->父类空间) 43 * !!!但是像这种子类和父类中使用同名变量的情况几乎不存在,因为既然在父类中定义就表明是共性内容, 44 * !!! 就不需要在子类中在进行操作 45 */ 46 System.out.println("函数块内num="+num+",类内num="+this.num+",父类中num="+super.getNum()); 47 /*2、方法的继承: 48 * !!!1、如果子类中没有同名方法:使用父类中的方法,并且运行环境是在父类 49 * !!! (用this调用变量是在父类,但是如果调用方法仍然是先找子类) 50 * 2、如果类中有同名方法:父类方法被覆盖,所以使用子类中方法,可以用super来指向父类对象。 51 */ 52 super.show(); 53 } 54 } 55 56 public class ObjectExtend { 57 public static void main(String[] args){ 58 zi z=new zi(); 59 z.show(); 60 } 61 }
1 public class Test { 2 public static void main(String[] args){ 3 zilei z=new zilei(); 4 } 5 } 6 class fulei{ 7 private int num=3; 8 9 public int getNum() { 10 this.show(); 11 return num; 12 } 13 14 public void setNum(int num) { 15 this.num = num; 16 } 17 public void show(){ 18 System.out.println("fulei"); 19 } 20 } 21 class zilei extends fulei{ 22 private int num=4; 23 /* 24 public int getNum() { 25 return num; 26 } 27 public void setNum(int num) { 28 this.num = num; 29 } 30 */ 31 zilei(){ 32 //这里调用getNum方法,子类中没有所以在父类中找;而父类该方法调用了show(),子类中有所以用子类的 33 System.out.println(this.getNum()); 34 } 35 public void show(){ 36 System.out.println("zilei"); 37 } 38 }
6、抽象类和接口:
1 /*有两类特殊的继承:抽象类(abstract class)和接口(interface),都是在向上抽离类的过程中出现的, 2 * 抽象类和普通类相似,只是包含抽象类而已,由abstract标示,!!!并且不能实例化,但是可以初始化 3 * 接口使用interface,不需要使用class,方法全都是抽象方法,同样不能实例化 4 * 5 * ☆注意:实例化和初始化的区别: 6 * 实例化是用new进行的,并将产生的对象首地址返回给变量以供操作 7 * 初始化是指将已存在的对象空间的变量进行赋值的过程,由jvm执行 8 * !!!综上:抽象类可以进行初始化是由jvm开辟一片内存空间,来进行初始化操作,但是不能由用户进行new操作 9 * !!!所以抽象类中可以使用this访问其中的属性 10 */ 11 public class ObjectExtend2 { 12 public static void main(String[] args){ 13 Programmer p=new Programmer("asd",1,5000); 14 p.work(); 15 } 16 } 17 18 /*其中的抽象方法没有方法体,并且用abstract修饰;类中有抽象方法,该类也必须用abstract修饰。 19 * 因为抽象类中有没有实现的方法,所以不能实例化;并且只有其子类将所有的抽象方法实现才能实例化 20 */ 21 /*下面是一个抽象类例子: 22 * 需求:公司中程序员有姓名,编号,工资等属性,行为是工作->写代码;还有经理除了上述属性还有奖金,行为是工作->管理。 23 * 对给出的需求进行数据建模 24 */ 25 abstract class Employee{ 26 private String name; 27 private int id; 28 private double pay; 29 public abstract void work(); 30 Employee(String name,int id,double pay){ 31 this.name=name; 32 this.id=id; 33 this.pay=pay; 34 } 35 public void setName(String name){ 36 this.name=name; 37 } 38 public String getName(){ 39 return name; 40 } 41 public void setId(int id){ 42 this.id=id; 43 } 44 public int getId(){ 45 return id; 46 } 47 public void setPay(int pay){ 48 this.pay=pay; 49 } 50 public double getPay(){ 51 return pay; 52 } 53 } 54 55 class Programmer extends Employee{ 56 Programmer(String name,int id,double pay){ 57 super(name,id,pay); 58 } 59 public void work(){ 60 System.out.println("I‘m "+this.getName()+",and is the "+this.getId()+" employee,for "+this.getPay()+"money,i‘m coding..."); 61 } 62 } 63 64 class Manage extends Employee{ 65 private int bonus; 66 Manage(String name,int id,double pay,int bonus){ 67 super(name,id,pay); 68 this.setBonus(bonus); 69 } 70 public int getBonus() { 71 return bonus; 72 } 73 public void setBonus(int bonus) { 74 this.bonus = bonus; 75 } 76 public void work(){ 77 System.out.println("manage!"); 78 } 79 } 80 81 /*接口中常见的成员包括:1、全局常量,2、抽象方法 82 * !!!类与类(包括抽象类)之间的关系为继承extends;类与接口之间的关系为实现implements; 83 * !!!接口与接口之间是继承关系(extends),而且只有在继承接口是可以多继承 84 * 接口中的抽象方法必须都实现,才能被实例化,否则是抽象子类 85 * 接口的一个优点是可以多实现,间接实现了多继承。这是因为即使实现的多个接口中有同名方法,它们都没有方法体, 86 * 而是由实现类完成的,所以无所谓 87 * !!!继承(extends)和接口(implements)可以同时进行 88 */ 89 interface Demo1{ 90 public static final int NUM=4; 91 public abstract void show1(); 92 public abstract void show2(); 93 } 94 95 interface Demo2{ 96 public abstract void show3(); 97 public abstract int show4(int a,int b); 98 } 99 100 class DemoImpl extends Programmer implements Demo1,Demo2{ 101 DemoImpl(String name,int id,double pay){ 102 super(name,id,pay); 103 } 104 public void show1(){ 105 106 } 107 public void show2(){ 108 109 } 110 public void show3(){ 111 112 } 113 public int show4(int a,int b){ 114 return a+b; 115 } 116 }
7、多态:
1 public class ObjectPolymorphism { 2 public static void main(String[] args){ 3 /*java中的多态简单来说就是一个对象对应着不同的类型(可以是本类类型,父类类型,实现的接口类型) 4 * 像下面的Dog对象转为Animal对象是类型提升/向上转型 5 * 当然转换后的类型也可以强制转换为Dog对象,但是不能强制转换为其他子类 6 */ 7 Animal dog=new Dog(); 8 /*dog1=(Dog)dog; 经过类型提升的对象才可以向下转型,若原来就是父类对象,就不允许向下转型 9 * cat=(Cat)dog; 不同类型不允许强制转换 10 */ 11 eat(dog); 12 work(dog); 13 } 14 /*多态是应对Java强类型语言在对象作为参数传递时的局限性, 15 * 例如下面,不同动物有不同的eat方法,如果只能传入具体动物类,则每个动物都需要写一个相应eat方法 16 * 但是内部的操作是一样的,所以只需传入父类类型即可,实现时根据具体的动物类型,调用其内部的eat方法。 17 */ 18 public static void eat(Animal a){ 19 a.eat(); 20 } 21 /*public static void eat(Cat c){ 22 * c.eat(); 23 * } 24 *public static void eat(Dog d){ 25 * d.eat(); 26 * } 27 */ 28 public static void work(Animal a){ 29 /*如果要判断具体的类型,可以使用instanceof关键字, 30 * 31 */ 32 if(a instanceof Cat){ 33 Cat c=(Cat)a; 34 c.catchMouse(); 35 }else if(a instanceof Dog){ 36 Dog d=(Dog)a; 37 d.kanjia(); 38 } 39 } 40 41 } 42 abstract class Animal{ 43 abstract void eat(); 44 } 45 class Cat extends Animal{ 46 void eat(){ 47 System.out.println("吃鱼"); 48 } 49 void catchMouse(){ 50 System.out.println("捉老鼠"); 51 } 52 } 53 class Dog extends Animal{ 54 void eat(){ 55 System.out.println("啃骨头"); 56 } 57 void kanjia(){ 58 System.out.println("看家"); 59 } 60 }
!!!注意:静态方法在静态区,不能覆盖
8、内部类:
1 public class InnerClass { 2 public static void main(String[] args){ 3 //通过外部类访问内部类,是在外部类中产生的内部类 4 outer o=new outer(); 5 o.function(); 6 o.function1(); 7 o.function2(); 8 //!!!上面方法的一种变形,就是把产生内部类的过程放在外面 9 outer.inner i=new outer().new inner(); 10 /*如果内部类是static修饰的,外部类一加载就存在了,所有访问时不需要创建外部类对象,即: 11 *outer.inner i=new outer.inner(); 12 */ 13 i.show(); 14 } 15 16 } 17 class outer{ 18 private int num=3; 19 //内部类:和js中的作用域链有点类同,就是本类中如果没有,会向外部寻找,但是依然有权限限制,如果外部是private,则只能在inner类的内部进行访问 20 //内部类的修饰符:private->只能在包含类中访问,外部不能访问;static->相当于外部类,访问情况见下 21 class inner{ 22 private int num=4; 23 void show(){ 24 int num=5; 25 //内部类与外部类变量重名时的访问 26 System.out.println("num="+num); //访问局部成员 27 System.out.println("this.num="+this.num); //访问内部类成员变量 28 //=System.out.println("inner.this.num="+inner.this.num); 29 System.out.println("outer.this.num="+outer.this.num); //访问外部类成员变量 30 } 31 } 32 void function(){ 33 inner i=new inner(); 34 i.show(); 35 } 36 void function1(){ 37 /*局部内部类:是将内部类定义在局部环境中,!!!如果此时内部类访问局部变量,需要使用final 38 * 这是因为Java是一种严谨的语言,考虑到了特殊的情况: 39 * 就是下面注释中展示的不是直接操作内部对象,而是将其返回到外部,然后进行操作,如果此时调用内部变量, 40 * 外部将报错,所以需要使用final修饰,使其永远可以访问 41 */ 42 final int NUM=6; 43 class inner{ 44 void say(){ 45 System.out.println("NUM="+NUM); 46 } 47 } 48 inner i=new inner(); 49 i.say(); 50 /*public inner getInnerObject(){ 51 * inner i=new inner(); 52 * return i; 53 *} 54 */ 55 } 56 void function2(){ 57 /*下面是一个匿名内部类的例子,直接创建一个父类/接口对象, 58 * 和对象不同的是有{}包含的抽象方法实现,这就是一个子类的匿名形式, 59 * 但是返回值是一个对象,如果要调用多个方法,可以用一个变量接收这个对象 60 * !!!注意接收这个对象的类型只能是父类的类型,此时向上转型,只能调用父类中有的方法 61 */ 62 Inner i=new Inner(){ 63 public void show1(){ 64 System.out.println("这是匿名内部类方法1"); 65 } 66 public void show2(){ 67 System.out.println("这是匿名内部类方法2"); 68 } 69 }; 70 i.show1(); 71 i.show2(); 72 } 73 } 74 abstract class Inner{ 75 abstract void show1(); 76 abstract void show2(); 77 }
总结:对象的初始化过程:
知识:设计模式。参考:http://zz563143188.iteye.com/blog/1847029
1 public class Singletion { 2 public static void main(String[] args){ 3 Singletiontest2 s1=Singletiontest2.getInstance(); 4 Singletiontest2 s2=Singletiontest2.getInstance(); 5 s1.setNum(10); 6 s2.setNum(20); 7 System.out.println(s1.getNum()==s2.getNum()); 8 System.out.println(s1.equals(s2)); 9 } 10 } 11 /*下面是一个简单的类,有一个私有属性,并提供了访问方式, 12 *如果现在又需求:只能产生一个类对象,产生过多则会浪费空间 13 *此时就可以进行单例模式设计 14 */ 15 class Singletiontest{ 16 private int num; 17 public int getNum() { 18 return num; 19 } 20 public void setNum(int num) { 21 this.num = num; 22 } 23 } 24 /*只要满足以下三个步骤就可以构成单例模式 25 * 1、其他类中不能通过new产生对象 --》将构造函数私有化 26 * 2、必须在本类中产生一个对象 --》在本类中new一个对象,并用私有属性保存 27 * 3、必须有一个方法将产生的对象提供出去以便其他类操作 --》将这个私有属性值返回调用处 28 * 注意: 29 * 单例是用类生成对象,所以生成对象的过程中所使用的都需要是static; 30 * 并且在获取对象过程中不能使用this关键字,之后由对象操作的部分才可以使用 31 */ 32 class Singletiontest2{ 33 private Singletiontest2(){} 34 private static Singletiontest2 instance=new Singletiontest2(); 35 public static Singletiontest2 getInstance(){ 36 return Singletiontest2.instance; 37 } 38 private int num; 39 public int getNum() { 40 return num; 41 } 42 public void setNum(int num) { 43 this.num = num; 44 } 45 } 46 /*单例模式的延迟加载写法:区别在于没有在加载时直接创建对象(static属性会在类加载时建立) 47 *而是在调用getInstance()时判断是否需要new 48 */ 49 class Singletiontest3{ 50 private Singletiontest3(){} 51 private static Singletiontest3 instance=null; 52 public static Singletiontest3 getInstance(){ 53 if(instance==null){ 54 instance=new Singletiontest3(); 55 } 56 return instance; 57 } 58 private int num; 59 public int getNum() { 60 return num; 61 } 62 public void setNum(int num) { 63 this.num = num; 64 } 65 }
原文:http://www.cnblogs.com/songfeilong2325/p/4393278.html