一、学习目的
继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。在实际操作中,多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法,而这些方法通过一个抽象类或者接口来实现,多态就是提供父类调用子类代码的一个手段。
二、学习内容
(1)代码块
一般情况下,如果有些代码需要在项目启动的时候就执行,这时需要用到代码块。
如何在创建对象之前先做点准备工作?
-
1,构造方法
-
2,静态变量
-
3,静态方法 但必须要主动调用才执行
-
4,代码块 代码块在对象创建之前就优先被调用,即优先于构造方法被调用
结构:
【修饰符】{
预先执行的语句;
}public class MyClass { static{ System.out.println("静态代码块"); } }
注意 :
- 修饰符只有static和缺省;
- 类里面有多个代码块,按从上到下先后执行,若后面的内容和前面的的内容相同,后面的内容覆盖前面的内容;
- 尽量不要在类里面写多个代码块;
- 静态代码块里面不能调用成员变量和实例方法 ,但可以调用静态成员变量;
(2)内部类
内部类: 所谓内部类就是在一个类内部进行其他类结构的嵌套操作。
定义一个类 可以在多个地方定义一个类,创建类的地方:
-
1,单独创建一个文件管理一个类
-
2,直接在文件里面 ,类的上面和下面创建
-
3,直接在某个类的内部创建一个类
为什么需要内部类?
希望一个类A依附于另一个类Bclass RelativeLayout{ String view; //在显示一个视图之前 必须告诉系统这个视图的具体位置 public void show(float leftMergin,float topMergin,float rightMergin,float bottomMergin){ System.out.println("视图"+view+"显示出来了"); System.out.println("left:"+leftMergin+" top:"+topMergin+ " right:"+rightMergin+" bottom:"+bottomMergin); } //定义一个内部类 用于管理相对布局的具体布局属性 public static class LayoutParams{ float leftMergin; float topMergin; float rightMergin; float bottomMergin; public LayoutParams(float leftMergin,float topMergin,float rightMergin,float bottomMergin){ //构造方法 this.leftMergin = leftMergin; this.topMergin = topMergin; this.rightMergin = rightMergin; this.bottomMergin = bottomMergin; } } }
上述代码定义了一个LayoutParams内部类用于管理布局的具体布局属性
访问该静态内部类的方法:
第一种
RelativeLayout.LayoutParams params = //创建内部类的对象
relativeLayout.new LayoutParams(20f,20f,20f,20f);
relativeLayout.show(params);
第二种 只有静态的内部类才能这样用 但此时又不算一个的内部类了,因为它能在外部使用 ,所以尽量不要在类的内部创建静态内部类
//show里面的是一个匿名类
relativeLayout.show(new RelativeLayout.LayoutParams(20f,20f,20f,20f));
relativeLayout.show(20f,20f,20f,20f);
若不是静态内部类的使用方法:直接调用外部类的show方法即可
relativeLayout.show(20f,20f,20f,20f);
内部类构造方法的调用:
class TestInner{
int a;
int b;
Inner inner;
class Inner{
//非静态的内部类,这个内部类类就可以引用外部类的属性和方法
public Inner(){
a = 20;
b = 30;
show();
}
}
public void test(){
inner = new Inner(); //调用内部类的构造方法
}
public void show(){
System.out.println("a = "+a);
}
}
调用,输出结果为a = 20;执行孙旭是先调用外部类的test方法,test方法里面在调用内部类的构造方法 给a赋值20;
TestInner testInner= new TestInner();
testInner.test();
(3)继承
继承 获得父类的属性和方法,并且可以自己添加一些属性和方法 使用关键字extends
class A extends B ,B是A父类
-
Java只能单继承 但可以变相的多继承 例如A继承B,B继承C,则A继承B,C,利用接口也可以实现变向多继承
-
所有的类都是直接或间接继承Object类
-
如果调用子类的方法,如果没有就回到父类里面查找, 如果子类里面需要调用父类的方法或者显示调用父类的属性,用super
什么情况下 需要在一个方法里面调用super的方法?
如果一个方法需要完成一个功能 又不能单独完成 必须要父类做相应的工作
1,父类做完之后,子类在操作
2,子类做点事情后,在调用父类去完成
父类:class Person{ String name; int age; public Person(String name,int age){ this.name = name; this.age = age; } public void walk(){ System.out.println(name+"在散步"); } public void eat(){ System.out.println(name+"在吃饭"); } }
子类:
class Student extends Person{
int id;
String school;
public Student(String name,int age,int id,String school){
super(name,age); //父类存在有参构造方法,所以要先调用父类的有参构造方法
this.id = id;
this.school = school;
}
// 重写toString
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
", id=" + id +
", school='" + school + ''' +
'}';
}
//方法的重写
@Override
public void walk() {
super.walk();
System.out.println("学生优雅的走");
}
@Override
public void eat() {
super.eat();
System.out.println("学生小口吃饭");
}
}
注意: 如果子类需要重新实现父类的方法 就需要重写,重写的方法前面加Override,例如子类中的walk(),eat()方法重写饭方法是也用super调用了一下父类原有的方法,但在构造方法重写时:若父类的是无参构造方法,子类可以直接重写构造方法;若父类里面存在有参的构造方法,则需要用super()先调用父类的构造方法,然后在为其他变量赋值,例如上面的子类的构造方法里面调用父类的构造方法super(name,age);
测试一下:
class TestExtends{
public static void main(String[] args){
Student xwj = new Student("xwj",20,10010,"SWU"); //创建一个子类对象
xwj.walk(); //调用子类重写的函数
xwj.eat();
System.out.println(xwj);
}
}
结果:
(4)多态
多态(polymorphic)
- 1,以同一个方法在不同的子类中有不同的实现
- 2,如果有继承关系 子类的对象可以使用父类的对象接收
类型的向上转换 父类型可接收子类型
多态的应用的具体展现在下面的小实例里面
三、实例应用
定义一个person类,在定义一个公务员类,一个公司员工类,存在同一个数组里,然后在输出每个人的基本信息
Person类:
package swu.xwj.day5.MessageManager;
public class Person {
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void walk(){
System.out.println("人在走路");
}
public void eat(){
System.out.println("人在吃饭");
}
}
CivilServant类:
package swu.xwj.day5.MessageManager;
public class CivilServant extends Person{
int salary;
int workTime;
public CivilServant(String name,int age,int salary,int workTime){
super(name,age);
this.salary = salary;
this.workTime = workTime;
}
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+"工作:公务员"+" 每天工作小时:"+workTime
+" 薪水:"+salary);
}
@Override
public void walk() {
System.out.println("公务员走路");
}
@Override
public void eat() {
System.out.println("公务员吃饭");
}
@Override
public String toString() {
return "CivilServant{" +
"salary=" + salary +
", newspaper=" + workTime +
", name='" + name + ''' +
", age=" + age +
'}';
}
}
Cilk类:
package swu.xwj.day5.MessageManager;
public class Clerk extends Person {
int salary;
String thch;
public Clerk(String name,int age,int salary,String thch){
super(name,age);
this.salary = salary;
this.thch = thch;
}
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+" 工作:公司员宫"+" 技术:"+thch+" 薪水"+salary);
}
@Override
public void walk() {
System.out.println("公司员工走路");
}
@Override
public void eat() {
System.out.println("公司员工吃饭");
}
@Override
public String toString() {
return "Clerk{" +
"salary=" + salary +
", thch='" + thch + ''' +
", name='" + name + ''' +
", age=" + age +
'}';
}
}
main方法类:
package swu.xwj.day5.MessageManager;
import java.util.ArrayList;
public class MyClass {
public static void main(String[] args){
ArrayList persons = new ArrayList(); //定义一个数组保存所有人
CivilServant cs1 = new CivilServant("xw",20,5000,4);
CivilServant cs2 = new CivilServant("xl",23,5500,5);//创建五个CivilServant类的对象
CivilServant cs3 = new CivilServant("zs",27,6000,7);
CivilServant cs4 = new CivilServant("xwj",30,5000,4);
CivilServant cs5 = new CivilServant("xwz",40,8000,10);
persons.add(cs1); //向数组里添加对象
persons.add(cs2);
persons.add(cs3);
persons.add(cs4);
persons.add(cs5);
Clerk cl1 = new Clerk("dsa",24,10000,"IOS"); //创建五个Cilk类的对象
Clerk cl2 = new Clerk("zsa",25,13000,"Android");
Clerk cl3 = new Clerk("fsa",26,14000,"Android");
Clerk cl4 = new Clerk("dea",21,9000,"IOS");
Clerk cl5 = new Clerk("na",27,7000,"Android");
persons.add(cl1); //向数组里添加对象
persons.add(cl2);
persons.add(cl3);
persons.add(cl4);
persons.add(cl5);
for(Person person:persons){
//找到person到底是哪个类型的对象
if(person instanceof CivilServant){
CivilServant cs = (CivilServant)person; //强制转换
cs.show();
cs.walk();
cs.eat();
cs.toString();
}else{
Clerk cl = (Clerk)person;
cl.show();
cl.walk();
cl.eat();
}
}
}
}
分析:由于要把公务员和公司员工放到一个数组里面,但数组只能存放容易中数据类型的元素,但Cilk和CivilServant是两个不同的类,但由于二者都继承于Person类,所以只要把数组类型设置为Person类,这样就可以把二者都存进去,这就体现了Java的多态性,也可以把数组类型设置为Object类型,因为所有的类都继承这个类。到后面输出信息时,要判断数组元素到底是哪个类型的,然后在强制转换成CivilServant类或Cilk类这样才能调用相应的show方法,用instanceof关键字判断。
四、学习感悟
今天的学习内容虽然比较多,但是相对而言比较简单,理解起来也不算麻烦,但在真正实际使用的时候会有点小迷茫,但仔细想一下也能清楚,这种情况就是练习的太少,所以不管那点内容,即使是简单知识,也需要不断地练习,不能眼高手低。