1.面向对象概念
什么是面向对象,面向对象与面向过程的区别?
面向对象是相对面向过程而言,面向过程和面向对象都是一种思想,面向过程注重的是过程, 强调的是功能行为,面向对象就是将功能封装进对象,强调的是具备了功能的对象。面向对象 简单地说就是站在对象的角度考虑问题。
面向对象的几个例子:(比较重要一定要理解)
a.账户的存取
面向对象简单地说就是站在对象的角度考虑问题,比如说有一个账户,我们可以对其进行存款和取款的操作,以面向过程的思想考虑就是我们操作此账户,来手动的完成存和取的动作。而以 面向对象的思想来考虑的话,就是我们可以把存款和取款这两个功能封装在账户中,每当我们要存或取的时候,就直接调用账户就行了。
b.冰箱的开关
要把大象放进冰箱,要分为三个步骤,把冰箱门打开,把大象放进去,把冰箱门关上。首先开门,放东西进去,关门,这三步都是过程吧,以面向过程的思想就是我们要去执行这三个过程,每一次往里放东西都要执行这三个步骤,这样是比较麻烦的,这样考虑下,加入我们把这三个 功能的方法装进冰箱里,就是说冰箱具有自动开关等功能,我们再需要往冰箱里放东西,是不是就可以直接找冰箱这三个步骤让它来做(因为它具有了这三个功能)就行啦。
再简单点说就是,比如有一个大筐里面放了编写程序所需要的所有功能(也就是函数),再假如 说此时我们要做一件事,过程中需要调用好多功能,这时我们是不是就需要在那个大筐里找我们所 需要的功能啊,这样是比较麻烦的。然后我们再想是不是可以这样,这个大筐中的功能肯定有好多共性的,并且同属于一个事物的(比如说冰箱的开关等),这时我们是不是就可以把这些共性的功能放到另一个小筐里啊,等下次再用的时候直接找这个小框就行了,反正那些功能是小筐特有的,那就直接让它做就ok了,这样是不是就省了很多事儿啊。
面向对象的特点有哪些?
1、 面向对象是一种思想
2、可以将复杂的事情简单化
3、将程序员从执行者转换成了指挥者
为什么需要面向对象?
面向对象与人们习惯的思维方法一致,使程序代码更加容易让人理解和接受,开发效率高,并且有利与后期修改和维护;面向对象能提高代码的复用性,而面向过程就不行,好比有一个功能, 面向过程的程序设计时如果有很多地方都用到这个功能,那好多地方的代码肯定都是重复的,而用面向对象的话,就直接调用(对象.功能) 就行了,够简洁吧。
2.类与对象的区别
在开发的过程中其实就是在找对象用,比如说要用一个功能,就找其对应的对象,如果没有的话,就 自己造一个对象,把功能封装进去。然后再指挥该对象做事情。
类:就是具体事物的描述,就是描述对象的,类是抽象的,就像一张图纸。
对象:就是实实在在具体的事物,类就是描述它的。new一个类就出来一个对象实体在java中,描述就是class定义的类,对象就是java堆内存中new出来的实体。因为一个对象里含有很多数据,我们说含有很多数据的就用实体来存储,就像数组一样
怎么定义一个类?
定义一个类其实就是在描述一个事物,而一个事物通常都会有属性与行为,就像一只鸭子,眼睛 腿就是 属性,游泳就是行为。属性对应的就是类中的变量,行为对应的就是类中的函数。 一个类要想独立运行的前提是要有主函数,而建立一个类不需要独立运行的话可以不写主函数
类中的成员有:成员变量和成员函数
成员变量与局部变量的区别是什么?
成员变量作用于整个类中,而局部变量作用于函数中或语句中,用过后空间会被自动释放。成员变量在栈内存中,而局部变量存在于堆内存中,因为它是因对象存在而存在的,你说人都没了定义人的年龄有什么用。局部变量没有默认初始化值,而成员变量有默认初始化值。
定义一个类:
class Car//对Car这类事物进行描述
{
String color = "red";//在整个类中有效
int num = 4;
void show()
{
System.out.println("color="+color+"..num="+num);
}
}
class CarDemo
{
public static void main(String[] args)
{
Car c = new Car();//new一个汽车实体
c.color = "black";//对对象(汽车)的属性进行修改
c.show();//使用对象的功能。
}
}
匿名对象
什么是匿名对象?
匿名对象是对象的简化形式
例如:Car c = new Car();c.show();可以写成new Car().show;这就是匿名对象直接调用show方法
什么情况下使用匿名对象?
1.当对对象的方法只调用一次时(调用变量没意义),可以用匿名对象来完成,这样写比较简化。
如果对一个对象进行多个成员调用,必须给这个对象起个名字。
2.可以将匿名对象作为实际参数进行传递。
代码:
class Car { String color = "红色";//描述颜色 int num = 4;//描述轮胎数 void run()//运行行为。 { System.out.println(color+".."+num); } } class CarDemo { public static void main(String[] args) { //创建一匿名对象调用属性 new Car().num = 5; //又创建一匿名对象,此时上面创建的堆内存中的实体已经成垃圾了 new Car().color = "blue"; new Car().run();//创建匿名对象调用属性没意义,因为调过来了没人用 Car q = new Car(); show(q);//创建一有名对象,调用show方法 //上面两步可以简化成这样: show(new Car());//匿名对象当参数传入 } public static void show(Car c)//传入一个car类型的参数 { c.num = 3; c.color = "black"; c.run(); } }
对象与匿名对象在内存中的结构如下图:
黑马程序员——面向对象之封装 - hm_yong_jie - hm_yong_jie的博客
3.封装
什么是封装?
面向对象三大特征之一,是指隐藏对象的属性和实现细节,仅对外提供 公共访问方式。就是说我们如果调用一个功能的话,我们要的就是它的结果,而它怎么实现的和我们没关系。函数就是最小的封装体。
1、比如说我们使用的电脑,什么上网啊,玩游戏啊,我们使用的只是它的功能,有必要直到它内部是怎么实现的吗?有必要打开机箱看看里面都是什么吗?即使打开看了也不懂,还有可能把电脑给捯饬坏。
使用封装有什么好处呢?
1.提高安全性 把主板啊,cpu啊封装在机箱内,避免我们这些不懂的人乱碰乱改,是不是安全了?
2.提高重用性
3.将变化隔离 这次机箱里面的部件是这样,等过些日子又出来一新电脑,里面的东西是不是变啦, 怎么变得我们知道,也不需要知道,这就是将变化隔离
4.便于使用 我们不需要知道电脑的内部结构了,直接拿过来就能用,是不是很方便
private(私有)关键字
封装的目的就是限制对类里面成员的访问,隐藏类的实现细节,那么要限制类的外部对类成员的访问,可以用访问修饰符private来修饰属性。
1.private是一个权限修饰符
2.用于修饰成员(成员变量和成员函数)
3.被私有化的成员只在本类中有效用private将成员变量私有化,对外提供对应的set,get方法对其进行访问,提高对数据访问的安全性。
代码:
class Person { //把person类中的age属性私有化,在其他类中将不能访问它,像new Person().age是不行的 private int age; //在这个类中不让访问age,但是你得提供一个让别人访问的方法啊,就是下面这样 public void setAge(int a) { if(a>0 && a<130) { age = a; speak(); } else System.out.println("feifa age"); } public int getAge() { return age; } //类中的方法被私有化,在别的类中也是访问不到的,只在本类中有效 private void speak() { System.out.println("age="+age); } }
4.构造函数
什么是构造函数?
构造函数是类中一种特殊的函数,它方法名誉类名相同,没有返回值类型,也不需要void,构造 函数的作用在于创建对象的时候初始化对象,给实例化对象的成员变量赋初始值。
构造函数的特点是什么?
1.函数名与类名相同
2.不用定义返回值类型(void也是一种返回值类型)
3.不可以写return语句 函数中连返回值类型都没有还用得着把return语句吗?
构造函数与一般函数有什么区别?
1.首先在写法上就不同,然后在运行上也有不同。构造函数是在对象一建立就运行。给对象初始化。而一般方法是对象调用才执行,是给对象添加对象具备的功能。
2.一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。可以理解为构造函数就是为了创建对象,对象一创建完它的使命就完成了
什么时候用构造函数?
当分析事物时,该事物存在具备一些特性或者行为,就是该食物一定具备哪些行为(就像小孩 一出生就哭)那么将这些内容定义在构造函数中。然后再考虑写构造函数的时候是否需要未知参数参与运算。
构造函数有什么用?
构造函数是用来给对象进行初始化的,对象一建立就会调用与之对应的构造函数,
注意:
说是对象一初始化就要调用构造函数,那前些日子写代码也没斜构造函数啊?这是因为当 一个类中没写构造函数时,系统会帮你自动加一个空参数的构造函数,方便于对象初始化, 否则对象是建立不出来的。总之要记着,一个类中如果没有构造函数,那这个对象是肯定new不出来的。如果new对象时,类中没有与它对应的构造函数,这样也是创建不出对象的。 如果你自己建立了一个构造函数,那默认的构造函数就没了。
部分代码:
class Person { private String name; private int age; //所以对象一创建就会按下面与之对应的构造函数来初始化对象 Person() { System.out.println("A: name="+name+",,age="+age); } //构造函数也是函数它也可以重载 Person(String n) { name = n; System.out.println("B: name="+name+",,age="+age); } Person(String n,int a) { name = n; age = a; System.out.println("C: name="+name+",,age="+age); } } class PersonDemo2 { public static void main(String[] args) { //对应第一种构造函数new出来的人什么都没有 Person p1 = new Person(); //对应第二种构造函数new出来的人有名字没年龄 Person p2 = new Person("lisi"); //对应第三种构造函数new出来的人有年龄有姓名 Person p3 = new Person("lisi",0); } }
构造代码块:
作用:给对象进行初始化,对象一创建就运行,并且优先于构造函数
疑问:构造函数不就是给对象进行初始化的吗,为什么还要用构造代码块啊?和构造函数的区别: 上面不是说有很多种构造函数吗,就是说创建对象的时候能创建很多种类型的对象,每一种构造函数都是给其对应的那类对象初始化,而构造代码块是给所有种类的对象都初始化,也就是说把所有类型对象的共同点给抽出来写在构造代码块里,这样就不用在每种构造函数都写了,比如每一种小孩生下来都哭,那么这样就可以把哭的行为写进构造代码块,是不是比在每个构造函数里都写显得轻松啊,就像是以前说的如果好几段代码里都有相同代码的时候,那就把这些相同的抽出来写进一个函数中,不就 省的来回的重复写啦。
5.this关键字
class Person
{
private String name;//此name是成员变量
public void String setName(String name)//此name是往函数中传的参数是局部变量
{
//this.成员变量 = 局部变量
this.name = name;
}
}
从以上代码看出this是用来解决成员变量和局部变量同名似的问题。
this:看上去,是用于区分局部变量和成员变量同名情况。
this:就代表本类的对象,到底代表哪一个呢?
this代表它所在函数所属对象的引用。
简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
类中成员之间的互相调用的时候其实都是对象完成的,只不过是省略了this.。
class Person
{
private String name;
public void speak()
{
System.out.println("name="+this.name);//省略了this.
}
}
this的应用:
当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用了了本类对象,都用this表示。
this语句 :用于构造函数之间进行互相调用。
this语句只能定义在构造函数的第一行。因为初始化要先执行。
部分代码:
class Person { private String name; private int age; Person(String name) { this.name =name; } Person(String name,int age) { this(name);//调用上一种构造函数,不过要写在第一行 this.age = age; } }
6.static关键字
static用于修饰成员(成员变量和成员函数),static修饰的是把所有new出来的对象共性的东西。
参看下图:
黑马程序员——面向对象之封装 - hm_yong_jie - hm_yong_jie的博客
被修饰后的成员具备以下特点:
1.随着类的加载而加载 说明它的生命周期和类一样长,而一般成员是随着对象的存在而存在的
2.优先于对象存在 静态是先存在的,对象是后存在的。
3.被所有对象所共享
4.可以直接被类名调用
使用static时要注意:
1.静态方法只能访问静态成员
2.静态方法中不可以写this,super关键字,静态修饰的对象先于构造函数存在,
3.主函数是静态的
什么时候使用静态?
因为静态修饰的内容有成员变量和函数。那就分两步下手:
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态存在于堆内存中。
什么时候定义静态函数呢?
当功能内部没有访问到肺静态数据(对象的特有数据),那么该功能可以定义成静态的。
静态代码块。
格式:
static
{
//静态代码块中的执行语句。
}
特点:随着类的加载而执行,只执行一次,并优先于主函数。用于给类进行初始化的。
优先级 高----------------------------------->低
静态代码块---- 构造代码块----构造函数
class StaticCode
{
StaticCode()
{
System.out.println("b");
}
static//静态代码块,先于构造代码块和构造函数
{
System.out.println("a");
}
//构造代码块,先于构造函数
{
System.out.println("c");
}
StaticCode(int x)
{
System.out.println("d");
}
}
class StaticCodeDemo
{
public static void main(String[] args)
{
new StaticCode(4);
}
}
打印结果:a c d
实例变量(成员变量)和类变量(static修饰的变量)的区别:
1,存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
2,生命周期:
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
使用静态有哪些利弊?
利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。
弊端:生命周期过长。访问出现局限性。(静态虽好,但是只能访问静态。)
对象初始化过程:
Person p = new Person("zhangsan",20);
该句话都做了什么事情?
1,因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。
2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3,在堆内存中开辟空间,分配内存地址。
4,在堆内存中建立对象的特有属性。并进行默认初始化。
5,对属性进行显示初始化。
6,对对象进行构造代码块初始化。
7,对对象进行对应的构造函数初始化。
8,将内存地址付给栈内存中的p变量。
7.单例设计模式
单例设计模式:解决一个类在内存只存在一个对象。
想要保证对象唯一新需要三步:
1,为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象
2,还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
这三部怎么用代码体现呢?
1,将构造函数私有化。
2,在类中创建一个本类对象。
3,提供一个方法可以获取到该对象。
饿汉式
这个是先初始化对象。Single类一进内存,就已经创建好了对象。
class Single { private static Single s = new Single(); private Single(){} public static Single getInstance() { return s; } }
懒汉式
对象是方法被调用时,才初始化,也叫做对象的延时加载。Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
class Single { private static Single s = null; private Single(){}; public static Single getInstance()//双重判断 先判断是否为空,再判断锁,然后再判读是否为空 { if(s==null) { synchronized(Single.class) { if(s==null) s = new Single(); } } return s; } }
1.继承
1、什么是继承?
多个类中存在相同属性和行为时,将这些内容抽取到 单独一个类中,那么多个类无需再定
义这些属性和行 为,只要继承单独的那个类即可。多个类可以称为子类,单独这个类称为父类
超类。子类可以直接访问父类中的非私有的属性和行为。通过extends 关键字让类与类之间产生
或者继承关系。如:class SubDemo extends Demo{}
-------------------------------------------------------------------------------------------------
举个例子,比方说俩兄弟去露营,那这时候是不是要带帐篷,救生箱,睡袋什么的啊。但是哥俩
每个人都带一份是不是就显得累赘啊,这个时候父亲看到了:"说我也去,我拿帐篷,救生箱什么
的“。这样兄弟俩是不是就轻松了许多啊,不用每个人都拿那么多东西了,晚上睡觉的时候或者
需要救生箱的时候到父亲那拿就行了。 这个父亲就相当于父类,俩兄弟就是子类,父类中都是
子类所共有的,所以子类中就没必要再挨个定义了。只要不是父类私有的东西,子类都可以继承
过来用,父类与子类之间通过 extends 来实现继承。
-------------------------------------------------------------------------------------------------
通过继承可以使用其他类里的功能,但是千万不要为了使用其他类里的功能而随便继承,必须是
类与类之间存在所属关系才能够继承,就像是你露营的时候不可能别人拿了个游戏机你为了玩个
游戏,就随便认别人为父亲吧。像燕子麻雀等都能继承鸟类,但你不可能为了吃的功能去继承哺
乳动物那一类吧。所属关系是 is a才能继承。is a(谁是谁里面的一员)。
-------------------------------------------------------------------------------------------------
2、继承的特点是什么?
Java只支持单继承,不支持多继承。一个类只能有一个父类,不可以有多个父类。因为多继承容
易带来安全隐患:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一
个。但是java保留这种机制。并用另一种体现形式来完成表示。可以多实现接口。
class SubDemo extends Demo{} //正确
class SubDemo extends Demo1,Demo2...//错误
Java支持多层继承(继承体系),就类似父亲-儿子-孙子的关系
class A{}
class B extends A{}
class C extends B{}
定义继承需要注意:
不要仅为了获取其他类中某个功能而去继承
类与类之间要有所属( " is a " )关系才能继承,xx1是xx2的一种。
-------------------------------------------------------------------------------------------------
3.如何使用一个继承体系中的功能呢?
在使用一个继承体系中的功能时,可以看一下这个体系中父亲类的功能是什么,因为父亲类中
肯定是这个体系中最共性的东西,通过了解共性功能,就了解到这个体系的基本功能是什么了。
但是在具体调用时,要创建最子类的对象,为什么呢?
一是因为有可能父类不能创建对象,
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。
简单一句话:查阅父类功能,创建子类对象使用功能。
-------------------------------------------------------------------------------------------------
4.聚集关系
java类与类之间的其它关系:
聚集或者叫关联: 分为聚合和组合两部分
聚合:has a 一个班级由很多学生组成,学生与班级的关系就是组合。
组合:事物的联系程度更紧密,例如心脏是人身体中的一部分,班级少一个人行,人缺了心脏不行。
-------------------------------------------------------------------------------------------------
5.子父类中成员的特点
类中成员包括:1,变量。2,函数。3,构造函数。
a.那么子父类中的变量特点是什么呢?
继承的时候,当子类和父类之间存在相同的成员变量时,子类要访问本类中的变量,用this,
子类要访问父类中的同名变量,用super。比方说你本来有一个苹果,又从父亲那继承过来一
个苹果,这个时候你要吃的话,就是吃自己的(this)还是父亲的(super);
super 的使用和this的使用几乎一致。this代表的是本类对象的引用。super代表的是父类对象的引用。
b.子父类中函数的特点
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。
如同父类的函数被覆盖一样。就像孩子从父亲那继承过来说话的行为(函数),运行的时候,是
自己说话的功能,而不是父亲的。
这种情况是函数的另一个特性:重写(或覆盖)
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却
和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重
写功能内容。
比如说你写了一个类,类中的功能(函数)什么的都很符合当时的需求,但是过了一段时间功能
例的内容又改变了怎么办?不可能一遍又一遍的修改源代码,这时就可以再写一个类来继承这
各类,然后再写一个与父类方法名一样的函数,来更新函数的功能,这就用到了覆盖。
部分代码:
class Tel//比如这个程序的功能当时就能打电话发信息
{
void show()
{
System.out.println("打电话");
System.out.println("发信息");
}
}
//一段时间后,又需要加一个上网的功能,这时不可能去改源代码或重新写一个程序这时只
//需要再写个类继承上个类,然后重写父类的功能就行了,如果这个新功能用着不好,还可以
//接着在用父类的
class NewTel extends Tel//继承上个类
{
void show()//覆盖父类的方法
{
System.out.println("打电话");
System.out.println("发信息");
System.out.println("上网");
}
}
使用覆盖时需要注意哪些问题?
1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2,静态只能覆盖静态。
重载与重写的区别:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。就方法里面的内容不一样
c.子父类中的构造函数的特点。
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第
一行有一条隐式的语句 super();super():是访问父类中空参数的构造函数。而且子类中
所有的构造函数默认第一行都是super();
super关键字
1.super和this的用法相同
2.this代表本类应用,super代表父类引用
3.当子父类出现同名成员时,可以用super进行区分
4.子类要调用父类构造函数时,可以使用super语句。
-------------------------------------------------------------------------------------------------
为什么子类一定要访问父类中的构造函数呢?
因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如
何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造
函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
-------------------------------------------------------------------------------------------------
子类的实例化过程:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super();当父类中没有空参数的构造函数时,子类必须手 动通过super语句形式来指定要访问父类中的构造函数。子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
部分代码:
class Fu
{
int num ;//1.子类继承它之后,这个成员就能直接拿过去用了
Fu()
{
num= 60;//2.但是拿过去之前得先看下父类是怎么初始化的啊
System.out.println("fu run");
}
Fu(int x)
{
System.out.println("fu ...."+x);
}
}
class Zi extends Fu
{
Zi()
{
//3.如果父类已经初始化过num=60了,那再在子类中初始化就有点多余了不是
//num = 60
//4.所以子类初始化之前要先看下父类是怎么初始化的,默认是父类空参数的构造函数
super();
//super(4);5.但是也可以自己指定用父类的哪个构造函数,无论哪种都必须在第一行
System.out.println("zi run");
}
Zi(int x)
{
this();//6.子类中的构造函数也可用this语句访问本类的构造函数
//super();7.有6的话,就不用再写父类的构造函数了,因为this()里已经做了这个的动作了
System.out.println("zi..."+x);
}
}
class ExtendsDemo4
{
public static void main(String[] args)
{
Zi z = new Zi(0);
System.out.println(z.num);
}
}
-------------------------------------------------------------------------------------------------
6.final关键字
继承的缺点是破坏了封装性,人家本来一个类好好的,把里面的功能封装起来就是让你不用动
里面的功能直接用就行了,你这把人家继承过来之后,不光用还能改,这样是不是封装性就打
破了啊?要想不让别人改你的功能,可以用final来修饰类,这样别人就不能继承你了,如果一
个类被别人继承之后觉得里面的个别功能你能重写,但是有的你不能重写,只是就可以用final
来修饰那些不认别人重写的功能(函数)。
final : 最终的意思。是一个修饰符,
final的特点:
1,可以修饰类,函数,变量。
2,被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3,被final修饰的方法不可以被复写。
4,被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,有可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起
个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。
final常量:常量的书写规范所有字母都大写,如果由多个单词组成。单词间通过_连接。
如:public static final double PI = 3.14;
5,内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.继承(2)
7.抽象类
什么是抽象?
抽象就是不具体的东西,就是将很多事物的共性的本质的抽取出来。比如说狗和狼都属于
犬科,那么这个犬科就是抽象的,它具有狗和狼的共性,但是它很笼统。
什么是抽象类?
Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,
包含抽象方法的类就是抽象类。
举个例子: 比方说父亲要教两个孩子一个运动的功能,但是具体的是什么不教,两个孩子
从父亲那继承过来后,就要重写这个运动功能,一个孩子踢足球,一个孩子打篮球,那么
这个父亲就是抽象类,因为他将两个孩子的共性抽取出来了,并且孩子从父亲那继承过来
之后还必须自己重写这个功能,不然孩子也是抽象类了。
当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取。这时,只抽取功能
定义,而不抽取功能主体。
部分代码:
abstract class Fu//抽象类必须用abstract修饰,它不能new对象,比方说你new
{ // 了一个对象调用相面这个方法有意义吗?
abstract void sport();//抽象函数也必须用abstract修饰
}
class Zi1
{
void sport()//要使用父类的抽象方法必须复写抽象方法
{
System.out.println("踢足球");
}
}
class Zi2
{
void sport()
{
System.out.println("打篮球");
}
}
-------------------------------------------------------------------------------------------------
抽象类的特点:
1,抽象方法一定在抽象类中。
2.抽象方法只有方法声明,没有方法体,定义在抽象类中。
格式:修饰符abstract 返回值类型 函数名(参数列表) ;
3.抽象方法和抽象类都必须被abstract关键字修饰。
4.抽象类不可以用new创建对象。因为调用抽象方法没意义。
5.抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对
象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
-------------------------------------------------------------------------------------------------
抽象类与一般类没什么太大的区别,就是抽象类中比一般类多了个抽象方法,其他的
还该怎么写该怎么写,抽象类中可以有好多函数,但并不意味着抽象类里面的函数都得是
抽象的。另一个就是抽象类不能被实例化。
抽象类中可以不定义抽象方法,加abstract的目的仅仅是不让创建该类的对象(不常见)。
abstract 与final修饰的类的区别:
用final修饰的类不能被继承,而用abstract修饰的类一定要有子类,不然里面的抽象
方法没人复写留着有什么用。
-------------------------------------------------------------------------------------------------
abstract 与下面三个关键字不能共存:
final:被final修饰的类不能有子类,而被abstract修饰的类一定是一个父类。
private: 抽象类被私有了,不被子类所知,就无法被复写,而抽象方法出现的就是
需要被复写。
static:如果static修饰了抽象方法,那么连对象都省了,直接类名调用就可以了,
可是抽象方法运行没意义。
-------------------------------------------------------------------------------------------------
抽象类和接口中是否有构造函数?
抽象类中有,抽象类是一个父类,而子类继承父类的时候,子类的构造函数第一句一定是
父类的构造函数(super()),如果抽象类中没有,构造函数那子类不能实例化成功;
接口中没有构造函数,因为接口中都是方法都是抽象的,变量都是被final修饰的不能更
改的,而构造函数中可以有方法体,这与抽象函数相违背。然后类可以实现多个接口,若
多个接口都有自己的构造器,则不好决定子类的构造函数第一行怎么写。
-------------------------------------------------------------------------------------------------
9. 模板方法模式
什么是模版方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不
确定的部分,那么这时就将不确定的部分暴露出去。由该类的子类去完成。
部分代码:
abstract class GetTime//1.例如获取一个for循环遍历运行的时间 { public final void getTime()//2.获取时间的方法是确定的定义开始时间在定义结束时间 { long start = System.currentTimeMillis(); //3.但是求那种for循环的代码是不确定的,比如说你是求打印100个数用的时间呢还是求遍 //历出数组中最大值然后再打印的时间呢 runcode();//4.所以求那段代码运行的时间是不确定的 long end = System.currentTimeMillis(); System.out.println("毫秒:"+(end-start)); } public abstract void runcode();//5.所以把这段不确定的给暴露出去,让子类继承 } class SubTime extends GetTime// { public void runcode()//6.然后子类需要求谁的运行时间就复写5的功能把谁写进去 { for(int x=0; x<4000; x++) { System.out.print(x); } } } class TemplateDemo { public static void main(String[] args) { SubTime gt = new SubTime();//创建子类对象 gt.getTime(); } }
10.接口
什么是接口?
接口:可以认为是一个特殊的抽象类当抽象类中的方法都是抽象的,那么该类可以通过接
口的形式来表示。用interface用来定义接口。格式为 : interface 接口名 {}
接口中常见定义的有常量和抽象函数他们的默认表达方式为:
常量:public static final
方法:public abstract
接口中的成员都是public修饰。
接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全都
覆盖后,子类才可以实例化。否则子类是一个抽象类。
-------------------------------------------------------------------------------------------------
接口的特点:
1.对外暴露规则
2.降低耦合度 需要举例,如usb。pci,主板。插座。
3.接口是程序的功能扩展
4.接口直接可以用来多实现
5.类与接口之间是实现关系,而且类继承 类的同时可以多实现接口
6.接口与接口之间有继承关系,并且可以多继承。
注意:java中不支持多继承类但是可以多实现接口,另外接口继承接口,接口之间存在多继承,
类继承类的同时还能实现多个接口来进行功能扩展。
接口与接口之间存在多继承,类之间不能多继承的原因是,如果两个父类中有两个相同的函数,
方法体却不一样时,子类继承过来后,不知道该调用那个函数。而接口中因为都是抽象的方法,
没有方法主体,所以接口之间可以继承。
-------------------------------------------------------------------------------------------------
部分代码:
interface A { void methodA(); } interface B { void methodB(); void methodD();//类可以多实现的原因,B和D中都有methodD(),类D显现哪个都一样 } interface C //extends B,A接口之间可以多继承 { void methodC(); void methodD(); } class D implements B,C//类可以多实现接口 { public void methodA(){}//因为接口中成员都是public权限的,所以子类要想用的话 public void methodC(){}//权限得大于等于public public void methodB(){} }--------------------------------------------------------------------------------------------------------------------------------------------------------------
2.多态
1.什么是多态?
多态:可以理解为事物存在的多种体现形态。
部分代码:
abstract class Animal { abstract void eat(); } class Cat extends Animal//1.使用多态前提是类与类(接口)之间必须具有继承或实现关系 { //因为若没有继承关系2中Animal就不能接收它 public void eat() { System.out.println("吃鱼");//3.通常还要有覆盖关系 } public void catchMouse()//子类特有的方法 { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("吃骨头"); } public void kanJia()//子类特有的方法 { System.out.println("看家"); } } class DuoTaiDemo { public static void main(String[] args) { function(new Dog());//相当于Animal a = new Dog(); function(new Cat());//相当于Animal a = new Cat(); } public static void function(Animal a)//2.而使用Animal可以接收所有它的子类 { a.eat();//4.如果没有覆盖关系,把它接收过来又有什么用呢 } }3.多态--转型
上面代码是通过多态使用父类中的方法。因为子类中都复写了,所以可以通过把父类当参数传
进来,然后接收它的子类,再调用父类的方法(其实就是子类的方法因为复写)就行了。
-------------------------------------------------------------------------------------------------
但是怎么通过多态来调用子类中特有的方法呢?
Animal a = new Cat();接收一个猫类型的话,猫类型提升,向上转型就像byte提升为int
如果想要调用猫的特有方法时,如何操作?
强制将父类的引用。转成子类类型。向下转型。
Cat c = (Cat)a;
c.catchMouse();
千万不要出现这样的操作,就是将父类对象转成子类类型。如下:
Animal a = new Animal();
Cat c = (Cat)a;
我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
-------------------------------------------------------------------------------------------------
如上面的代码:
Animal a = new cat();//类型提升 向上转型了
但是如和访问cat类中特有的方法呢?
这个时候如果使用a.catchMouse();因为a被提升为动物类型了,那动物有很多种,不一定指的就是猫
instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型)
1,多态的体现
父类的引用指向了自己的子类对象。例如:动物 x = new 猫();
2,多态的前提
必须是类与类之间有关系。要么继承,要么实现。通常还有一个前提:存在覆盖。
3,多态的好处
多态的出现大大的提高程序的扩展性。
4,多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5,多态的应用
-----------------------------------------------------------------------------------
4.多态中成员的特点
多态中成员函数的特点:编译看左边运行看右边
成员变量的特点:无论编译还是运行都看左边
静态成员函数的特点:编译或运行都看左边
-----------------------------------------------------------------------------------
部分代码:
class Fu { int num = 5; void show1() { System.out.println("Fu show_1"); } void show2() { System.out.println("Fu show_2"); } static void show4() { System.out.println("Fu show_4"); } } class Zi extends Fu { int num = 8; int x=3; void show1() { System.out.println("Zi show_1"); } void show3() { System.out.println("Zi show_3"); } static void show4() { System.out.println("Zi show_4"); } static void show5() { System.out.println("Zi show_5"); } } class DuoTaiTeDian { public static void main(String[] args) { Fu f = new Zi(); //如果是f.Show3();则编译不通过因为父类中没有f.Show3();运行结果则是累类中的"Zi show_1"; f.show1(); //如果是f.x则编译不通过,因为看左边父类中无X成员变量,运行结果也是5,因为运行也看左边父类中有num=5; System.out.println(f.num); //因为左边父类中无show5(),所以编译不通过。如果为f.show4(),则打印结果为"Fu show_4"; f.show4(); } }5.object类equal
Object:是所有对象的直接后者间接父类,传说中的上帝。所以该类中定义的肯定是所有对象都
具备的功能。
Object类中已经提供了对对象是否相同的比较方法。如果自定义类中也有比较相同的功能,没
有必要重新定义。只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。
使用运算符"=="与equals()方法都可以进行对象的比较但是两者是有区别的?
当使用关系运算符"=="比较两个对象时,是比较两个对象使用的内存地址和内容是否像相同,
如果两个对象使用的是同一个内存地址,并且内容相同,则结果返回true,否则结果为false。
当使用equals()方法比较两个对象时,则是比较两个对象的内容是否相同,而与内存地址无关,
如果两个对象的内容相同,则结果为true,否则结果为false。
部分代码:
class EqualDemo { public static void main(String[] args) { String str1 = new String("hello"); String str2 = new String("hell0"); String str3 = str2; //用“==”比较str1与str2 System.out.println("str1与str2的比较结果为:"+(str1==str2)); //用“==”比较str2与str3 System.out.println("str1与str2的比较结果为:"+(str2==str3)); //用equals方法比较str1与str2 System.out.println("str1与str2的比较结果为:"+str1.equals(str2)); //用equals方法比较str2与str3 System.out.println("str1与str2的比较结果为:"+str2.equals(str3)); } }---------------------- android开发、java培训、期待与您交流! ----------------------
相关推荐
### 黑马_Linux网络编程-网络基础-socket编程-高并发服务器 #### 知识点概述 本篇文章旨在深入解读“黑马_Linux网络编程-网络基础-socket编程-高并发服务器”相关的核心概念和技术要点,包括网络基础知识、常用...
黑马程序员__移动商城项目实战 包括黑马程序员乐淘商城实战和慕课React+Antd
公式指标,黑马起爆,有助于判断什么时候可以入手
黑马程序员_毕向东_Java基础视频教程第05天-01-面向对象(概述).avi
在下载和比较了大量同类书籍后不得不承认孙卫琴老师的这本书循序渐进由浅入深是最好的Java入门教程,同时它的...本资源包含《Java面向对象编程》的电子书,实例源代码,课后题答案等可以说是当前该书最全的资源了。。。
黑马程序员,C++核心编程
在《黑马程序员 - Java基础教学 - 05 - 面向对象(1)》文档中,详细讲解了面向对象的基本概念及其在Java中的应用。 ### 面向对象与面向过程 面向对象和面向过程都是解决问题的思维模式,但面向对象更注重将功能和...
6. HQL(Hibernate Query Language):学习Hibernate特有的查询语言,它可以像SQL一样操作对象,但更面向对象,避免了直接写SQL的复杂性。 7. Criteria查询:除了HQL,Hibernate还提供了Criteria API,它提供了一种...
1. **面向对象编程**:C++是面向对象的编程语言,它支持类、对象、封装、继承和多态等核心概念。学习这一阶段的内容,你需要理解如何定义和使用类,以及如何通过对象来操作数据和实现功能。 2. **类与对象**:类是...
在【标签】"Java加强"中,我们可以推断这门课程不仅覆盖了Java的基础知识,还可能涉及了一些进阶主题,比如面向对象编程的深入理解、异常处理、多线程、集合框架的高级用法、IO流和NIO、网络编程等,以提升学员对...
黑马程序员_张孝祥_Java多线程与并发库,老师讲的非常仔细,老师很有耐心.欢迎大家下载学习.
【标题】:“B站《黑马程序员匠心之作-C++教程从0到1入门编程,学习编程不再难》 配套笔记” 【描述】提及的是一个针对初学者的C++教学资源,来自B站上的视频课程“BV1et411b73Z”。这门课程的特色在于提供了一份...
Java的核心在于面向对象编程(OOP)。毕向东的源码将展示类的定义、对象的创建、封装、继承和多态等概念。类是对象的蓝图,而对象则是程序的基本运行单元。理解如何通过类来组织代码,并利用继承和多态性实现代码的...
C++黑马程序员学习资料,附赠《InterviewGuide第四版By阿秀》、《LeetCode刷题手册》、《背包问题九讲》、《算法图解》pdf版本,三个基础课程文档手册及三个实验项目,由简到繁分别为《通讯录管理系统》、《职工管理...
5. **第4阶段实战-基于多态的企业职工系统资料**:在这个阶段,学习者将利用多态性来构建一个企业职工管理系统,进一步巩固面向对象编程的应用,同时提升问题解决能力。 6. **第5阶段-C++提高编程资料**:这部分...
本套黑马程序员的Java函数式编程视频教程涵盖了Lambda表达式、Stream流以及函数式编程的核心概念,旨在帮助学习者全面掌握这一现代编程技术。 Lambda表达式是Java 8引入的关键特性,它允许我们以更简洁的方式定义...
看pytorch代码看不懂,需要补面向对象的基础,(用B站搜黑马程序员Python,其中的第二部分)看完视频课(对照这个PPT),再回来看代码,会豁然开朗
标题中的“heima_ugo_xiaochengxu_黑马训练营_微信小程序_小程序支付_VantWeapp商城”揭示了这是一个关于微信小程序开发的项目,由黑马训练营提供教学支持,特别关注了商城功能、微信登录和微信支付的集成,并且使用...
1.1 ORM概述:ORM是Object-Relational Mapping的缩写,它提供了一种将面向对象的编程模型与关系型数据库之间的映射机制,使得开发者可以使用面向对象的方式来操作数据库,避免了繁琐的SQL编写。 1.2 Hibernate概述...
3. **面向对象编程**:深入讲解Java的核心特性——面向对象编程,包括类的定义、对象的创建与使用、封装、继承和多态等概念。 4. **数组和集合框架**:介绍数组的使用,以及ArrayList、LinkedList、HashSet、...