第八次课总结及思考

        好像过了很久,现在才来总结第八次课的知识,真应该早些总结的,因为那时候对所学的知识会印象深刻一下。好了,以下进入正题。这节课主要介绍了以下知识:主要是面向对象三大特性——封装、继承、多态,具体有隐藏与封装、继承(软件复用)、super关键字限定、多态、重写父类方法(override)、引用变量的类型和强制类型转换、反射的概念、初始化块的使用。希望这篇文章对读者有所帮助。若有不对的地方,欢迎读者指出,在此谢过了!微笑微笑

一、隐藏与封装

            1、限制对成员变量的不合理的访问

            2、可进行数据检查,从而有利于保证对象信息的完整性

            3、隐藏类的实现细节

二、继承(软件复用)

         1、子类继承父类,使用extends关键字,如public class Apple extends Friut{}

         2、若定义一个未显式声明父类的类,那么它的父类是Object类是(隐式声明)

         3、重写父类方法(override)(方法注解),下面的内容介绍都围绕着这个例子

package sandatexing;


public class Ostrich extends Bird {

	@Override
	public String fly() {
//		return super.fly();
		return " can only run";
	}
	
	public static String run() {
//		return super.fly();
		return "ostrich";
	}

	public static void main(String[] args) {
		Ostrich ostrich = new Ostrich();
		System.out.println("Ostrich is "+ostrich.fly());

	}
}

package sandatexing;

public class Bird {

	public Bird(String name) {
		
	}
	public String fly() {
		return "flying...";
	}
	public static String run() {
		return "static";
	}	
}
运行结果
Ostrich is  can only run

       4、继承带来一个坏处:破坏封装,所以:

         (1)尽量隐藏父类的内部数据

         (2)不要让子类可以随意访问、修改父类方法

         (3)尽量不要在父类构造器中调用被子类重写的方法(详见4.5)

三、super关键字限定

       1、super.方法名:用于调用父类被覆盖的实例方法。

public class Ostrich extends Bird {

	@Override
	public String fly() {
		// TODO Auto-generated method stub
		return super.fly();
	}

	public static void main(String[] args) {
		Ostrich ostrich = new Ostrich();
		System.out.println(ostrich.fly());
}
运行结果:
flying...

       2、子类不能重写父类静态方法。但是如果你要在子类中用到这个方法,你可以去掉"@Override"

    


       注意:虽然子类不能重写父类静态方法,但是,如果你想用父类的这个镜头方法,可以通过子类对象调用父类的这个静态方法,代码如下(注意这个代码和原始的代码是不同的)如:

package sandatexing;

public class Ostrich extends Bird {
	@Override
	public String fly() {
		return super.fly();
	}
	//这里没有run()
	
	public static void main(String[] args) {
		Ostrich ostrich = new Ostrich();
		System.out.println("now it is "+ostrich.run());
	}
}
package sandatexing;
public class Bird {
	public Bird(String name) {
		
	}
	public String fly() {
		return "flying...";
	}
	public static String run() {
		return "static";
	}
}
运行结果:
now it is static

       3、如果想要调用父类构造器,只能在子类构造器里面调用,如:
package sandatexing;
public class Bird {
	public Bird() {
		System.out.println("我是父类构造器");
	}
	public String fly() {
		return "flying...";
	}
	public static String run() {
		return "static";
	}
}
package sandatexing;
public class Ostrich extends Bird {
public Ostrich() {
	super();
}
	@Override
	public String fly() {
		return super.fly();
	}
	public static void main(String[] args) {
		Ostrich ostrich = new Ostrich();
		System.out.println("now it is "+ostrich.run());
	}
}
运行结果:
我是父类构造器
now it is static

      4、若子类中声明了与父类相同的实例变量,那么父类的实例变量将被隐藏,如:

package sandatexing;
public class BaseClass {
	public String name = "父类的实例变量-name";
	
	public void accessOwner() {
		System.out.println("BaseClass" + name);
	}
}

package sandatexing;
public class SubClass extends BaseClass {
	public int age = 123;

