Java基础知识——面向对象

面向对象:

面向对象和面向过程的区别:

面向过程:如单片机,嵌入式开发,Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
	优点:性能比面向对象高,因为类调用时需要实例化,开销较大,比较消耗资源
	缺点:不易维护,不易复用,不易扩展
面向对象:
	优点:易维护,易复用,易扩展,由于面向对象有封装,继承,多态的特性,可以设计出低耦合的系统
		使系统更加灵活,易于维护。
	缺点:性能比面向过程低。
面线对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象了。

面向对象的三大特征:

封装:把一个对象的属性私有化,同时提供一些可以被外界访问的方法,如果属性不想被外界访问,就不提供方法。
继承:继承是使用已存在的类创建新类的技术,新类的定义可以增加新的数据或新的功能,也可以使用父类的功能,
	继承的三个重点:
	1.子类拥有父类非private的属性和方法。
	2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
	3.子类可以用自己的方法实现父类的方法。
多态:所谓多态就是指程序中定义的应用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,
	而是在运行期间确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类的方法,
	必须在程序运行期间才能确定。
	java中实现多态的两种形式:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中的同一方法)。
	方法重载(overload)实现的是编程时的多态性(也称为前绑定)
	方法的重写(override)实现的是运行时的多态性(也称为后绑定)

多态的实现:java实现多态有三个必要条件:继承,重写,向上转型。

继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋值给父类对象,只有这样该引用才能具备能调用父类方法和子类方法

面向对象的五大基本原则:

1.单一职责原则SRP(Single Responsibility Principle)
	类的功能要单一,不能包罗万象。
2.开放封闭原则OCP(Open-Close Principle)
	一个模块对于拓展是开放的,对于修改是封闭的,支持增加功能,不支持修改功能。
3.里氏替换原则LSP(the Liskov Subsititution Principle)
	子类可以替换父类出现在父类能够出现的任何地方。
4.依赖倒置原则DIP(the Dependecy Inversion Principle)
	高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象,
5.接口分离原则ISP(the Interface Sefregation Principle)
	设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好,将多个功能分成不同的接口。

类与接口:

抽象类与接口的对比:
	抽象类是用来捕捉子类的通用特性。接口是抽象方法的集合。
	从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
相同点:
	接口和抽象类都不能实例化。
	都位于继承的顶端,用于被其他实现或继承。
	都包含抽象方法,其子类都必须覆写这些抽象方法。
不同点:
	1.抽象类使用abstract关键字声明,接口使用interface声明。
	2.抽象类的子类使用extend关键字继承抽象类,接口子类使用implement关键字来实现接口。
	3.抽象类有构造器,接口不能有构造器。
	4.抽象类中的方法是任意访问修饰,接口方法默认修饰符是public。并且不应许定义为private或者protected。
	5.一个类最多只能继承一个抽象类,但可以实现多个接口。
	6.抽象类的字段声明可以是任意的,接口的字段默认都是static和final的。
Java8中接口中引入默认方法和静态方法,一次来减少抽象类和接口之间的差异。
现在,可以为接口提供默认实现的方法,并不需要强制子类类实现它。
接口和抽象类各有缺点,在接口和抽象类的选择上,必须遵循这样一个原则:
	1.行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
	2.选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。

普通类和抽象类有哪些区别:

普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以实例化。

抽象类能使用final修饰吗:

不能,final修饰的类不能被继承。

创建一个对象用什么关键字?对象实例和对象引用有什么不同?

1.new关键字。new关键字对象创建的实例在堆内存中。
2.Demo demo = new Demo();
	1)右边的new Demo,是以Demo类为模板,在堆空间里创建一个Demo对象。
	2)末尾的()意味着,在对象创建后,立即调用Demo的构造函数,对刚生成的对象进行初始化。
	3)左边的Demo demo创建了一个Demo类引用变量,它存放在栈空间,也就是用来指向Demo对象的对象引用。
	4)'='操作使对象引用指向刚创建的那个Demo对象。

变量与方法:

成员变量与局部变量的区别:

	变量:在程序执行过程中,在某个范围内其值可以发生改变的两。本质上,变量时内存中的小块区域。
	成员变量:方法外部,内部定义的变量
	局部变量:类的方法中的变量。
作用域:成员变量针对整个类。局部变量只在某个范围内有效。
存储位置:成员变量随着对象的创建而存在,对象的消失而消失,存储在堆内存中。
	局部变量在方法被调用或者语句被执行的时候存在,存在栈内存中。使用完就释放。
声明周期:成员变量的声明周期随着对象的创建而存在,随着对象的消失二消失。
	局部变量当方法调用完,或者语句结束后,就自动释放。
