黑马程序员——java基础--面向对象基础
2015-05-17 08:07
513 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
二、面向对象基础
类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。例如一个鸟类,鸟类封装了所有鸟的共同属性和应具有的行为用java语言对现实生活中的事物进行描述是通过类的形式来体现的。怎么描述呢?对于事物描述通常只关注两方面:一个是属性,一个是行为。只要明确该事物的属性和行为并定义在类中即可。那么类与对象之间是什么关系呢?类:事物的描述,对象:该类事物的实例,在java中通过new来创建的。
成员变量定义在类中,整个类中都可以访问。
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
2,
成员变量存在于堆内存的对象中。
局部变量存在于栈内存的方法中。
3,
成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
4,
成员变量都有默认初始化值。
局部变量没有默认初始化值。
好处:1,将变化隔离;2,便于使用;3,提高重用性;4,提高安全性。
封装原则:
1,将不需要对外提供的内容都隐藏起来。
2,把属性都隐藏,提供公共方法对其访问。
将age私有化以后,类以外即使建立了对象也不能直接访问,但是人应该有年龄,就需要在Person类中提供对应访问age的方式
1,函数名与类名相同
2,不用定义返回值类型
3,不可以写return语句
作用:
给对象进行初始化。
注意:
1,默认构造函数的特点。
2,多个构造函数是以重载的形式存在的。
一个对象的建立,构造方法只运行一次,而普通方法可以多次运行。
那么,什么时候需要定义构造函数呢?
我的理解是:当创建对象需要初始化对象类中的变量,给其赋值的时候可以使用构造函数,或者对象一初始化就具备某些行为的时候,可以用构造函数
this为什么可以解决这个问题?this到底代表的是什么?
根据我所理解,this指代的是当前所指示的这个对象,我们把name传进去其实是把name赋值给我们所建立的这个对象,所以用this关键字标示一下指代当前对象的成员变量
this:代表本类对象,代表他所在函数所属对象的引用,简单说,哪个对象在调用this所在的函数,this就指代哪个对象
this应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用了本类对象,就要用到this。
this语句:用于构造函数之间互相调用
this语句只能定义在构造函数的第一行,因为要先执行
当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用
2,static修饰的成员被所有的对象所共享。
3,static优先于对象存在,因为static的成员随着类的加载就已经存在了。
4,static修饰的成员多了一种调用方式,就可以直接被类名所调用 。 类名.静态成员 。
5,static修饰的数据是共享数据,对象中的存储的是特有数据。
1,两个变量的生命周期不同。
2,静态方法中不可以使用this或者super关键字。
3,主函数是静态的。
主函数是一个特殊函数,作为程序的入口,可以被jvm调用
主函数特殊之处:
1,格式是固定的。
2,被jvm所识别和调用。
public:代表该函数的访问权限必须是最大的。
static:代表主函数随着类的加载就已经存在了,不需要对象的,直接用主函数所属类名调用即可。
void:主函数没有具体的返回值。
main:函数名,不是关键字,只是一个jvm识别的固定的名字。
String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
要从两方面下手,因为静态修饰的内容有成员变量和函数。
那么什么时候定义静态的变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中
什么时候定义静态函数呢?
函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。当功能内部没有访问到非静态数据(对象的特有数据)该功能可以定义成静态的。简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的没有访问特有数据的方法,该对象的创建是没有意义。
静态的应用-->创建静态工具类:
使用静态工具类:
生成帮助文档时在命令行输入:javadoc -d myhelp -author -version ArrayTool.java 其中-d标示出帮助文档所存目录,-author列出作者,-version列出版本号
这句话都做了那些事?
1,因为new用到了Person.class文件,所以先找到Person.class文件加载进内存
2,执行该类中的static代码块,如果有的话,给Person类进行初始化,
3,在堆内存中开辟空间,分配内存地址。
4,在堆内存中建立对象的特有属性并进行默认初始化,
5,对属性进行显示初始化
6,对对象进行构造代码块初始化,
7,对对象进行对应的构造函数初始化
8,将内存地址赋值给内存中的p变量
继承就是一个类具有另一个类的所有特征并且会有自己的特有特征
继承的好处:
1,提高了代码的复用性。
2,让类与类之间产生了关系,给第三个特征多态提供了前提.
java中支持单继承。不直接支持多继承,但对C++中的多继承机制进行改良。
单继承:一个子类只能有一个直接父类。
多继承:一个子类可以有多个直接父类(java中不允许,进行改良)
不直接支持,因为多个父类中有相同成员,会产生调用不确定性。
在java中是通过"多实现"的方式来体现。
java支持多层(多重)继承。
C继承B,B继承A。
就会出现继承体系。
当要使用一个继承体系时,
1,查看该体系中的顶层类,了解该体系的基本功能。
2,创建体系中的最子类对象,完成功能的使用。
什么时候定义继承呢?
当类与类之间存在着所属关系的时候,就定义继承。xxx是yyy中的一种。 xxx extends yyy
所属关系: is a 关系。
继承中的成员变量:
基本格式:
例子:
变量:
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this,子类要访问父类的同名变量,用super
super的使用和this几乎一致
this代表的是本类对象的引用,super代表的是父类对象的引用
函数:
当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作。这时函数在子父类中的特性。
函数两个特性:
1,重载。同一个类中。overload
2,覆盖。子类中。覆盖也称为重写,覆写。override
覆盖注意事项:
1,子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
2,静态只能覆盖静态,或被静态覆盖。
构造函数:
抽象:笼统,模糊,不具体。
特点:
1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
抽象方法必须定义在抽象类中。该类必须也被abstract修饰。
2,抽象类不可以被实例化。为什么?因为调用抽象方法没意义。
3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。
否则,这个子类还是抽象类。
1,抽象类中有构造函数吗?
有,用于给子类对象进行初始化。
2,抽象类可以不定义抽象方法吗?
可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
通常这个类中的方法有方法体,但是却没有内容。
3,抽象关键字不可以和那些关键字共存?
private 不行
static 不行
final 不行
4,抽象类和一般类的异同点。
相同点:
抽象类和一般类都是用来描述事物的,都在内部定了成员。
不同:
1,一般类有足够的信息描述事物。
抽象类描述事物的信息有可能不足。
2,一般类中不能定义抽象方法,只能定非抽象方法。
抽象类中可定义抽象方法,同时也可以定义非抽象方法。
3,一般类可以被实例化。
抽象类不可以被实例化。
5,抽象类一定是个父类吗?
是的。因为需要子类覆盖其方法后才可以对子类实例化。
abstract class Demo
{
void show1()
{}
void show2()
{}
}
父类对象的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象
2,多态的前提
必须是类与类之间有关系,要么继承,要么实现
通常还有一个前提:存在覆盖
3,多态的好处
多态的出现大大提高程序的扩展性
4,多态的弊端
虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员
5,多态的应用
6,多态的出现代码中的特点(多态使用注意事项)
在多态中成员函数的特点:(动态绑定和静态绑定)
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败
在运行时期:参阅对象所述的类中是否有调用的方法
简单总结就是,成员函数在多态中,编译看左边,运行看右边
模板方法设计模式
多态降低耦合性示例:
1,未利用多态的程序
使用多态:(接口)
1,内部类可以直接访问外部类的成员,包括私有。
之所以可以直接访问外部类的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2,外部类要访问内部类,必须建立内部类对象。
访问格式:
1,当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;,2,当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装,static:内部类就具备static特性,当内部类被静态修饰后,只能直接访问外部类静态成员
异常由来:问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。
其实就是java对不正常的情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种是非严重的问题
对于严重的,java通过Error类进行描述。
对于不严重的,java通过Exception类进行描述。
异常的体系:
Throwanle
Error:通常出现大量问题如,运行的类不存在或者内存溢出等,不编写针对代码对其处理
Exception:在运行时运行出现的一些情况,可以通过try catch finally来处理
处理方法:
1,
try{
//此处放异常的代码
}
catch(Exception e){
//此处是如果try里面的语句发生异常不能执行,就执行catch里的语句
}
finally{
//此处放必须会执行的代码
}
2,
在功能上通过throws关键字声明了该功能可能出现问题。
throws Exception
多异常处理 :
1,声明宜昌市,建议声明更为具体的异常,这样处理的可以更具体。
2,对方声明几个异常,就对应有几个catch块,不要定义多余的
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
建议在进行catch处理时,catch中一定要定义具体的处理方式。
不要简单定义一句e.printStackTrace(),也不要简单的就书写一条输出语句
[b]throws和throw区别
throws:使用在函数上
throw使用在函数内
throws后面跟的是异常类,可以跟多个,用逗号隔开。
throw后跟的是异常对象。
二、面向对象基础
1. 概念
现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机、高楼大厦等。人类解决问题的方式总是将复杂的事物简单化,于是就会思考这些对象都是由哪些部分组成的。通常都会将对象划分为两个部分,即动态部分与静态部分。静态部分,顾名思义就是不能动的部分,这个部分被称为“属性”,任何对象都会具备其自身属性,如一个人,它包括高矮、胖瘦、性别、年龄等属性。然而具有这些属性的人会执行哪些动作也是一个值得探讨的部分,这个人可以哭泣、微笑、说话、行走,这些是这个人具备的行为(动态部分),人类通过探讨对象的属性和观察对象的行为了解对象。类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。例如一个鸟类,鸟类封装了所有鸟的共同属性和应具有的行为用java语言对现实生活中的事物进行描述是通过类的形式来体现的。怎么描述呢?对于事物描述通常只关注两方面:一个是属性,一个是行为。只要明确该事物的属性和行为并定义在类中即可。那么类与对象之间是什么关系呢?类:事物的描述,对象:该类事物的实例,在java中通过new来创建的。
类与对象的概念:
对象在内存中的存在:
成员变量和局部变量的区别:
1,成员变量定义在类中,整个类中都可以访问。
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
2,
成员变量存在于堆内存的对象中。
局部变量存在于栈内存的方法中。
3,
成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
4,
成员变量都有默认初始化值。
局部变量没有默认初始化值。
2. 封装(Encapsulation)
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式好处:1,将变化隔离;2,便于使用;3,提高重用性;4,提高安全性。
封装原则:
1,将不需要对外提供的内容都隐藏起来。
2,把属性都隐藏,提供公共方法对其访问。
将age私有化以后,类以外即使建立了对象也不能直接访问,但是人应该有年龄,就需要在Person类中提供对应访问age的方式
class Person { private int age; public void setAge(int a) { age = a; } void speak() { System.out.println("age="+age); } } class PersonDemo { public static void main(String[] args) { Person p = new Person(); p.setAge(20); p.speak(); } }
3. 构造函数与构造代码块
特点:1,函数名与类名相同
2,不用定义返回值类型
3,不可以写return语句
作用:
给对象进行初始化。
注意:
1,默认构造函数的特点。
2,多个构造函数是以重载的形式存在的。
<span style="font-family:Microsoft YaHei;font-size:14px;">/* 对象一建立就会调用与之对应的构造函数。 构造函数的作用:可以用于给对象进行初始化。 构造函数的小细节: 当一个类中没有定义的函数时,那么系统就会默认给该类加入一个空参数的构造函数。 当在类中自定义了构造函数后 */ </span>
一个对象的建立,构造方法只运行一次,而普通方法可以多次运行。
那么,什么时候需要定义构造函数呢?
我的理解是:当创建对象需要初始化对象类中的变量,给其赋值的时候可以使用构造函数,或者对象一初始化就具备某些行为的时候,可以用构造函数
class { public static void main(String[] args) { new Person(); Person p = new Person(); Person p1 = new Person("zhangsan"); } } class Person { private String name; /*构造代码块 对象一初始化就运行,而且优先于构造函数执行。 和构造函数的区别: 构造代码块是给所有对象统一初始化, 而构造函数是给对应的对象初始化。 */ { System.out.println("person code run"); } Person() { System.out.println("A:name="+name+",,age="+age); } Person(String n) { name = n; System.out.println("B:name="+name+",,age="+age); } }
4. this关键字
看上去是用于区分成员变量和局部变量的this为什么可以解决这个问题?this到底代表的是什么?
根据我所理解,this指代的是当前所指示的这个对象,我们把name传进去其实是把name赋值给我们所建立的这个对象,所以用this关键字标示一下指代当前对象的成员变量
this:代表本类对象,代表他所在函数所属对象的引用,简单说,哪个对象在调用this所在的函数,this就指代哪个对象
this应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用了本类对象,就要用到this。
class Demo { public static void main(String[] args) { new Person(); Person p = new Person(); Person p1 = new Person("zhangsan"); } } class Person { private String name; private int age; /*构造代码块 对象一初始化就运行,而且优先于构造函数执行。 和构造函数的区别: 构造代码块是给所有对象统一初始化, 而构造函数是给对应的对象初始化。 */ { System.out.println("person code run"); } Person() { System.out.println("A:name="+name+",,age="+age); } Person(String name) { this.name = name; System.out.println("B:name="+name+",,age="+age); } Person(String name,int age) { this.name = name; //用this关键字用来指示成员变量 //如果局部有,就在局部找,如果没有就到局部变量里找 this.age = age; } public void speak() { System.out.println("name="+name+"...age="+age); } }
class Person { private int age; Person(int age) { this.age = age; } /* 需求:给人定义一个用于比较年龄是否相同的功能,也就是否是同龄人 */ public boolean compare(Person p) { return this.age==age; } } class Demo { public static void main(String[] args) { Person p1 = new Person(20); Person p2 = new Person(25); boolean b = p1.compare(p2); System.out.println(b); } }
this语句:用于构造函数之间互相调用
this语句只能定义在构造函数的第一行,因为要先执行
class Person { private String name; private int age; Person(String name) { this.name = name; } Person(String name,int age) { this(name); //调用Person(String name)构造方法 this.age = age; } } class Demo { public static void main(String[] args) { Person p= new Person("lisi",30); } }
5. static关键字和main函数
静态:static
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用
static的特点:
1,static是一个修饰符,用于修饰成员。2,static修饰的成员被所有的对象所共享。
3,static优先于对象存在,因为static的成员随着类的加载就已经存在了。
4,static修饰的成员多了一种调用方式,就可以直接被类名所调用 。 类名.静态成员 。
5,static修饰的数据是共享数据,对象中的存储的是特有数据。
成员变量和静态变量的区别?
1,两个变量的生命周期不同。
成员变量随着对象的创建而存在,随着对象的被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2,调用方式不同。
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3,别名不同。
成员变量也称为实例变量。
静态变量称为类变量。
4,数据存储位置不同。
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据.
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据.
静态使用的注意事项:
1,静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)2,静态方法中不可以使用this或者super关键字。
3,主函数是静态的。
<span style="font-family:Arial;font-size:12px;">class Person { private String name; private int age; static String country = "CN"; public Person(String name,int age) { this.name = name; this.age = age; } public void show() { System.out.println(Person.country+":"+this.name+":"+this.age); } //静态方法中存在调用静态变量的行为,可以直接类名调用 public static void method() { System.out.println(Person.country); } } class StaticDemo2 { public static void main(String[] args) throws Exception { //线程暂停5秒 Thread.sleep(5000); //类名调用静态方法无需对象 Person.method(); //创建对象后可以调用非静态方法 Person p = new Person("java",20); p.show(); } }</span>
main函数
public static void main(String[] args)主函数是一个特殊函数,作为程序的入口,可以被jvm调用
主函数特殊之处:
1,格式是固定的。
2,被jvm所识别和调用。
public:代表该函数的访问权限必须是最大的。
static:代表主函数随着类的加载就已经存在了,不需要对象的,直接用主函数所属类名调用即可。
void:主函数没有具体的返回值。
main:函数名,不是关键字,只是一个jvm识别的固定的名字。
String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
class MainDemo { public static void main(String[] args) //new String[0] { /**/ // System.out.println(args);//[Ljava.lang.String;@c17164 System.out.println(args.length); for(int x=0; x<args.length; x++) System.out.println(args[x]); } }
6. 静态应用
什么时候使用静态:要从两方面下手,因为静态修饰的内容有成员变量和函数。
那么什么时候定义静态的变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰,对象中的特有数据要定义成非静态存在于堆内存中
什么时候定义静态函数呢?
函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。当功能内部没有访问到非静态数据(对象的特有数据)该功能可以定义成静态的。简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的没有访问特有数据的方法,该对象的创建是没有意义。
class Demo { int age ; static int num = 9; Demo(int age) { this.age = age; } public static void speak() { System.out.println(num); } public void show() { System.out.println(age); } } class StaticDemo3 { public static void main(String[] args) { // Demo d = new Demo(30); // d.speak(); Demo.speak(); // System.out.println("Hello World!"); } }
静态的应用-->创建静态工具类:
/* 每个用用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用 */ class ArrayTool {private ArrayTool(){} //构造函数私有化防止建立对象 //获取最大值功能 public static int getMax(int[] arr) { int max = arr[0]; for(int x=1;x<arr.length;x++) { if(arr[x]>max) max = arr[x]; } return max; } //获取最小值功能 public static int getMin(int[] arr) { int min = arr[0]; for(int x=1;x<arr.length;x++) { if(arr[x]<min) min = arr[x]; } return min; } //选择排序 public static void selectSort(int[] arr) { for(int x=0;x<arr.length-1;x++) { for(int y=x+1;y<arr.length;y++) { if(arr[y]<arr[x]) { int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } } } } //冒泡排序 public static void bubbleSort(int[] arr) { for (int x=0;x<arr.length ;x++ ) { for (int y=0;y<arr.length-x-1 ;y++ ) { if (arr[y]>arr[y+1]) { int temp = arr[y]; arr[y] = arr[y+1]; arr[y+1] = temp; } } } } //位置置换 public static void swap(int[] arr,int a,int b) { int temp = arr[a]; arr[a] = arr; arr[b] = temp; } //打印数组 public static void printArr(int[] arr) { System.out.print("["); for (int x=0;x<arr.length ;x++ ) { if (x!=arr.length) { System.out.print(arr[x]+","); } else System.out.print(arr[x]); } System.out.print("]"); } }
使用静态工具类:
class TestTool { public static void main(String[] args) { int[] arr = {1,5,7,8,6,2,3}; ArrayTool.printArr(arr); //直接类名调用 } }
7. 帮助文档的制作
在工具类中用/***/来标示帮助内容,@param 接收参数 @return 返回参数 等等生成帮助文档时在命令行输入:javadoc -d myhelp -author -version ArrayTool.java 其中-d标示出帮助文档所存目录,-author列出作者,-version列出版本号
/* 每个用用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用 */ public class ArrayTool { /** 构造函数私有化 */ private ArrayTool(){} //获取最大值功能 /** 获取一个整形数组中的最大值 @param arr 接受一个int型的数组 @return 会返回该数组中的最大值 */ public static int getMax(int[] arr) { int max = arr[0]; for(int x=1;x<arr.length;x++) { if(arr[x]>max) max = arr[x]; } return max; } /** 获取一个整形数组中的最小值 @param arr 接受一个int型的数组 @return 会返回该数组中的最小值 */ //获取最小值功能 public static int getMin(int[] arr) { int min = arr[0]; for(int x=1;x<arr.length;x++) { if(arr[x]<min) min = arr[x]; } return min; } /** 对int数组进行选择排序 @param arr 接受一个int型的数组 */ //选择排序 public static void selectSort(int[] arr) { for(int x=0;x<arr.length-1;x++) { for(int y=x+1;y<arr.length;y++) { if(arr[y]<arr[x]) { int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } } } } /** 对int数组进行冒泡排序 @param arr 接受一个int型的数组 */ //冒泡排序 public static void bubbleSort(int[] arr) { for (int x=0;x<arr.length ;x++ ) { for (int y=0;y<arr.length-x-1 ;y++ ) { if (arr[y]>arr[y+1]) { int temp = arr[y]; arr[y] = arr[y+1]; arr[y+1] = temp; } } } } /** 对int数组的元素进行位置置换 @param arr 接受一个int型的数组 @param a 要置换的位置 @param b 要置换的位置 */ //位置置换 public static void swap(int[] arr,int a,int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /** 对int数组进行打印 @param arr 接受一个int型的数组 */ //打印数组 public static void printArr(int[] arr) { System.out.print("["); for (int x=0;x<arr.length ;x++ ) { if (x!=arr.length) { System.out.print(arr[x]+","); } else System.out.print(arr[x]); } System.out.print("]"); } }
8. 对象初始化与调用成员的过程
Person p = new Person("zhangsan",20);这句话都做了那些事?
1,因为new用到了Person.class文件,所以先找到Person.class文件加载进内存
2,执行该类中的static代码块,如果有的话,给Person类进行初始化,
3,在堆内存中开辟空间,分配内存地址。
4,在堆内存中建立对象的特有属性并进行默认初始化,
5,对属性进行显示初始化
6,对对象进行构造代码块初始化,
7,对对象进行对应的构造函数初始化
8,将内存地址赋值给内存中的p变量
9. 单例设计模式
我们需要一个类只能创建一个对象,也就是同一时刻在内存中只存在一个对象/* 设计模式:对问题行之有效的解决方式。其实它是一种思想。 1,单例设计模式。 解决的问题:可以保证一个类在内存中的对象唯一性。 必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。 如何保证对象唯一性呢? 1,不允许其他程序用new创建该类对象。 2,在该类创建一个本类实例。 3,对外提供一个方法让其他程序可以获取该对象。 步骤: 1,私有化该类构造函数。 2,通过new在本类中创建一个本类对象。 3,定义一个公有的方法,将创建的对象返回。 */ //饿汉式,类一加载,对象就已经存在了。 class Single { private static Single s = new Single(); private Single(){} public static Single getInstance() { return s; } } //懒汉式,类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象 //也称为延迟加载形式。 class Single2 { private static Single2 s = null; private Single2(){} public static Single2 getInstance() { if(s==null) s = new Single2(); return s; } } class Test { private int num; private static Test t = new Test(); private Test(){} public static Test getInstance() { return t; } public void setNum(int num) { this.num = num; } public int getNum() { return num; } } class SingleDemo { public static void main(String[] args) { Single s1 = Single.getInstance(); Single s2 = Single.getInstance(); System.out.println(s1==s2); Test t1 = Test.getInstance(); Test t2 = Test.getInstance(); t1.setNum(10); t2.setNum(20); System.out.println(t1.getNum()); System.out.println(t2.getNum()); } }
10. 继承
1.继承继承就是一个类具有另一个类的所有特征并且会有自己的特有特征
继承的好处:
1,提高了代码的复用性。
2,让类与类之间产生了关系,给第三个特征多态提供了前提.
java中支持单继承。不直接支持多继承,但对C++中的多继承机制进行改良。
单继承:一个子类只能有一个直接父类。
多继承:一个子类可以有多个直接父类(java中不允许,进行改良)
不直接支持,因为多个父类中有相同成员,会产生调用不确定性。
在java中是通过"多实现"的方式来体现。
java支持多层(多重)继承。
C继承B,B继承A。
就会出现继承体系。
当要使用一个继承体系时,
1,查看该体系中的顶层类,了解该体系的基本功能。
2,创建体系中的最子类对象,完成功能的使用。
什么时候定义继承呢?
当类与类之间存在着所属关系的时候,就定义继承。xxx是yyy中的一种。 xxx extends yyy
所属关系: is a 关系。
继承中的成员变量:
基本格式:
class Demo { void show1(){} } class DemoA extends Demo { void show1(){} void show2(){} } class DemoB extends Demo { void show1(){} void show3(){} }
例子:
class Person { String name; int age; } class Student extends Person//Student继承Person { String name; int age; void study() { System.out.println(name+"..student study.."+age); } } class Worker extends Person { // String name; // int age; void work() { System.out.println("worker work"); } } class ExtendsDemo { public static void main(String[] args) { Student s = new Student(); s.name= "zhangsan"; s.age = 22; s.study(); Worker w = new Worker(); w.work(); } }
变量:
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this,子类要访问父类的同名变量,用super
super的使用和this几乎一致
this代表的是本类对象的引用,super代表的是父类对象的引用
函数:
当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作。这时函数在子父类中的特性。
函数两个特性:
1,重载。同一个类中。overload
2,覆盖。子类中。覆盖也称为重写,覆写。override
覆盖注意事项:
1,子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
2,静态只能覆盖静态,或被静态覆盖。
构造函数:
/* 子父类中的构造函数的特点。 在子类构造对象时,发现,访问子类构造函数时,父类也运行了。 为什么呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句。 super(); 子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数。 为什么子类实例化的时候要访问父类中的构造函数呢? 那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前, 要先看父类是如何对自己的内容进行初始化的。 所以子类在构造对象时,必须访问父类中的构造函数。 为什么完成这个必须的动作,就在子类的构造函数中加入了super()语句。 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用 父类中哪个构造函数。同时子类构造函数中如果使用this调用了本类构造函数时, 那么super就没有了,因为super和this都只能定义第一行。所以只能有一个。 但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。 注意:supre语句必须要定义在子类构造函数的第一行。因为父类的初始化动作要先完成。 */ class Fu { int num ; Fu() { num =10; System.out.println("A fu run"); } Fu(int x) { System.out.println("B fu run..."+x); } } class Zi extends Fu { int num; Zi() { //super();//调用的就是父类中的空参数的构造函数。 System.out.println("C zi run"+num); } Zi(int x) { this(); //super(); // super(x); System.out.println("D zi run "+x); } } class ExtendsDemo4 { public static void main(String[] args) { new Zi(6); } } class Demo//extends Object { /* Demo() { super(); return; } */ }
11. 抽象类
抽象类:抽象:笼统,模糊,不具体。
特点:
1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
抽象方法必须定义在抽象类中。该类必须也被abstract修饰。
2,抽象类不可以被实例化。为什么?因为调用抽象方法没意义。
3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。
否则,这个子类还是抽象类。
1,抽象类中有构造函数吗?
有,用于给子类对象进行初始化。
2,抽象类可以不定义抽象方法吗?
可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
通常这个类中的方法有方法体,但是却没有内容。
3,抽象关键字不可以和那些关键字共存?
private 不行
static 不行
final 不行
4,抽象类和一般类的异同点。
相同点:
抽象类和一般类都是用来描述事物的,都在内部定了成员。
不同:
1,一般类有足够的信息描述事物。
抽象类描述事物的信息有可能不足。
2,一般类中不能定义抽象方法,只能定非抽象方法。
抽象类中可定义抽象方法,同时也可以定义非抽象方法。
3,一般类可以被实例化。
抽象类不可以被实例化。
5,抽象类一定是个父类吗?
是的。因为需要子类覆盖其方法后才可以对子类实例化。
abstract class Demo
{
void show1()
{}
void show2()
{}
}
/* 雇员示例: 需求:公司中程序员有姓名,工号,薪水,工作内容。 项目经理除了有姓名,工号,薪水,还有奖金,工作内容。 对给出需求进行数据建模。 分析: 在这个问题领域中,先找出涉及的对象。 通过名词提炼法。 程序员: 属性:姓名,工号,薪水、 行为:工作。 经理: 属性:姓名,工号,薪水,奖金。 行为:工作。 程序员和经理不存在着直接继承关系, 但是程序员和经理却具有共性内容。 可以进行抽取。因为他们都是公司的雇员 可以将程序员和经理进行抽取.建立体系. */ //描述雇员。 abstract class Employee { private String name; private String id; private double pay; Employee(String name,String id,double pay) { this.name = name; this.id = id; this.pay = pay; } public abstract void work(); } //描述程序员。 class Programmer extends Employee { Programmer(String name,String id,double pay) { super(name,id,pay); } public void work() { System.out.println("code..."); } } //描述经理。 class Manager extends Employee { private int bonus; Manager(String name,String id,double pay,int bonus) { super(name,id,pay); this.bonus = bonus; } public void work() { System.out.println("manage"); } } class AbstractTest { public static void main(String[] args) { System.out.println("Hello World!"); } } class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Student extends Person { Student(String name,int age) { super(name,age); } } class Worker extends Person { Worker(String name,int age) { super(name,age); } }
12. 接口
/* abstract class AbsDemo { abstract void show1(); abstract void show2(); } 当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用 另一种形式定义和表示,就是 接口 interface。 */ //定义接口使用的关键字不是class,是interface. /* 对于接口当中常见的成员:而且这些成员都有固定的修饰符。 1,全局常量: public static final 2,抽象方法。public abstract 由此得出结论,接口中的成员都是公共的权限. */ interface Demo { public static final int NUM = 4; public abstract void show1(); public abstract void show2(); } //类与类之间是继承关系,类与接口直接是实现关系。 /* 接口不可以实例化。 只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。 否则,这个子类就是一个抽象类。 */ class DemoImpl implements /*实现*/Demo { public void show1() {} public void show2() { } } /* 在java中不直接支持多继承,因为会出现调用的不确定性。 所以java将多继承机制进行改良,在java中变成了多实现。 一个类可以实现多个接口。 */ interface A { public void show(); } interface Z { public int add(int a,int b); } class Test implements A,Z//多实现 { public int add(int a,int b) { return a+b+3; } /**/ public void show(){} } /* 一个类在继承另一个类的同时,还可以实现多个接口。 */ class Q { public void method() {} } abstract class Test2 extends Q implements A,Z { } /* 接口的出现避免了单继承的局限性。 */ interface CC { void show(); } interface MM { void method(); } interface QQ extends CC,MM//接口与接口之间是继承关系,而且接口可以多继承。 { void function(); } class WW implements QQ { //覆盖3个方法。 public void show(){} public void method(){} public void function(){} } class InterfaceDemo { public static void main(String[] args) { Test t = new Test(); t.show(); DemoImpl d = new DemoImpl(); System.out.println(d.NUM); System.out.println(DemoImpl.NUM); System.out.println(Demo.NUM); } }
13. 多态
1,多态的体现父类对象的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象
2,多态的前提
必须是类与类之间有关系,要么继承,要么实现
通常还有一个前提:存在覆盖
3,多态的好处
多态的出现大大提高程序的扩展性
4,多态的弊端
虽然提高了扩展性,但是只能使用父类的引用访问父类中的成员
5,多态的应用
6,多态的出现代码中的特点(多态使用注意事项)
在多态中成员函数的特点:(动态绑定和静态绑定)
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败
在运行时期:参阅对象所述的类中是否有调用的方法
简单总结就是,成员函数在多态中,编译看左边,运行看右边
/* 基础班学生 学习,睡觉 高级班学生 学习,睡觉 可以将这两类事物进行抽取 */ abstract class Student { public abstract void study(); public viud sleep() { System.out.println("躺着睡"); } } class BaseStudent extends Student { public void study() { System.out.println("base study"); } public void sleep() { System.out.println("坐着睡"); } } class AdvStudent extends Student { public void study() { System.out.println("adv study"); } } class DoStudent { public void doSome(Student s) { s.study(); s.sleep(); } } class Demo { public static void main(String[] args) { DoStudent ds = new DoStudent(); ds.doSome(new BaseStudent()); ds.doSome(new AdvStudent()); /* BaseStudent bs = new BaseStudent(); bs.study(); bs.sleep(); AdvStudent as = new AdvStudent(); as.study(); as.sleep(); */ } }
模板方法设计模式
/* 需求:获取一段程序运行的时间 原理:获取程序开始和结束的时间并相减就可以 */ abstract class GetTime { public final void getTime()//用final修饰防止被复写 { long start = System.currentTimeMillis(); runcode(); long end = System.currentTimeMillis(); System.out.println("毫秒:"+(end-start)); } public abstract void runcode();//因为不明确方法主体所以使用抽象方法 } class Test extends GetTime { public void runcode() { for(int x=0;x<1000;x++) { System.out.println(x); } } }
多态降低耦合性示例:
1,未利用多态的程序
/* 需求: 电脑运行实例, 电脑运行基于主板 */ class MainBoard { public void run() { System.out.println("mainboard run"); } public void useNetCard(NetCard c) { c.open(); c.close(); } } class NetCard { public void open() { System.out.println("netcard open"); } public void close() { System.out.println("netcard close"); } } class Computer { public static void main(String[] args) { MainBoard mb = new MainBoard(); mb.run(); mb.useNetCard(); } }
使用多态:(接口)
interface PCI { public void open(); public void close(); } class MainBoard { public void run() { System.out.println("mainboard run"); } public void usePCI(PCI p) { if(p!=null) { p.open(); p.close(); } } } class NetCard implements PCI { public void open() { System.out.println("netcard open"); } public void close() { System.out.println("netcard close"); } } class Demo2 { public static void main(String[] args) { MainBoard mb = new MainBoard(); mb.run(); } }
14. 内部类
内部类的访问规则:1,内部类可以直接访问外部类的成员,包括私有。
之所以可以直接访问外部类的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2,外部类要访问内部类,必须建立内部类对象。
访问格式:
1,当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;,2,当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装,static:内部类就具备static特性,当内部类被静态修饰后,只能直接访问外部类静态成员
/* 内部类 */ class Outer { int x=3; class Inner { void function() { System.out.println("Inner:"+x); } } void method() { Inner in = new Inner(); in.function(); } } class Main { public static void main(String[] args) { Outer out = new Outer(); //内部类访问 Outer.Inner in = new Outer().new Inner(); out.method(); } }
15. 异常
异常:就是程序在运行时出现的不正常情况。异常由来:问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。
其实就是java对不正常的情况进行描述后的对象体现。
对于问题的划分:两种:一种是严重的问题,一种是非严重的问题
对于严重的,java通过Error类进行描述。
对于不严重的,java通过Exception类进行描述。
异常的体系:
Throwanle
Error:通常出现大量问题如,运行的类不存在或者内存溢出等,不编写针对代码对其处理
Exception:在运行时运行出现的一些情况,可以通过try catch finally来处理
处理方法:
1,
try{
//此处放异常的代码
}
catch(Exception e){
//此处是如果try里面的语句发生异常不能执行,就执行catch里的语句
}
finally{
//此处放必须会执行的代码
}
2,
在功能上通过throws关键字声明了该功能可能出现问题。
throws Exception
多异常处理 :
1,声明宜昌市,建议声明更为具体的异常,这样处理的可以更具体。
2,对方声明几个异常,就对应有几个catch块,不要定义多余的
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
建议在进行catch处理时,catch中一定要定义具体的处理方式。
不要简单定义一句e.printStackTrace(),也不要简单的就书写一条输出语句
[b]throws和throw区别
throws:使用在函数上
throw使用在函数内
throws后面跟的是异常类,可以跟多个,用逗号隔开。
throw后跟的是异常对象。
相关文章推荐
- 黑马程序员 java 基础 毕向东 面向对象 集合框架 工具类 Collections and Arrays
- 黑马程序员_java面向对象基础学习笔记
- 黑马程序员_java基础复习二面向对象
- 黑马程序员---Java基础--06天(面向对象之二)
- 黑马程序员——Java语言基础——03.面向对象(1)思想和一些概念
- 黑马程序员 java 基础 毕向东 面向对象 集合框架 List Set
- 黑马程序员--Java基础--面向对象之三大特性
- 黑马程序员学习log第六篇基础知识:JAVA的面向对象之IO总结
- 黑马程序员——Java基础---面向对象及其一些代码内部结构分析
- 黑马程序员 java 基础 毕向东 面向对象 多态
- 黑马程序员——Java重点基础之面向对象思想
- 黑马程序员_java基础笔记(03)...面向对象
- 黑马程序员-Java基础(二)-面向对象
- 黑马程序员---java基础知识(三):面向对象
- 黑马程序员—4—Java基础: 面向对象继承学习笔记和学习心得体会
- 黑马程序员--面向对象第二部分-内部类、异常--java学习日记6(基础知识)
- 黑马程序员_java基础笔记(03)...面向对象
- 黑马程序员——一切皆对象:Java面向对象基础
- 黑马程序员----java基础面向对象总结
- 黑马程序员====JAVA基础之面向对象及其特性====