	private String name = "隐藏父类的同名变量-name";
	
//	优先当前类的成员变量,即子类的实例变量会隐藏父类的实例变量
	@Override
	public void accessOwner() {	
		System.out.println("SubClass中,子类的实例变量-name的值:" + name);
	}
	
	public void accessBase() {
		//访问父类的实例变量
		System.out.println("现在在子类中,调用父类的同名变量:" + super.name);
	}	
	public static void main(String[] args) {
		SubClass sc = new SubClass();
		sc.accessOwner();
		sc.accessBase();
		
	}

}
运行结果:
SubClass中,子类的实例变量-name的值:隐藏父类的同名变量-name
现在在子类中,调用父类的同名变量:父类的实例变量-name

       所以,针对此种情况,会出现内存开销的问题:2块内存:

               即创建SubClass对象时,系统会为SubClass对象分配两块内存,一块用于储存子类中定义的的name实例变量,一块储存从BaseClass类中继承的name实例变量

四、多态

      1、java引用变量类型:编译时类型和运行时类型,如

BaseClass pBc = new SubClass();
                BaseClass是编译时类型,SubClass是运行时类型

     2、编译时类型:由声明该变量时使用的类型决定

      3、运行时类型:由实际赋值给该变量的对象决定

      4、所以,多态可以理解为:编译时类型和运行时类型不同。

            余老师(读者可以访问其博客,请点击链接)说得很好:由多态,即编译时类型和运行时类型不同,我们可以联系这些知识点:运行时类型、编译时类型、强制类型转等,这样就可以形成一张知识网络了。

      我们来看下面的例子(与3.4的例子稍微不同):
package sandatexing;

public class BaseClass {
	public String name = "父类的实例变量-name";

	public int age = 89;
	static String num = "89";
	
	public void accessOwner() {
		System.out.println("BaseClass" + name);
	}
	
	public void test() {
		System.out.println("将要被子类重写的方法,父类被覆盖的方法");
	}
	
	public void base() {
		System.out.println("父类的普通方法");
	}
	
	public static void staticMethod(){
		System.out.println("父类的静态方法");
	}
}
<pre name="code" class="java">package sandatexing;

public class SubClass extends BaseClass {
	public int age = 123;

	private String name = "隐藏父类的同名变量-name";

	
//	优先当前类的成员变量,即子类的实例变量会隐藏父类的实例变量
	@Override
	public void accessOwner() {
		// TODO Auto-generated method stub
		System.out.println("SubClass中,子类的实例变量-name的值:" + name);
//		super.accessOwner();
	}
	
	public void accessBase() {
		//访问父类的实例变量
		System.out.println("现在在子类中,调用父类的同名变量:" + super.name);
		
	}
	
	public void base() {
		// TODO Auto-generated method stub
//		super.base();
		System.out.println("子类base方法");
	}
	
	@Override
	public void test() {
		// TODO Auto-generated method stub
//		super.test();
		System.out.println("子类---name字符串的长度:" + name.length());
	}
	