初始值:
	成员变量有默认初始值,局部变量没有默认初始值,使用前必须赋值。
使用原则:就近原则:首先在局部范围内找,有就是用;没有就接着在成员位置找。

在Java中定义一个不做事且没有参数的构造方法的作用:

Java程序在执行子类构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”,
因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中有没有用super()来调用父类中特定的构造方法,则编译时会报错
,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类中加上一个不做事且没有参数的构造方法。

在调用子类的构造方法之前会调用父类没有参数的构造方法,其目的是?

帮助子类做初始化工作。

一个类的构造方法的作用是什么,若没有声明构造方法,程序能正确执行吗?

主要作用是完成对类对象的初始化工作。可执行,因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

构造方法有哪些特性:

名字与类名相同,没有返回值,但不能用void声明构造函数,生成的类对象时自动执行,无需调用。

静态变量和实例变量的区别:

静态变量:静态变量由于不属于任何实例对象,属于类,所以在内存中只会存在一份,
	在类的加载中,JVM只为静态变量分配一次内存空间。
实例变量:每次创建对象,都会分配内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有积分成员变量。

静态变量与普通变量的区别:

1.在外部调用静态方法时,可以使用(类名.方法名)的方式,也可以使用(对象名.方法名)的方式。
	也就是说,调用静态方法无需创建对象。
2.静态方法在访问本类成员时,只允许访问静态成员,而不允许访问实例成员变量和实例方法,实例方法则没有限制。

在一个静态方法内调用一个非静态成员为什么是非法的?

由于静态方法可以不通过对象进行调用,因此在静态方法中,不能调用其他非静态变量,也不可以访问非静态成员变量。

内部类:

什么是内部类?

在Java中,可以将一个类的定义放在另外一个类的内部,就是内部类,定义方式与其他属性定义方式一样。

内部类的分类:

	内部类可以分为四种:成员内部类,,局部内部类,匿名内部类,静态内部类。
静态内部类:定义在类内部的静态类。静态内部类可以访问外部所有的静态类,而不可访问外部的非静态类。
成员内部类:定义在类的内部的非静态类。可以访问外部类的所有变量和方法。
局部内部类:定义在方法中的内部类,就是局部内部类。
匿名内部类:没有名字的内部类,日常开发中使用的比较多。

匿名内部类的特点:
匿名内部类必须继承一个抽象类或者事项接口。
匿名内部类不能定义任何静态成员和静态方法。
当所在的方法的形参需要被匿名内部类使用时,必须声明为final
匿名内部类不能是抽象的,他必须要实现继承类或者实现接口的所有抽象方法。
	new 类/接口{ 
	  //匿名内部类实现部分
	}
内部类的优点:
1.一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据
2.内部类不为同一包的其他类所见,具有很好的封装性。
3.内部类有效地实现了“多重继承”,优化java单继承的缺陷。
4.匿名内部类可以很方便的定义回调。
内部类的应用场景:
1.一些多算法场合。
2.解决一些非面向对象的语句块
3.适合使用内部类,使得代码更加灵活和富有扩展性。
4.当某个类除了它的外部类,不在被其他类调用时。
局部内部类和匿名内部类访问局部变量时,为什么变量必须要加上final:
是因为声明周期不一样,局部变量直接存储在栈中,访问执行结束后,非final的局部变量就会被销毁,
而局部内部类对局部变量的引用依然存在,如果继续调用就会出错。加上final,可以确保局部内部类
使用的变量与外层的局部变量分开,解决了这个问题。

重载与重写:

构造器(constructor)是否可以被重写(override):

构造器不能被继承,因此不能被重写,但可以被重载。

重载(overload)与重写(override)的区别:重载的方法能否根据返回的类型进行区分

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,
后者实现的是运行时的多态性。

重载:发生在同一个类中,参数名相同参数列表不同(参数类型,个数,顺序),与方法返回值和访问修饰符无关,
	及重载的方法不能根据返回类型进行区分。
重写:发生在父类中,方法名,参数名,参数列表必须相同,返回值小于等于父类,抛出异常小于等于父类,
	访问修饰符大于等于父类(里氏代换原则);如果父类访问修饰符为private则子类中就不是重写。
	
简单理解:重载:一个类中多个方法同名,参数列表不同。
		 重写:子类重写父类方法,参数名参数都一样。

代码块的执行顺序

遵循:
静态优先,普通代码随后,构造函数次之;不管是静态还是普通代码或构造函数,都是父类先于子类。
父类静态代码块 ->子类静态代码块 ->父类非静态代码块 -> 父类构造函数 -> 子类非静态代码块 -> 子类构造函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值