主要内容:学习方法介绍、面向对象思想介绍、类与对象关系、封装概念
1. 学习方法介绍:四问法
① 什么?
② 有什么特点
③ 怎么用demo
④ 什么时候用?test
2. 面向对象与面向过程的区别
面向过程强调的是功能和行为,面向对象强调的是具有某种功能的对象,即只要调用具有功能的对象即可。
面向对象实现了从执行者向指挥者的转变。
举例1:买电脑
面向过程:①先在网上查询好电脑的相关信息②到电脑城询价③在电脑城查看电脑的配置信息④挑选配置的硬件⑤自己砍价讨价⑥把电脑带回家 整个过程都是亲力亲为,即都在执行功能
面向对象:①找一个具有选电脑技术和经验的朋友一起去②让朋友前去去询价③让朋友去选电脑,查看电脑信息④让朋友去挑选要配的硬件⑤让朋友砍价讨价⑥让朋友把电脑扛回家⑦让朋友把电脑组装起来 整个过程都是在下命令
举例2,洗衣服
面向过程:①要自己动手将脏衣服拿去洗②自己动手搓衣服③自己动手漂干净④自己动手拧干
面向对象:调用洗衣机这个对象,将以上过程全部封装进洗衣机,我们只要用洗衣机就行了,不用管洗衣机怎么做的
3. 类与对象的关系
类:类是对事物的描述
对象:该类事物的实例,在java中通过new关键字创建
/**
需求:描述人类
1. 人类属性:
姓名;年龄;性别;
2. 人类行为:
跑;说;
class Person
{
//描述姓名
String name;
//描述年龄
int age;
//描述性别
String sex;
//描述跑的行为
void run(){
System.out.println(“I can run”);
}
//描述说的行为
void speak(){
System.out.println(“I can speak”);
}
}
class PersonDemo
{
public static void main(String [] args){
Person p=new Person();
p.name=”张三”;
p.age=23;
p.sex=”男”;
}
}
*/
内存图
对象的属性对应着类的成员变量,就好比拿人来说,人有名字,年龄,性别等,这些就是人这个个体的属性
对象的行为对应着类的成员方法,而人的吃喝拉撒是人类有的行为,对应着具体的个体对象的行为
4. 封装
面向对象的三大特征:
① 封装②继承③多态
封装:在内部隐藏其实现细节,只对外提供公共的访问接口
封装的好处:
① 高了安全性,因为不允许外界直接访问,因而实现了可控
② 提高了代码的复用性
③ 提高了易用性
④ 对外隔离了内部变化,电视机的例子
封装的体现方式之一是私有private,通过private修饰符修饰类内部的成员,达到控制类成员的有效范围的目的。
封装代码体现:
class Person
{
//私有成员属性
private String name;
private String sex;
private int age;
//通过get 和set方法对外提供公共访问的接口和方法
public void setName(String n)
{
name=n;
}
public String getName()
{
return name;
}
public void setAge(int x)
{
age=x;
}
public int getAge()
{
return age;
}
public void setSex(String sxx)
{
this.sex=sxx;
}
public String getSex()
{
return sex;
}
// void speak()
// {
// System.out.println(name+" "+age+" "+sex);
// }
}
class PersonDemo
{
public static void main(String[] args)
{
//实例化类
Person p=new Person();
p.setName("张三");
p.setAge(28);
p.setSex("男");
String mName=p.getName();
int mAge=p.getAge();
String mSex=p.getSex();
System.out.println("这个人的名字是"+mName+"性别是"+mSex+"年龄是"+mAge);
//p.speak();
}
}
5. 成员变量和局部变量
成员变量是定义在类内部的变量,局部变量定义在方法内部或者定义在语句中
两者的区别:
在代码中的位置不同。成员变量定义在类中,局部变量定义在方法内部或者定义在语句中
内存中存储位置不同。局部变量存储在栈内存中,成员变量存储在堆内存中,且有默认初始化值。
生命周期不同。局部变量随着方法或语句的出现而出现,方法或者语句作用完,局部变量就被自动释放。而成员变量随着对象的出现而出现。
=====================20##-08-04====================
主要内容:构造函数、this关键字,静态修饰符static、三大代码块、创建一个对象的流程
1. 构造函数:用于申请内存,给对象进行初始化的方法。
构造函数特点:
① 名字必须与类名相同
② 除访问权限修饰符外,不能有其他任何修饰符,也不能有返回值
③ 尽管没有返回值,但是也不能用void修饰
④ 构造方法不能用static final修饰,一般也不能用private修饰,否则会导致外部无法创建对象
⑤ 构造方法不能显式调用,一般通过new关键字来调用,或者用this,super调用
⑥ 构造函数 的参数列表可以为空也可以有参数,根据参数的有无可以将构造函数分为无参构造函数和有参构造函数
⑦ 可以定义多个构造方法,但是要求参数列表不同,即以重载的形式存在
⑧ 如果未定义任何构造方法,系统会自动提供一个无参构造函数,而一旦定义了构造函数,默认无参构造函数就没有了
⑨ 构造函数可以调用一般方法,但是一般方法不能调用构造函数
⑩ 构造函数中有return语句,用于结束初始化
构造函数在对象初始化时执行而且只执行一次
构造函数的初始化过程:
1. super();调用父类构造方法
2. 显示初始化
3. 构造代码块执行
2. this关键字:
this代表啥?哪个对象调用该函数或者方法或者属性this就代表哪个对象
this可以用于对成员变量和成员方法进行调用,调用的方式是this.属性名和this.方法名
特殊用法:this可以用于调用本类构造函数,格式是this(参数列表),而且必须放在构造函数的第一行,所以this和super是不能共存的
3. static关键字:是用于修饰成员属性和成员方法的一个关键字
特点:
① 被static关键字修饰的成员可以被对象共享
② 被static关键字修饰的成员可以不依赖于对象存在,可以直接被类名调用即类名.成员
③ 被static关键字修饰的成员是优先于对象存在的,随着类的加载而加载
Static使用注意事项:
① 被static修饰的成员方法不能调用非静态属性,即在静态的环境中不能存在非静态的,但是非静态的却可以调用静态的成员属性和成员方法
② 静态修饰的成员变量中不允许出现this和super关键字,因为this和super代表的是对象,而静态可以不依赖于对象存在
③ 被静态修饰即意味着这部分数据是要被对象共享的,所以在定义成员时必须明确这部分是不是要被共享,如果这部分数据只想被让对象自己具有则没有必要共享
Static什么时候用?两个明确
① 明确成员数据是不是要被共享?如果是让所有对象共享则可以定义,如果不是而是对象特有的数据,则不能定义成静态的
② 明确成员函数是否有访问到类中的非静态数据,如果有访问到则不能够被定义为静态方法,因为静态方法中不允许调用非静态属性和方法。即是否要访问对象中的特有数据。
静态变量和成员变量的区别:
① 归属不同:静态变量所属于类,也称为类变量;成员变量依赖于对象存在,也成为实例变量
② 生命周期不同:静态变量是随着类的加载而加载的,随着类的消失而消失。成员变量则是随着对象的被创建而存在,对象一旦被回收立刻就消失
③ 在内存中的存储位置不同。静态变量存储在内存中的方法区中的静态区,而实例变量则存储在堆内存中
④ 调用方式不同。实例变量要调用就必须创建对象,利用 对象.实例变量调用,而静态变量可以直接被类调用即类.静态变量,当然静态变量也可以被对象调用,调用方式对象.静态变量
4. 三大代码块
① 普通代码块:直接在一个方法中出现的{}就称为普通代码块,例子程序如下:
public class CodeDemo01{
public static void main(String[] args){
//普通代码块
{
int x = 10;
System.out.println("x=" + x);
}
int x = 100;
System.out.println("x=" + x);
}
}
② 构造代码块:
直接在类中定义的没有加static关键字的代码块{}称为构造代码块,用来给类进行初始化的,例子程序如下:
public class CodeDemo02{
public CodeDemo02(){
System.out.println("========这是构造方法=========");
}
//这是构造代码块,而且在new对象时,构造代码块优先构造方法执行
{
System.out.println("=========这是构造块!=========");
}
public static void main(String[] args){
new CodeDemo02();
new CodeDemo02();
}
}
③ 静态代码块:静态使用static关键字声明的代码块称为静态代码块,静态块的主要目的是用来为静态属性初始化,例子程序如下:
public class CodeDemo03
{
static{
System.out.println("这是主类中的静态代码块!");
}
public static void main(String[] args){
new Demo();
new Demo();
new Demo();
}
}
class Demo
{
static{
System.out.println("这是Demo类中的静态代码块!");
}
{
System.out.println("这是Demo类中的构造块!");
}
public Demo(){
System.out.println("这是构造方法!");
}
}
注意事项:静态块优先于主方法的执行,静态块优先于构造方法的执行,而且只执行一次!静态代码块是在类加载时自动执行的,而且只执行一次,非静态代码块是在创建对象时自动执行的代码,不创建对象不执行该类的非静态代码块。且执行顺序为静态代码块------非静态代码块----构造函数。
5. 对象创建流程
① 当执行到相应的对象时将字节码文件加载进内存
② 一new就在内存里开辟空间并分配首地址值
③ 对对象中的属性进行默认初始化
④ 调用构造函数,构造函数压栈
⑤ 执行构造函数中隐式语句super(),访问父类构造方法
⑥ 对对象的属性进行显示初始化
⑦ 调用类中的构造代码块
⑧ 执行构造函数中自己定义的初始化代码块
⑨ 初始化完毕将地址值赋给指定的引用
===============20##-08-06 day 08======================
1. 设计模式:解决问题的思想,是一种解决问题的行之有效的方式
单例设计模式的出现是为了保证创建对象时对象的唯一性
思路:
1. 问题:创建了类之和谁都可以创建对象,数量无法控制
2. 为了限制对象创建的数量,就不让别的程序new对象,转而只让自己new自己的对象
3. 然后对外提供获取该对象的方式
步骤:
1. 由于java创建对象时会调用构造函数,为了达到限制对象创建的目的,将构造函数私有化
2. 然后我在本类中new一个对象
3. 对外提供一个访问本类中new的对象的接口
表现为代码:
class Single// 饿汉模式
{
//创建一个本类对象
/*加private修饰符是为了限制直接用类名调用s,而static 是为了让s能够在主函数中被调用*/
private static Single s=new Single();
//私有化构造方法
private Single(){}
//定义一个方法返回该对象
//建立一个方法的目的是实现可控
//static修饰符是为了让该方法可以直接被类在主方法中调用
public static Single getInstance()
{
return s;
}
}
class SingleDemo
{
Single s1=Single.getInstance();
Single s2=Single.getInstance();
}
/**懒汉模式*/
class Single
{
//在本类中创建一个对象为空
private static Single s=new Single();
//私有化构造方法
private Single(){}
//建立一个对外访问的接口,返回该类对象
public static Single getInstance()
{
if(s==null)
s=new Single();
return s;
}
}
单例设计模式练习:
class SingleSuperManDemo
{
public static void main(String[] args)
{
SuperMan superman=SuperMan.getInstance();
superman.show();
//改变超人的名字
superman.setName("李白");
superman.show();
}
}
//定义一个SuperMan类,由于超人只有一个,为防止出现多个,采用单例设计模式
class SuperMan
{
//定义内部属性并私有化封装
private String name;
//在类内部创建一个私有化的类superman
private/*私有是为了防止直接被类名调用而失去可控性*/ static/*static是为了便于在静态的主函数中被调用,如果不私有调用将出错*/ SuperMan man=new SuperMan("奥巴马");
//对构造函数进行私有化操作,限制外部程序创建对象
private SuperMan(String name)
{
this.name=name;
}
//在类内部定义一个方法返回该类对象
public static/*static是为了便于在静态的主函数中被调用,如果不私有调用将出错,同时也为了可以让类名直接调用*/ SuperMan getInstance()
{
return man;
}
//定义外部程序修改内部成员变量的方法
public void setName(String name)
{
this.name=name;
}
//定义外部获取内部私有成员变量的方法
public String getName()
{
return this.name;
}
//定义一个亮明身份的语句
public void show()
{
System.out.println(this.name+"才是超人");
}
}
单例设计模式练习二:采用懒汉式,皇帝的例子
class SingleEmperorDemo
{
public static void main(String[] args)
{
Emperor emperor=Emperor.getInstance();
emperor.show();
//改变皇帝的名字
emperor.setName("乾隆");
emperor.show();
}
}
//定义一个皇帝类
class Emperor
{
//定义内部变量名
private String name;
//在内部创建一个本类实体,并赋值为空
private static Emperor emp=null;
//私有化构造方法,实现可控
private Emperor(String name)
{
this.name=name;
}
//定义一个返回该类对象的方法
public static Emperor getInstance()
{
if(emp==null)
emp=new Emperor("康熙");
return emp;
}
//定义外部程序修改内部成员变量的方法
public void setName(String name)
{
this.name=name;
}
//定义外部获取内部私有成员变量的方法
public String getName()
{
return this.name;
}
//定义一个亮明身份的语句
public void show()
{
System.out.println(this.name+"才是皇帝");
}
}
2. 继承
2.1继承的好处:
①提高了代码的复用性,减少代码和数据的冗余
②让类与类之间产生了关系,为多态提供了前提。
2.2. java中的类大都采用单一继承,多重继承虽然可以提供更灵活更强大的功能,但是会带来调用时的歧义。
2.3. java实现继承要使用extends关键字,在现实生活中的继承,可以理解为儿子继承了父亲的财产,即财产重用;
class Person { //定义人类
public String mName; //姓名
public int mAge; //年龄
public void dining() { System.out.println("吃饱了..."); } //吃饭的方法
}
class Student extends Person { //学生类继承于人类
public float mGrade; //成绩
public void examination() { System.out.println("考试及格了..."); } //考试的方法
}
class Teacher extends Person { //教师类继承于人类
public float mSalary; //薪水
public void prelection() { System.out.println("上课很累..."); } //上课的方法
}
public class InheritanceDemo { //该类用于容纳main方法
public static void main(String[] args) {
Student std = new Student(); //实例化学生对象
std.mName = "张三"; std.mAge = 18; //为姓名和年龄赋值,访问的是父类中的成员
std.dining(); //调用吃饭的方法,访问的是父类中的成员
std.examination(); //调用考试方法,访问的是子类中的成员
Teacher tea = new Teacher(); //实例化教师对象
tea.mName = "小强"; tea.mAge = 65;
tea.dining();
tea.prelection();
}
}
2.4. 继承体系,学习继承体系时先看顶层,使用时找底层
2.5. 什么时候要定义继承?当类与类之间存在着某种所属关系时定义继承
2.6. 子类父类成员关系,被private修饰的父类成员,子类继承过来了,但是对于子类来说呢,他是看不见这些属性,也就无法调用;
注意:子父类中的变量不存在覆盖,当子类与父类的变量有重名出现时,用super来区分
2.7this与super的区别:this代表的是本类对象的引用,super指的父类的那片空间
2.8方法覆盖:当子类与父类存在一模一样的方法时就存在覆盖现象
方法覆盖的注意事项:
① 类方法覆盖父类方法时,必须保证子类方法的权限大于父类方法
② 静态只能被静态覆盖,换言之,父类是静态子类必须是静态
2.9子父类中的构造方法
① 执行顺序:当实例化子类的对象时,必须先执行父类的构造方法,然后再执行子类的构造方法;如果父类还有更上级的父类,就会先调用最高父类的构造方法,再逐个依次地将所有继承关系的父类构造方法全部执行;如果父类的构造方法执行失败,那么子类的对象也将无法实例化。
② super关键字
super用途一:区分子类与父类重名变量
super用途二:所有子类的构造函数第一行都默认有一个隐式的super()语句调用父类无参构造方法,强调必须是子类构造方法的第一条语句
③ 调用本类构造函数用this(实参列表),调用父类构造函数用super();
④ 由于this()和super()在调用构造函数时都要位于构造函数的第一行,所以两者不可以同时存在
⑤ 当父类中没有空参构造函数时,必须在子类构造函数中显式调用super(实参列表)语句指定访问父类中的构造函数,否则将报错
⑥ 子类调用父类构造函数的原因是,子类在创建对象时必须先看看它的父亲要如何初始化内容
6. final关键字
① final有最终的意思,final可以被用来修饰变量,修饰类、修饰方法
② 被final修饰的类不能被继承
③ 被final修饰的方法也不能被覆盖
④ 被final修饰的变量是一个常量,只能赋值一次
===============20##-08-07 day09==========================
主要内容:抽象类 接口 多天概述
1. 抽象类:在描述事物的时候,没有足够的具体的信息,我们就把这个事物定义为抽象事物。
1.1 抽象类虽然没有足够具体的信息,但是可以将其中的一些共性信息抽取出来,但是由于缺少信息,这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。抽象方法所在类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。
1.2抽象类特点:
① 抽象类和抽象方法必须用abstract修饰,抽象方法只能定义在抽象类中,abstract可以修饰类和方法,但是不能修饰变量
② 抽象类中只声明抽象方法,并不实现方法,抽象方法没有方法体
③ 抽象类不可以被实例化,即不能用new创建对象
④ 只有通过子类继承抽象类,并覆盖了所有抽象方法之后,子类才可以被实例化,如果子类中还有抽象方法,则该子类还是一个抽象类
1.3抽象类五问:
① 抽象类一定是一个父类吗?
答:是,因为抽象类必须要子类覆盖了所有抽象方法之后才可以被实例化和使用
② 抽象类中有构造函数吗?
答:有,抽象类本身虽然不能被实例化,但是抽象类的构造可以用来给子类对象初始化
③ 抽象方法中可以定义非抽象方法吗?
可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。所以抽象类和一般类在定义上,都是需要定义属性和行为的。只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
④ 抽象类中可以不定义抽象方法吗?
答:可以,之所以定义抽象方法只是为了让抽象类不能创建对象
⑤ 抽象关键字abstract和哪些关键字不能共存?
答:final:因为被final修饰的类不能被继承,被final修饰的方法也不能被覆盖,而抽象类是一定要被继承的,抽象方法是一定要被覆盖的
static :被static修饰的方法无需创建对象就可以被调用,而抽象方法被直接调用时无意义的。
private:如果抽象方法被私有,则子类不能实现抽象方法
2. 接口:
2.1,接口是可以看成一种特殊的抽象类,采用关键字interface定义
内部常见成员以及固定的修饰符:
① 接口中的成员是常见的全局变量、抽象方法,且成员都有固定修饰符public
② 接口中成员即使没有写上固定修饰符,在编译的时候也会自动加上
2.4,接口中有抽象方法,所以接口不能被实例化。同抽象方法一样,接口的子类必须实现了接口中的所有抽象方法,子类才可以被实例化,否则该子类仍然是一个抽象类
2.4,类与类之间可以用extends继承,而类与接口之间是通过implements存在实现关系,即接口是被实现的。
接口解决了什么问题?
2.5在java中是不允许多继承的,但是接口的出现改良了这一局面,可以利用接口的多实现功能来避免单继承的局限,而且还能对类进行功能扩展。
1.接口解决了什么问题?多继承的问题。★★★★★
答:在java中是不允许多继承的,会发生调用的不确定性,问题主要在于方法主体上,但是接口的出现改良了这一局面,因为接口中的方法没有方法体,可以利用接口的多实现功能来避免单继承的局限,而且还能对类进行功能扩展。java将多继承机制通过多现实来体现。
2.内部常见成员以及固定的修饰符。
①接口中的成员是常见的全局变量、抽象方法,且成员都有固定修饰符public
② 接口中成员即使没有写上固定修饰符,在编译的时候也会自动加上
接口另一个好处?
一个类继承一个类的同时,还可以实现多个接口,避免了单继承的局限性,提高了功能的扩展性
3.接口的特点?
①接口是用来实现的
②因为接口中有抽象方法,所以接口是不能被实例化的
③必须将接口中的所有的抽象方法都覆盖,子类才可以被实例化,否则子类仍然是一个抽象类
4.接口的思想:代码举例。★★★★★
1.功能扩展
2.暴露规则
3.解耦
接口的出现是:一方在实现接口,一方在使用接口,接口的作用就是把使用接口的人和实现接口的人分开,实现接口的人不必要关心谁去使用,而使用接口的人也不用关心谁实现的接口,由接口将他们联系在一起。
程序解释:
1、以生产和使用一台计算机为例,首先,我们定义了一个显卡的接口,他里面有显示功能和获取显卡名称的功能:
interface VideoCard
{
void display();
String getName();
}
2、显卡的生产者来了,他必须实现接口中定义的所有方法,也可以自己增添若干方法:
class MaxsunVideoCard implements VidioCard
{
//定义铭瑄显卡
String name="This is MaxsunVideoCard";
void setName(String name)
{
this.name=name;
}
public void display()
{
System.out.println("The Maxsun's vidiocard is running!!");
}
public String getName()
{
return this.name;
}
};
显卡制造商生产出了显卡,并且通过setName方法贴上了自己的商标,而通过getName方法可以让使用者知道这块显卡的制造商。
3、现在显卡已经生产出来了,但是我们还需要一块主板,把生产出来的显卡插到主板上才能够使用,那么我们去买主板:
class MainBorad
{
String cpuName;
//定义一个显卡
VideoCard vc;
void setCPU(String cpuname)
{
this.cpuName=cpuName;
}
void setVideoCard(VideoCard vc)
{
this.vc=vc;
}
void run()
{
System.out.println("超级无敌主板");
System.out.println(vc.getName());
vc.display();
System.out.println("mainbord is running successful!");
}
};
这是主板厂商生产的主板,这也就是我们所说的接口的使用者,在他生产主板
的时候并不知道用户使用的是哪块显卡,但是他留出来了显卡的插槽(插槽就是接口)
也就是他不关心谁实现的接口,但是他可以使用接口,预留出显卡的插槽让用户去选购显卡。
程序中这样理解:Mainborad这个类只知道接口VidioCard中有哪些方法,但是并不知道
接口的实现类MaxsunVideoCard是怎么去实现接口的,也就是生产主板的厂商并没有必要考虑显卡是
哪个厂商的,他要做的只是根据接口把显卡插槽做好,接口里没有实现的方法相当于插槽
4、现在我们用户开始组装计算机了:
public class ComputerBuyers
{
public static void main(String [] args)
{
MaxsunVideoCard max=new MaxsunVideoCard();//买了一块Maxsun显卡
MainBorad mb=new MainBorad();//买了一块主板
mb.setCPU("Intel");//买的是Inter主板
mb.setVideoCard(max);//把Maxsun显卡插到主板上(通过主板上setVideo方法)
//System.out.println(hv.getName());
mb.run();//开电脑运行
System.out.println("success");
}
};
以上看出接口的作用就是大力实现了java的开源性,使软件开发过程优化,接口重要的特征是实现了多样性,能够很好地解决C++中遗留的多继承中出现的问题。
3、多态:同一事物的多种形态
好处:提高了代码的扩展性
弊端:不能使用子类的特有方法
前提:必须存在继承和实现
什么时候使用向上转型,向下转型?★★★★★★
答:当面对一些共性类型的时候可以采用向上转型,提高扩展性
当想要去用子类的特有方法时,会有向下转型,但向下转型存在风险
容易发生ClassCastException。只要转换类型和对象类型不匹配就会发生
代码体现:
abstract MrBi
{
abstract void takeClass();
}
class BiLaoYe extends MrBi
{
void takeClass()
{
System.out.println("毕姥爷讲课真风趣");
}
void takeFish()
{
System.out.println("毕姥爷还会钓鱼哦");
}
}
class TeacherBi extends MrBi
{
void takeClass()
{
System.out.println("毕老师讲课同样风趣!");
}
void seeMovie()
{
System.out.println("毕老师还喜欢看电影");
}
}
class BiDemo
{
public static void main(String[] args)
{
//将毕老师提升为毕祖父类型
MrBi bls=new TeacherBi();
bls.takeClass();
//向下转型
BiLaoYe bly=(BiLaoYe)bls;
bly.takeFish();
}
}
===========20##-08-09 day10==============================
主要内容:多天运行时成员的调用方式、多态综合练习、内部类详解
一、多态运行时成员调用方式
① 成员变量
答:当子父类中出现重名成员变量时,在编译时参考的是引用变量所属类中是否有该成员变量,在运行时也是参考引用变量所属类中是否有该成员变量,总结成一句话就是:无论是编译还是运行都是看等号左边就行;
② 成员函数
答:当子父类中有一模一样函数时,在进行多态调用时,编译时看的引用变量所属类中的方法,运行时看的是对象所属类中的方法,一句话总结:编译时看等号左边,运行时看等号右边
③ 静态函数:
答:子父类中出现一模一样函数时,编译和运行都是看引用变量所属类中的方法,一句话总结:无论编译还是运行都是看等号左边
二、多态综合练习—内存图绘制
class Fu
{
int num = 3;
Fu()
{
System.out.println("fu show :"+show());
}
int show()
{
return num;
}
}
class Zi extends Fu
{
int num = 4;
Zi()
{
System.out.println("zi show :"+show());
}
int show()
{
return num;
}
}
class DuoTaiTest3
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.show());
}
}
三、Object方法中 的equals和toString方法
① Object类是Java中所有类的超类,是Java中上帝,属于Java层次中的最顶级,它定
义了所有对象都具备的功能。
② Boolean equals方法用于比较两个对象是否相等,其实内部比较的是两个对象的地址,但是根据对象属性的不同,判断的内容也会不一样,所以在定义类时一般都会覆盖equals方法,建立本类特有的判断对象的依据
举例:class Book
{
String bookName;
String bookContent;
Book(String name,String content)
{
this.bookName=name;
this.bookContent=content;
}
//覆盖equals方法,建立本类判断对象的特有依据
public boolean equals(Object obj)
{
//如果传进来的对象和要比较的属于同一引用则直接返回
if(this==obj)
return true;
//如果想要使用子类特有方法需要对其进行判断
if(!(obj instanceof Book))
return false;
//向下转型
Book bk=(Book)obj;
return this.bookContent.equals(bk);
}
//覆盖toString方法,建立本类特有的将对象以字符串方式输出的方法
public String toString()
{
return "This book's name is"+this.bookName+"and the content is"+this.bookContent;
}
}
class EqualsTest
{
public static void main(String[] args)
{
Book bk1=new Book("谁的青春不迷茫","一本讲述青年迷茫之路的书");
Book bk2=new Book("因为痛所以叫青春","青春就是是痛的");
System.out.println(bk1.equals(bk2));
System.out.println(bk1.toString());
Book bk3=new Book("谁的青春不迷茫","一本讲述青年迷茫之路的书");
Book bk4=new Book("因为痛所以叫青春","一本讲述青年迷茫之路的书");
System.out.println(bk3.equals(bk4));
System.out.println(bk3.toString());
}
}
三、内部类
① 概念:将一个类定义在另一个类内部
② 访问规则:内部类可以直接访问外部类的成员,外部类需通过创建内部类对象的方式访问内部类的成员。
内部类可以直接访问外部类的原因:因为内部类持有了一个外部类的引用 外部类名.this
③ 当内部类定义在成员位置上时可以使用一些成员修饰符private static 修饰,当内部类static修饰该类为静态内部类,其实就相当于一个外部类。会出现访问局限性,只能访问外部类中的静态成员。内部类中不允许定义静态成员变量和静态方法 注意;如果内部类中定义了静态成员,那么该内部类必须是静态的。
三种访问内部类成员的方式:
非静态、非私有的内部类访问:可以通过创建外部类对象来访问
如:Outer.Inner in=new Outer().new Inner();
In.show();
静态非私有内部类访问:
Outer.Inner2 in = new Outer.Inner2();
in.show2();
或者直接:Outer.Inner2.show3();
④ 如果将内部类定义到了局部位置上,就称该内部类为局部内部类,局部内部类只能访问被final修饰的局部变量。
⑤ 匿名内部类:
实质:匿名内部类的实质就是匿名子类对象。
前提:想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
使用条件:内部待实现的方法不宜过多
===============2013-08-10==========================
主要内容:
1. 异常:程序运行出问题了,这个问题产生时,有问题的原因,出现问题的位置,问题的名称等信息存在,按照面向对象的思想,将这个问题封装成对象,这样,当再出现问题时,就可以利用封装好的问题对象,对这些问题进行操作和处理。
2. 异常的原理:将产生的问题封装成对象,当问题产生时将问题对象利用throw关键字向外抛出,如果没有定义处理方式,最终将交由JVM处理,JVM默认的处理方式是将出现问题的位置,名称,原因输出在屏幕上。
3. 自定义异常:当程序中出现java中没有出现过的问题时,这时就需要我们效仿java这种处理问题的机制,将自己程序中出现的问题,按照自己想要的处理方式,将问题封装成对象,这就是自定义异常。
自定义异常过程:
① 描述特定的异常
② 要让定义的异常类具有可抛性,必须继承Throwable或者Exception类(继承异常体系中的成员),让其具有可抛性
③ 定义类的构造函数,直接通过super(),访问父类相应构造方法
④ 自定义中其他内容自己定义
4. 异常体系
Throwable
|--Error错误,一般系统调用时发生的问题,一般不捕获(不编写针对性代码)
|--Exception异常,是可以处理的,throws
|--RuntimeException
异常体系特点:异常名字的命名很有意思都是以Exception即以父类的名字作为后缀的,处于异常体系中的成员都具有可抛性。
5. 异常类型
① 编译时检测异常,包括Exception类及其子类(但是不包括RuntimeException)
如果抛出了编译时检测异常,则要在函数上进行throws声明或者进行捕获操作
② 运行时检测异常(编译时不检测异常)包括RuntimeException及其子类,这如果抛出了编译时检测异常可以不进行throws声明或者不进行捕获
③ 编译时不检测异常应用场景,当有些方法需要传递参数而参数的传递有误时,让程序停止,让调用者去解决代码问题
6. throw和throws的区别,throws是用在函数上的,用于声明异常类的,让调用者看到异常信息代码并提供处理方式;而throw是用在函数内的用于抛出异常对象的,如果在函数内使用throw关键字,那么就必须在函数上进行异常类的声明或者对异常进行捕获
7. 异常捕获处理
try{
//需要被检测的代码
}catch(异常类 变量){
//对异常进行处理的代码
}finally{
//一定会被执行的代码
}
异常处理原则:
① 如果在函数内抛出了异常对象,那么就必须要在函数上利用throws进行声明异常或者进行try catch处理
② 什么时候捕获什么时候声明异常?如果发生的异常在catch里面能够处理就采用捕获,如果不能就采用声明异常的形式,让调用者去处理
③ throws几个异常就必须进行几个catch处理
8. finally什么时候用?
当有资源的利用一定要被关闭或者有些代码最后一定要被执行时利用finally
9. try catch finally的几种组合方式:
① try{
//需要被检测的代码
}finally{
//一定会被执行的代码
}
② try{
//需要被检测的代码
}catch(异常类 变量){
//对异常进行处理
}
③ try{
//需要被检测的代码
}catch(异常类 变量){
//对异常进行处理
}finally{
//一定会被执行的代码
}
10. 异常注意事项
当存在继承时,子类在抛出异常的时候只能抛出父类异常或者父类异常的子类
一句话就是说子类抛出异常只能抛出父类异常的子集
====================20##-08-11 day12==================
主要内容:
1. 线程概述:进程是正在运行的程序,会在内存中分配一个存储空间,而进程中的一条执
行路径就是线程,一个进程中至少有一个线程,如果有多个线程就称之为多线程程序。
2. 多线程的好处:可以让多部分代码同时执行
3. CPU在执行多线程程序时是随机的,在执行一个线程时不会执行另一个。
4. JVM启动也有多线程,一个是执行主函数内容的主线程,另一个垃圾回收的线程,垃圾回收时间不确定是因为CPU在执行时的不确定性。
5. 创建线程有两种方式:
方式一:继承Thread类
步骤:
① 继承Thread类
② 重写run方法,自定义线程要完成的任务
③ 创建子类对象创建线程
④ 调用start方法开启线程
每一步解析:
① 其实直接创建Thread类就创建了一个线程对象,调用start就开启线程了,然后会调用Thread的run方法,但是Thread的run方法没有定义要执行任务的代码,所以为了能够让线程执行我们给的任务,就需要重写run方法,而要重写run就要继承Thread,在子类中重写run方法,定义执行任务的代码
② 重写run方法,自定义要完成的任务的代码
③ 通过创建子类 对象创建线程
④ 调用start方法开启线程调用run方法
创建线程小结:
① 创建线程的目的是为了完成我们给分配的任务
② 创建多线程是为了完成多个任务
③ 线程的诞生都是带着任务出生的,而且有任务代码的位置
④ 主线程自己的任务执行代码都放在主函数中,自定义要执行的任务放在run方法中,线程一旦启动就会去找自己要完成的任务
方式二、实现Runnable接口
步骤:
① 实现Runnable接口
② 重写Runnable接口中的run方法
③ 创建Runnable子类对象
④ 创建线程Thread类对象
⑤ 将Runnable的子类对象作为参数传递给Thread类的构造函数
⑥ 调用Thread对象的start方法开启线程
步骤解析:
① 为什么实现Runnable接口?
因为采用实现的方式可以避免单继承的局限性
② 重写Runnable接口的方法,定义线程的任务代码
③ 创建Runnable子类对象即去创建要完成任务类的对象,以便能传给线程。
④ 之所以创建Thread类的对象,是因为要创建线程对象要么通过实现Thread类要么通过Thread的子类
⑤ 将Runnable子类创建的对象作为参数传递给Thread类的构造函数,之所以传递给Thread类构造函数,是因为虽然Thread类中有run方法,但是run的功能不是我们需要,因为完成不了我们的任务,所以将我们创建的线程任务对象传递给Thread的构造函数,让Thread类去帮我们完成我们自定义的线程任务
实现Runnable接口的好处是①避免了单继承的局限性②将任务和线程解耦了,因为之前通过继承Thread创建对象时,每一个线程在执行时都会去完成代码任务,这就带了数据共享时的问题,而通过实现Runnable接口,将任务与线程分开,解除线程和任务耦合性
6. start和run的区别:
调用start方法会开启一个新的执行路径,而调用run方法时不会开启一个新的执行路径
7. 两种创建方式的不同,继承Thread类方法覆盖的是Thread类中的run方法,而实现Runnable接口覆盖的是Runnable接口中的方法,然后将实现了该方法的类的对象作为参数传递给Thread类的构造方法Thread(Runnable target)//体现多态。
8.