	public static void main(String[] args) {
		
		BaseClass pBc = new SubClass();
		System.out.println("子类方法:");
		pBc.base();
		pBc.test();
		System.out.println();
		
		//可以调用父类未被重写的方法
		System.out.println("调用父类未被重写的方法:");
		pBc.staticMethod();
		System.out.println();
		
		//不能直接调用子类的实例方法
		//pBc.accessBase();
		//需要:
		System.out.println("调用子类的实例方法:");
		((SubClass)pBc).accessBase();
		System.out.println();
		
		//调用父类的实例变量
		System.out.println("调用父类的实例变量:"+((SubClass) pBc).age);//123
		//调用子类的实例变量
		System.out.println("调用子类的实例变量"+pBc.age);//89
		
		//当前运行时类型
		System.out.println("当前运行时类型:" + pBc.getClass().getName());
			
		//下面的方法不能得出当前运行时类型
//		if (pBc instanceof BaseClass) {
//			
//			System.out.println("运行时类型是BaseClass" + "  " + BaseClass.class);
//		}
//		if(pBc instanceof SubClass){
//			System.out.println("运行时类型是SubClass:");
//			
//		}
		
	}

}

 
 
运行结果:
子类方法:
子类base方法
子类---name字符串的长度:14

调用父类未被重写的方法:
父类的静态方法

调用子类的实例方法:
现在在子类中,调用父类的同名变量:父类的实例变量-name

调用父类的实例变量:123
调用子类的实例变量89
当前运行时类型:sandatexing.SubClass


这SubClass类中的main方法中,需要注意:

(1)BaseClass pBc = new SubClass();
pBc.base();
pBc.test();
        这里pBc 调用的是子类的方法(实例方法或静态方法),而且子类中的这个方法需与父类的对应方法同名,而且要同样是实例方法或是静态方法,且返回值类型需要都一样。但是,如果形参数量、类型如果不同则涉及到重载的内容了,可以具体见下面的例子:

package sandatexing;

public class BaseClass {	
	public String base() {
		return "父类的普通方法";
	}
}
package sandatexing;


public class SubClass extends BaseClass {
<span style="white-space:pre">	</span>public String base(int a) {
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>return "子类base方法";
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>public static void main(String[] args) {
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>BaseClass pBc = new SubClass();
<span style="white-space:pre">		</span>System.out.println(pBc.base());
<span style="white-space:pre">		</span>
<span style="white-space:pre">	</span>}


}
运行结果:
父类的普通方法

      ( 2)子类可以调用父类未被重写的方法,如

                System.out.println("调用父类未被重写的方法:");
                pBc.staticMethod();

      ( 3)引用变量的强制类型转换:在这个例子中,不能直接调用子类的实例方法/变量,需要对对象进行相应的强制类型转换才能调用子类的实例方法/变量,如:

                ((SubClass)pBc).accessBase();
                ((SubClass) pBc).age)

       (4)查看当前运行时类型,可以用:对象名.getClass().getName()。如:

                System.out.println("当前运行时类型:" + pBc.getClass().getName());

             这里涉及到一个反射的概念:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

5、需要注意一个问题,先看下面一个例子:
package sandatexing;

public class BaseClass {
	public BaseClass() {

		test();
	}

	public void test() {
		System.out.println("将要被子类重写的方法,父类被覆盖的方法");

	}
	
	
}
package sandatexing;

public class SubClass extends BaseClass {
	
	private String name;
	@Override
	public void test() {

		//Exception in thread "main" java.lang.NullPointerException
		//因为name还没初始化
		System.out.println("子类---name字符串的长度:" + name.length());
	}
	
	public static void main(String[] args) {
		SubClass sc = new SubClass();
	}

}
运行结果:
Exception in thread "main" java.lang.NullPointerException
	at sandatexing.SubClass.test(SubClass.java:18)
	at sandatexing.BaseClass.<init>(BaseClass.java:10)
	at sandatexing.SubClass.<init>(SubClass.java:4)
	at sandatexing.SubClass.main(SubClass.java:23)

这是因为创建sc对象时,会先执行BaseClass类中的构造器(里面的test()实际是子类的test()),而此时对象的name实例变量为null,所以会引发这个异常。即使在子类中给name赋初始值值,运行结果还是一样,这个读者可以试一下。所以,尽量不要在父类构造器中调用被子类重写的方法。




6、引用变量的强制类型转换,看下面的例子:
package sandatexing;

public class Qiangzhileixingzhaunhaun {

	public static void main(String[] args) {

		//多态
		Object object = new Integer(100);
		//编译时没错误,但运行时有错误
		String str = (String)object;
		
		System.out.println(str);
	}

}
运行结果:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at sandatexing.Qiangzhileixingzhaunhaun.main(Qiangzhileixingzhaunhaun.java:11)
所以,我们可以改善一下:
package sandatexing;

public class Qiangzhileixingzhaunhaun {

