黑马程序员----面向对象及其三大特性
2015-08-15 15:18
429 查看
——- android培训、java培训、期待与您交流! ———-
一、面向对象
面向过程:强调动作,
面向对象:只要找到对象,对象的所有功能也都找到了。
1.面向对象的形象化解释(人开门:名词提炼法)
人
{
开门(门)
{
门.开;
}
}
门
{
开(){对门的操作}
}
2.面向对象有三个特征:封装,继承,多态。
(以后的开发就是找对象使用,没有对象,就创建一个对象;找对象,建立对象,使用对象,维护对象的关系;)
3.类和对象的关系:
类:就是对现实生活中事物的描述;
对象:就是这类事物,实实在在存在的个体(通过new操作符产生的一个实体,这个实体在堆内存当中);
描述和对象的关系:
现实生活中的对象:张三,李四;
想要描述:提取对象中共性内容,对具体的抽象
描述时:这些对象的共性有,姓名,年龄,性别,学习java的功能;
映射到java中,描述就是class定义的类;
具体对象就是对应java在堆内存中用new建立的实体。
//描述一个汽车:描述事物的属性和功能;
//属性对应的是类中的变量,行为对应的是类中的函数(方法);
//定义类就是在描述事物,就是在定义属性和行为,属性和行为共同成为类中的成员(成员变量和成员函数);
讲到对象,要试着画图,图画出来了,很多流程就能明白,在内存中是什么样子了
4.成员变量和局部变量的不同:
1)作用范围不一样:成员变量作用于整个类中,局部变量作用于函数中或者语句中;
2)在内存中的位置不一样:成员变量在堆内存中(因为对象的存在,才在内存中存在),局部变量存在栈内存中。
c.num=5;
上面两句代码可以简写为:new Car().num=5;
匿名对象和有名对象到底有什么不同?
匿名对象不断地在堆中创建对象,但是当创建后一个对象是,前一个对象就已经是垃圾了,没有人再用了(前一个对象一执行完就是垃圾了)。匿名对象调用的属性没有意义,但调用的方法是有意义的。
匿名对象使用方式一:当对象的方法只调用一次时,可以用匿名对象来完成;如果对一个对象进行多个成员调用,必须给这个对象起个名字。
匿名对象使用方法二:可以将匿名对象作为实际参数进行传递。
保证对象的生命周期到底有多长,如果不指定,虚拟机直接回收,但有些对象虚拟机不收,会一直在,那么就让该对象指向null;当做缓存技术的时候,就需要考虑到这个对象必须要把空间释放出来的时候,就需要注意强引用、弱引用、软引用、虚引用(用于优化内存,具体方法:直接用Java提供的对象就行)。
函数名与类名相同;
不用定义返回值类型(与void不同);
可以不写return语句。
作用:给对象进行初始化,对象一创建,就会调用与之对应的构造函数。
注意:
默认构造函数的特点:空参数;
多个构造函数是以重载的形式存在的。
什么时候定义构造函数呢?
当分析事物时,该事物具备一些特性或者行为,那么将这些内容定义在构造函数中;
确定是否有未知变量参与运算以确定参数。
构造函数的一个小细节:
当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数:
Person(){} //方便初始化;
当自己定义了构造函数时,系统就不再添加默认构造函数;
构造函数和一般函数的不同:
1.格式不同
2.在运行上不同:
构造函数是在对象一建立就运行,给对象初始化;而一般方法是对象调用才执行,是给对象添加对象具备的功能。 一个对象一建立,构造函数只运行一次,而一般方法可以被该对象调用多次。
好处:将变化隔离;便于使用;提高重用性; 提高安全性。
封装原则:1)将不需要对外提供的内容都隐藏起来; 2)把属性都隐藏,提供公共方法对其访问。
权限关键字:Public:公有(权限最大)Private:私有(权限最小),私有只在本类中有效,私有仅仅是封装的一种表现形式;
权限修饰符,用于修饰类中的成员(成员变量,成员函数);
一个成员变量,通常都会对应两个访问方式:set和get。
凡是set打头的方法,它的返回值类型一定是void,并且需要带参数;而get打头的方法的返回值类型跟它获取的变量类型一致,不带参数。
但凡看到一个类中有getXxx或者是setXxx,就代表这个类中一定有私有属性。
之所以对外提供访问方式,是因为可以在访问方式中加入逻辑判断等语句,对访问方式的数据进行操作,提高代码的健壮性。
1.提高了代码的复用性;
2.继承让类与类之间产生了关系,有了关系才有了多态的特性;
注意:千万不要为了获取其他类的功能,简化代码而继承;
必须是类与类之间有所属关系才可以继承,所属关系; 类1 is a 类2;当继承出现以后,子父类之间到底会发生什么样的变化?或者说,有什么样的特点了呢? 类中成员包括三个:
1.变量;如果子父类中出现非私有的同名成员变量时,子类要访问本类中的同名变量用this,子类要访问父类中的同名变量时用super。
this和super的使用方法基本一致。this代表的是子类对象的引用;super代表的是父类对象的引用;
2.函数;当子类继承了父类,沿袭了父类的功能到子类中,但是子类虽然具备该功能而功能的内容与父类不一致时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义并重写功能内容。(功能扩展)
3.构造函数。构造函数不能重写(构造函数随着类名走,子父类函数名不能一致)。
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类构造函数的第一条执行语句默认为super();
super();会访问父类中的空参数的构造函数;而且子类中所有的构造函数默认第一行都是super();
子类必然能够访问到父类中的构造函数(默认构造函数)。
覆盖注意事项:
1.子类覆盖父类,必须保证子类权限大于等于父类,否则编译失败;
2.静态只能覆盖静态(一般不用,知道就行,关系到先后加载的问题)
3.子类必须知道父类的功能才可以覆盖。
重载和重写的区别:
重载只看同名函数的参数列表,而重写叫做子父类方法要一模一样,包括返回值类型也要一样。
为什么子类一定要访问父类中的构造函数;
因为子类在对象初始化时要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句来访问。
super();//必须写在子类的首句;(先找父类)
子类中this();和super();不能同时存在。
子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
对象多态性两个体现:
人:男人;女人。
动物:猫;狗。
猫 x=new 猫();
动物 x=new 猫();
围绕四个问题学习:
1.多态的表现形式?
父类的引用指向了自己的子类对象;父类的引用也可以接受自己的子类对象;
2.多态的前提?
必须是类与类之间有关系,要么继承,要么实现;
存在覆盖(子类覆盖父类功能)。
3.多态到底有什么好处?
多态的出现大大的提高了程序的扩展性;
(弊端:只能使用父类的引用访问父类中的成员。)
4.多态如何应用?
5.多态在代码中的特点(多态使用的注意事项)
多态的特点:
1.多态中成员函数(非静态)的特点:
在编译时期,参阅引用类型的变量所属的类中是否有调用的方法,如果有,编译通过,否则编译失败;
在运行时期,参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
涉及到面试的内容,开发时一般不多见:
在多态中成员变量的特点 :无论编译还是运行,都参考左边(引用变量所属的类)
2.在多态中,静态成员函数的特点:无论编译和运行,都参考左边; 静态参考的是类。
一、面向对象
面向过程:强调动作,面向对象:只要找到对象,对象的所有功能也都找到了。
1.面向对象的形象化解释(人开门:名词提炼法)
人
{
开门(门)
{
门.开;
}
}
门
{
开(){对门的操作}
}
2.面向对象有三个特征:封装,继承,多态。
(以后的开发就是找对象使用,没有对象,就创建一个对象;找对象,建立对象,使用对象,维护对象的关系;)
3.类和对象的关系:
类:就是对现实生活中事物的描述;
对象:就是这类事物,实实在在存在的个体(通过new操作符产生的一个实体,这个实体在堆内存当中);
描述和对象的关系:
现实生活中的对象:张三,李四;
想要描述:提取对象中共性内容,对具体的抽象
描述时:这些对象的共性有,姓名,年龄,性别,学习java的功能;
映射到java中,描述就是class定义的类;
具体对象就是对应java在堆内存中用new建立的实体。
//描述一个汽车:描述事物的属性和功能;
//属性对应的是类中的变量,行为对应的是类中的函数(方法);
//定义类就是在描述事物,就是在定义属性和行为,属性和行为共同成为类中的成员(成员变量和成员函数);
讲到对象,要试着画图,图画出来了,很多流程就能明白,在内存中是什么样子了
4.成员变量和局部变量的不同:
1)作用范围不一样:成员变量作用于整个类中,局部变量作用于函数中或者语句中;
2)在内存中的位置不一样:成员变量在堆内存中(因为对象的存在,才在内存中存在),局部变量存在栈内存中。
class Car { //描述颜色; String color="红色";//显示初始化值。 //描述轮胎数 int num=4;//默认为0; //运行行为: void run() { Ststem.out.println(color+"...."+num); } //此类中一般不写主函数,一个程序有一个主函数就可以; /*public static void main(String[] args) { Car c=new Car();//在本类中创建对象, c.color="blue";//如果不赋值,则默认为null。 run(); }*/ } class CarDemo { public static void main(String[] args) { //生产汽车,在java中通过new操作符来完成,其实就是在堆内存中产生一个实体 Car c=new Car();//c就是一个类类型变量,引用型变量,类类型变量指向对象。 //将已有的车的颜色改成蓝色,指挥该对象做使用,在java指挥方式是:对象.对象成员; c.color="blue";//重新赋值; c.run(); Car c1=new Car(); c1.run();//red 4; } }
二、匿名对象
Car c=new Car();c.num=5;
上面两句代码可以简写为:new Car().num=5;
匿名对象和有名对象到底有什么不同?
匿名对象不断地在堆中创建对象,但是当创建后一个对象是,前一个对象就已经是垃圾了,没有人再用了(前一个对象一执行完就是垃圾了)。匿名对象调用的属性没有意义,但调用的方法是有意义的。
匿名对象使用方式一:当对象的方法只调用一次时,可以用匿名对象来完成;如果对一个对象进行多个成员调用,必须给这个对象起个名字。
匿名对象使用方法二:可以将匿名对象作为实际参数进行传递。
保证对象的生命周期到底有多长,如果不指定,虚拟机直接回收,但有些对象虚拟机不收,会一直在,那么就让该对象指向null;当做缓存技术的时候,就需要考虑到这个对象必须要把空间释放出来的时候,就需要注意强引用、弱引用、软引用、虚引用(用于优化内存,具体方法:直接用Java提供的对象就行)。
三、构造函数
特点:函数名与类名相同;
不用定义返回值类型(与void不同);
可以不写return语句。
作用:给对象进行初始化,对象一创建,就会调用与之对应的构造函数。
注意:
默认构造函数的特点:空参数;
多个构造函数是以重载的形式存在的。
什么时候定义构造函数呢?
当分析事物时,该事物具备一些特性或者行为,那么将这些内容定义在构造函数中;
确定是否有未知变量参与运算以确定参数。
构造函数的一个小细节:
当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数:
Person(){} //方便初始化;
当自己定义了构造函数时,系统就不再添加默认构造函数;
构造函数和一般函数的不同:
1.格式不同
2.在运行上不同:
构造函数是在对象一建立就运行,给对象初始化;而一般方法是对象调用才执行,是给对象添加对象具备的功能。 一个对象一建立,构造函数只运行一次,而一般方法可以被该对象调用多次。
四、封装(Encapsulation)
指隐藏对象的属性和实现细节,仅对外提供公共的访问方式。好处:将变化隔离;便于使用;提高重用性; 提高安全性。
封装原则:1)将不需要对外提供的内容都隐藏起来; 2)把属性都隐藏,提供公共方法对其访问。
权限关键字:Public:公有(权限最大)Private:私有(权限最小),私有只在本类中有效,私有仅仅是封装的一种表现形式;
权限修饰符,用于修饰类中的成员(成员变量,成员函数);
一个成员变量,通常都会对应两个访问方式:set和get。
凡是set打头的方法,它的返回值类型一定是void,并且需要带参数;而get打头的方法的返回值类型跟它获取的变量类型一致,不带参数。
但凡看到一个类中有getXxx或者是setXxx,就代表这个类中一定有私有属性。
之所以对外提供访问方式,是因为可以在访问方式中加入逻辑判断等语句,对访问方式的数据进行操作,提高代码的健壮性。
五、继承(Extends)
事物关系中的一种。1.提高了代码的复用性;
2.继承让类与类之间产生了关系,有了关系才有了多态的特性;
注意:千万不要为了获取其他类的功能,简化代码而继承;
必须是类与类之间有所属关系才可以继承,所属关系; 类1 is a 类2;当继承出现以后,子父类之间到底会发生什么样的变化?或者说,有什么样的特点了呢? 类中成员包括三个:
1.变量;如果子父类中出现非私有的同名成员变量时,子类要访问本类中的同名变量用this,子类要访问父类中的同名变量时用super。
this和super的使用方法基本一致。this代表的是子类对象的引用;super代表的是父类对象的引用;
2.函数;当子类继承了父类,沿袭了父类的功能到子类中,但是子类虽然具备该功能而功能的内容与父类不一致时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义并重写功能内容。(功能扩展)
3.构造函数。构造函数不能重写(构造函数随着类名走,子父类函数名不能一致)。
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类构造函数的第一条执行语句默认为super();
super();会访问父类中的空参数的构造函数;而且子类中所有的构造函数默认第一行都是super();
子类必然能够访问到父类中的构造函数(默认构造函数)。
class Telephone { void show() { System.out.println("number"); } } class NEWTelephone { void show() { //System.out.println("number"); super.show();//父类已经定义好了,直接拿过来用; System.out.println("name"); System.out.println("picture"); } }
覆盖注意事项:
1.子类覆盖父类,必须保证子类权限大于等于父类,否则编译失败;
2.静态只能覆盖静态(一般不用,知道就行,关系到先后加载的问题)
3.子类必须知道父类的功能才可以覆盖。
重载和重写的区别:
重载只看同名函数的参数列表,而重写叫做子父类方法要一模一样,包括返回值类型也要一样。
为什么子类一定要访问父类中的构造函数;
因为子类在对象初始化时要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句来访问。
class Person //extends Object(所有类的父类) { String name; Person(String name) { //super();父类中也有super语句。父类继承自object。 this.name=name; } } class Student extends Person { Student(String name) { super(name);//必须写在首句; } }
super();//必须写在子类的首句;(先找父类)
子类中this();和super();不能同时存在。
子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
class Extends //父类 { int num=4; void show1() { System.out.println("父类 show"); } void speak() { System.out.println("vb"); } Extends()//构造函数的函数名要和类名一致; { num=60; System.out.println("Father run"); } Extends(int x)//构造函数的函数名要和类名一致; { System.out.println("Father run"+x); } } //演示变量; class Extends_1 extends Extends //子类1 { int num2=5; int num=5;//当父类和子类的变量同名是,打印的是子类变量的值; void show() { System.out.println(this.num);//打印子类中的num1;this代表的是子类对象的引用; System.out.println(super.num);//打印父类中的num1;super代表的是父类对象的引用; System.out.println(this.num);//当子类中没有自己的num变量时,this和super为同一指向,都是指向父类中的num,所以打印结果为4; } } //演示函数; class Extends_2 extends Extends //子类2 { void show2() { System.out.println("子类 show"); } void speak()//如果子父类方法名一致,会运行子类函数的内容,这就是函数的另一个特性:覆盖(重写)。父类方法没有运行。 { System.out.println("java"); } } //演示构造函数; class Extends_3 extends Extends //子类3 { Extends_3()//函数名要和类名一致; { //super();//调用父类构造函数,不写虚拟机会自动加,父类构造函数中的内容会先执行; System.out.println("child run"); } Extends_3(int x)//函数名要和类名一致; { //super(); super(3);//手动指定要访问父类中的哪一个构造函数; //this();//调用本类空参数的构造函数; System.out.println("child2 run"+x); } } public class ExtendsDemo2 { public static void main(String[] args)//主函数; { //演示变量; Extends_1 z=new Extends_1(); System.out.println(z.num+"....."+z.num2 ); z.show(); //演示函数; Extends_2 z1=new Extends_2(); z1.show1();//打印父类 show,因为子类已经拿到了父类中的内容; z1.show2(); z1.speak(); //演示构造函数; Extends_3 z2=new Extends_3(); Extends_3 z3=new Extends_3(4);//传入参数; System.out.println(z2.num); } }
六、多态
多态:某一类事物的多种存在形态。对象多态性两个体现:
人:男人;女人。
动物:猫;狗。
猫 x=new 猫();
动物 x=new 猫();
围绕四个问题学习:
1.多态的表现形式?
父类的引用指向了自己的子类对象;父类的引用也可以接受自己的子类对象;
2.多态的前提?
必须是类与类之间有关系,要么继承,要么实现;
存在覆盖(子类覆盖父类功能)。
3.多态到底有什么好处?
多态的出现大大的提高了程序的扩展性;
(弊端:只能使用父类的引用访问父类中的成员。)
4.多态如何应用?
5.多态在代码中的特点(多态使用的注意事项)
//动物体系: abstract class Animals //父类 { abstract void eat();//吃什么不确定; } class Cat extends Animals { public void eat() { System.out.println("吃鱼"); } public void catchmouse() { System.out.println("抓老鼠"); } } class Dog extends Animals { public void eat() { System.out.println("吃骨头"); } public void kanjia() { System.out.println("看家"); } } class Pig extends Animals { public void eat() { System.out.println("猪吃饲料"); } public void gongdi() { System.out.println("拱地"); } } public class DuoTaiDemo { public static void main(String[] args) { /* Cat c=new Cat(); //c.eat(); //c.catchmouse(); //让另一只猫吃东西 Cat c1=new Cat();//重复使用,封装方法; //c1.eat(); function(c); function(c1); Dog d=new Dog(); //d.eat(); d.kanjia(); function(d); function(new Dog()); Pig p=new Pig(); function(p); //转换: Animals c2=new Cat(); //猫也是动物,具备动物类吃的属性(一个对象具备多种形态) c2.eat(); //子类中也有吃的方法,调用子类中的eat方法; Animals d1=new Dog(); //类型提升; d1.eat(); function(new Cat()); //提高代码的扩展性; function(new Dog()); function(new Pig()); //等学完反射,这块代码就可以不用动了; //如果想要调用猫的特有方法该如何操作? //强制将父类的引用转成子类类型;向下转型; Cat c3=(Cat)c2; //小动物强转成猫咪; c3.catchmouse(); //注意:千万不能将父类类型转成子类类型; //我们能转换的是父类引用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换; //多态自始至终都是子类对象在变化; */ function(new Cat()); function(new Dog()); function(new Pig()); //function(new Mouse()); } //都具备吃的行为,因为它们都是动物; /* public static void function(Cat c) { c.eat(); } public static void function(Dog d) { d.eat(); } public static void function(Pig p) { p.eat(); } */ public static void function(Animals a) { a.eat(); /* if(a instanceof Animals)//判断的时候父类不要写在上面,因为条件满足后面的代码就都不会再判断了; {} else{} */ if(a instanceof Cat) { Cat c=(Cat)a; c.catchmouse();//抓老鼠; } else if(a instanceof Dog) { Dog c=(Dog)a; c.kanjia();//看家; } else if(a instanceof Pig) { Pig c=(Pig)a; c.gongdi();//拱地; } else { System.out.println("Another Animals"); } } }
//一般不使用这种方法进行判断,因为当增加子类的时候,程序的扩展性极差; //instanceof用来判断所属类型; //instanceof在两种情况下使用: //1.当子类个数很少的时候; //2.当传的类型需要进行其他操作的时候(比如比较的时候),必须要确定它是哪种子类型(因为要调用特殊方法进行比较),这是用instanceof判断一下;
多态的特点:
1.多态中成员函数(非静态)的特点:
在编译时期,参阅引用类型的变量所属的类中是否有调用的方法,如果有,编译通过,否则编译失败;
在运行时期,参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
涉及到面试的内容,开发时一般不多见:
在多态中成员变量的特点 :无论编译还是运行,都参考左边(引用变量所属的类)
2.在多态中,静态成员函数的特点:无论编译和运行,都参考左边; 静态参考的是类。
class Fu { int num=5; void method1() { System.out.println("fu method1"); } void method2() { System.out.println("fu method2"); } static void method4() { System.out.println("fu method4"); } } class Zi extends Fu { int num=8; void method1() { System.out.println("zi method1"); } void method3() { System.out.println("fu method3"); } static void method4() { System.out.println("zi method4"); } } public class DuoTaiTedian { public static void main(String[] args) { Zi z=new Zi(); z.method1(); z.method2(); z.method3(); System.out.println(z.num);//结果是8 Fu f=new Zi(); f.method1(); f.method2();//调用子类中的method2方法; //f.method3(); System.out.println(f.num);//结果是5; f.method4();//开发时一般不覆盖静态;静态方法是不需要对象的。 } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统