	public static void main(String[] args) {

		//多态
		Object object = new Integer(100);
		
		if (object instanceof String) {
			String str = (String)object;
			System.out.println(str);
		}
		else if (object instanceof Integer) {
			System.out.println(object);
		}
	}

}
运行结果:
100

五、初始化块

          1、static{}先于构造器执行、且只有一个(最新执行,初始化块修饰符只有static)

           2、多个普通初始化块按顺序执行

        3、创建对象时,系统总是先调用类里的初始化块

           4、初始化块不接收任何参数,如:
package sandatexing;

public class Qiangzhileixingzhaunhaun {


		{
			int a=6;
			System.out.println("a="+a);
		}
		
		{
			String name="xiaoming";
			System.out.println("name="+name);
		}
		//静态初始化块
		static{
			boolean isFinished=true;
			System.out.println("Finish the job:"+isFinished);
		}
		public Qiangzhileixingzhaunhaun() {
			System.out.println("对象初始化");
		}
		
		public static void main(String[] args) {
			Qiangzhileixingzhaunhaun q=new Qiangzhileixingzhaunhaun();
		}
	

	

}
运行结果:
Finish the job:true
a=6
name=xiaoming
对象初始化
       请注意结果中的顺序

六、作业
       要求:
       定义普通人、老师、班主任、学生、学校这些类,提供适当的成员变量、方法用于描述其内部数据和行为特征,并提供主类运行。
       场景1:学生在学校上课
       场景2:老师给学生布置作业
       场景3:班主任要求学生参加学校的文体比赛

       我在下面的代码中每个类的成功变量都有很多,比如学生除了有姓名,还有学号、年龄等,班主任要求学生参加的活动不止一个等等这些场景,读者可以自行设计编写。
package homework;

import java.util.ArrayList;
import java.util.List;

public class Education {
	
	public static void main(String[] args) {

		School school = new School();
		school.setAddress("光明路666号");
		school.setName("前进小学");
		
		Student student = new Student();
		student.setId(1234);
		student.setAge(11);
		student.setName("张三");
		student.setLearningPlace(school.getName());
		//学生在学校上课
		System.out.println(student.learn());
		
		Teacher teacher = new Teacher();
		teacher.setId(2124);
		teacher.setAge(45);
		teacher.setName("王老师");
		teacher.setTeachingPlace("前进小学5年级教室");
		
		Student student2 = new Student();
		student.setId(1235);
		student.setAge(12);
		student2.setName("李四");
		student.setLearningPlace(school.getName());
		
		List<Student> students= new ArrayList<Student>();
		students.add(student);
		students.add(student2);
		
		teacher.setStudents(students);
		//老师给学生布置作业
		System.out.println(teacher.teach());
		
		HeadTeacher headTeacher = new HeadTeacher();
		headTeacher.setPosition("班主任");
		headTeacher.setId(2125);
		headTeacher.setAge(46);
		headTeacher.setName("王老师");
		headTeacher.setTeachingPlace("前进小学5年级教室");
		headTeacher.setStudents(students);
		
		Activity activity = new Activity();
		activity.setId(301);
		activity.setName("篮球比赛");
		activity.setMaxParticipant(40);
		activity.setParticipants(students);
		activity.setStartDate("20160701");
		activity.setEndDate("20160707");
		//教师要求学生参加活动(传人活动举行的学校名称、活动名称)
		System.out.println(headTeacher.doSomething(school.getName(), activity));
		
	}

}

class People{
	private String name;
	private int 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;
	}
}

class Student extends People{
	private int id;
	private String learningPlace;
	
	@Override
	public int getAge() {
		return super.getAge();
	}
	
	@Override
	public void setAge(int age) {
		super.setAge(age);
	}
	
	@Override
	public String getName() {
		return super.getName();
	}
	
	@Override
	public void setName(String name) {
		super.setName(name);
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getLearningPlace() {
		return learningPlace;
	}

	public void setLearningPlace(String learningPlace) {
		this.learningPlace = learningPlace;
	}
	
	public String learn(){
		return "学号为" + this.getId() + "、年龄为" + this.getAge() + "岁的" + this.getName() + 
				"同学在" + this.getLearningPlace() + "上课";
	}
}


class School{
	private String name;
	private String address;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	
}

class Teacher extends People{
	private int id;
	private String teachingPlace;
	private List<Student> students;
	
	@Override
	public String getName() {
		return super.getName();
	}
	@Override
	public void setName(String name) {
		super.setName(name);
	}
	@Override
	public int getAge() {
		return super.getAge();
	}
	@Override
	public void setAge(int age) {
		super.setAge(age);
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTeachingPlace() {
		return teachingPlace;
	}
	public void setTeachingPlace(String teachingPlace) {
		this.teachingPlace = teachingPlace;
	}
	public List<Student> getStudents() {
		return students;
	}
	public void setStudents(List<Student> students) {
		this.students = students;
	}
	public String teach(){
		String stus = "";
		for (Student stu : this.getStudents()) {
			stus += stu.getName() + " ";
		}
		stus += "等同学";
		return "教师id为" + this.getId() + "、年龄为" + this.getAge() + "岁的" + this.getName() + "在"
				+ this.getTeachingPlace() + "给" + stus + "布置作业";
	}
	
}

class HeadTeacher extends Teacher{

	private String position;
	
	
	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	@Override
	public String getName() {
		return super.getName();
	}

	@Override
	public void setName(String name) {
		super.setName(name);
	}

	@Override
	public int getAge() {
		return super.getAge();
	}

	@Override
	public void setAge(int age) {
		super.setAge(age);
	}

	@Override
	public int getId() {
		return super.getId();
	}

	@Override
	public void setId(int id) {
		super.setId(id);
	}

	@Override
	public String getTeachingPlace() {
		return super.getTeachingPlace();
	}

	@Override
	public void setTeachingPlace(String teachingPlace) {
		super.setTeachingPlace(teachingPlace);
	}

	@Override
	public List<Student> getStudents() {
		return super.getStudents();
	}

	@Override
	public void setStudents(List<Student> students) {
		super.setStudents(students);
	}
	
	public String doSomething(String schoolName,Activity activity){
		String stus = "";
		for (Student stu : this.getStudents()) {
			stus += stu.getName() + " ";
		}
		stus += "等同学";
		return "教师id为" + this.getId() + "、年龄为" + this.getAge() + "岁的" +
				this.getPosition() + this.getName() + "要求" + stus + "参加" +
				schoolName + "的" + activity.getName() +"等文体活动" + "\n\t(文体活动id:" + 
				activity.getId() + ",最大参加人数:" + activity.getMaxParticipant() + 
				",参加人有:" + stus + ",活动开始时间为:" + activity.getStartDate() + 
				",活动结束时间为:" + activity.getEndDate() + ")"; 
	}
}

class Activity{
	private String name;
	private int id;
	private int maxParticipant;
	private List<Student> participants;
	private String startDate;
	private String endDate;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getMaxParticipant() {
		return maxParticipant;
	}
	public void setMaxParticipant(int maxParticipant) {
		this.maxParticipant = maxParticipant;
	}
	public List<Student> getParticipants() {
		return participants;
	}
	public void setParticipants(List<Student> participants) {
		this.participants = participants;
	}
	public String getStartDate() {
		return startDate;
	}
	public void setStartDate(String startDate) {
		this.startDate = startDate;
	}
	public String getEndDate() {
		return endDate;
	}
	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}
}
运行结果:
学号为1234、年龄为11岁的张三同学在前进小学上课
教师id为2124、年龄为45岁的王老师在前进小学5年级教室给张三 李四 等同学布置作业
教师id为2125、年龄为46岁的班主任王老师要求张三 李四 等同学参加前进小学的篮球比赛等文体活动
	(文体活动id:301,最大参加人数:40,参加人有:张三 李四 等同学,活动开始时间为:20160701,活动结束时间为:20160707)

        最后,多谢读者耐心读完我这篇啰嗦的博文! 大笑


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值