java基础 java面向对象,抽象类,接口,变量

java基础



java 面向对象

java特性(面向对象概述)

核心:面向过程
优点:简单性.解释性.面向对象.高性能 多线程 跨平台 开源
三大特征:继承,封装,多态

面向对象三大特性

  • 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
  • 封装:把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
  • 继承:简单说就是子类继承了父类中的非私有属性和可以继承的方法,然后子类可以继续扩展自己的属性及方法。
    关于继承如下 3 点请记住:
    ①子类拥有父类非 private 的属性和方法。
    ②子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
    ③子类可以用自己的方式实现父类的方法
  • 多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
    在Java中有两种形式可以实现多态:
    继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)

什么是多态机制

多态就是指,程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用,在编程时并不确定,而是在程序运行期间才确定

即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定,因为在程序运行时才确定具体的类

这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性

多态分为编译时多态和运行时多态其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性,重写的方式

Java语言是如何实现多态的

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

重载(Overload)和重写(Override)的联系与区别

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;
重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分

向上转型与向下转型

要转型,首先要有继承。继承是面向对象语言中一个代码复用的机制,简单说就是子类继承了父类中的非私有属性和可以继承的方法,然后子类可以继续扩展自己的属性及方法
向上转型: 通过子类对象 (小范围) 实例化父类对象 (大范围) , 这种属于自动转换

Father f = new Son();

向下转型: 通过父类对象 (大范围) 实例化子类对象 (小范围) , 这种属于强制转换

Son s = (Son) f;

总结:

向上转型注意地方和向上转型意义

需要注意的地方
向上转型后,子类单独定义的方法会丢失(父类并不知道子类定义的新属性与方法)
父类引用可以指向子类对象,但是子类引用不能指向父类对象
如果子类中重写了父类的方法,那么调用这个方法的时候,将会调用子类中的方法

向上转型的意义
减少重复代码
实例化的时候可以根据不同的需求实例化不同的的对象,实现参数统一化
假如现在我们写一个getMessage()方法,用来接收不同子类的对象,然后调用它们的print()方法输出各个子类对象的相关信息,那么此时,有多少个子类,我们就需要写多少个方法,分别用来接收各个不同子类的对象

class Student extends Person {
     public void getMessage (Student stu) {
    	 stu.print();
     }
  }   
class Tescher extends Person {
     public void getMessage(Tescher ter) {
    	 ter.print();
     }
   }

当我们使用了向上转型之后,就可以只写一个fun()方法来接收所有Person类的子类对象,这样就实现了参数的统一化

public void getMessage(Person per) {
    	per.print();
    }

面向对象五大基本原则是什么(可选)

  • 单一职责原则SRP(Single Responsibility Principle)类的功能要单一,不能包罗万象,跟杂货铺似的
  • 开放封闭原则OCP(Open-Close Principle)一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改确是不行的
  • 里式替换原则LSP(the Liskov Substitution Principle LSP)子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活
  • 依赖倒置原则DIP(the Dependency Inversion Principle DIP)高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的
  • 接口分离原则ISP(the Interface Segregation Principle ISP)设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多

类与接口

抽象类

抽象:笼统、模糊、不具体 abstract

抽象类的特点

①方法只有声明没有实现时(没有方法体),该方法就是抽象方法,需要被abstract修饰,抽象方法必须定义在抽象类中,该类也必须被abstract修饰
②抽象类不可以被实例化(不可以被new) 因为调用抽象方法没有任何的意义
③抽象类必须由其子类覆盖了所有的抽象方法后,该子类才可以实例化
否则,这个子类还是抽象类
④抽象类和抽象方法非常适合做"系统的分析和设计的工具"

抽象类中有构造器吗

有,可以给子类对象进行初始化

抽象类可以不定义抽象方法吗?

可以

  abstarct class Demo{
  	void show1(){}
  	void show2(){}
  }
抽象类一定是父类

一定,需要子类覆盖其所有的抽象方法后才可以实例化

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

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

抽象类能使用 final 修饰吗

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生
矛盾,所以 final 不能修饰抽象类

abstract不可以和哪些关键字共存?

private
final
static

接口(interface)

接口表现形式

interface {}
接口中成员的修饰符是固定的:
成员常量:public static final
成员方法:public abstract

类与接口之间实现关系

类与类是继承关系,类与接口之间实现关系
接口不可以实例化:
只能由实现了接口的子类覆盖了接口中所有的抽象方法后,该子类才可以实例化,否则该子类还是一个抽象类,接口的出现将"多继承"通过另外一种形式体现出来,即"多实现"

接口的特点

1)接口是一个特殊的抽象类(纯抽象类)
2)接口是程序的功能扩展
3)接口的出现降低耦合性
4)接口可以用来多实现
5)类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
6)接口的属性默认是常量,而且是public static final修饰的
7)接口中的方法一定是public abstract修饰的(默认的,可以不写)
8)接口和接口之间可以有多继承关系

抽象类和接口的对比

抽象类:抽象类是用来捕捉子类的通用特性的。将类中共同的内容剥离出来
接口:接口是抽象方法的集合。

从设计层面看,抽象类是对类的抽象,是一种模板设计,接口是接口是行为的抽象,是一种行为的规范
相同点

  • 接口和抽象类都不能实例化(具体的对象实例没有意义)
  • 都位于继承的顶端,用于被其他类实现或继承(抽象类被继承,接口被实现)
  • 都包含抽象方法,其子类都必须覆写这些抽象方法

不同点
在这里插入图片描述
在接口和抽象类的选择上,必须遵守这样一个原则:

  • 行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
  • 选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能

实际项目中常用的写法

Interface A{
	void method a;
}
abstract B implment A{
	protect method b1;
	protect method b2;
}
class C extends B{
@override
	........
}

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

new关键字,new创建对象实例(对象实例在堆内存中)

对象引用(比作绳)指向对象实例(比作气球)(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)

变量与方法

成员变量与局部变量的区别有哪些

变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域

  • 成员变量:方法外部,类内部定义的变量
  • 局部变量:类的方法中的变量。

成员变量和局部变量的区别
作用域

  • 成员变量:针对整个类有效。
  • 局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

存储位置

  • 成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
  • 局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语
    句结束后,就自动释放。

生命周期

  • 成员变量:随着对象的创建而存在,随着对象的消失而消失
  • 局部变量:当方法调用完,或者语句结束后,就自动释放。

初始值

  • 成员变量:有默认初始值。
  • 局部变量:没有默认初始值,使用前必须赋值。

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

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

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

super()默认存在,隐藏
帮助子类做初始化工作

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

主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法,在子类构造器的第一行有一个默认隐式语句super()子类中所有的构造器默认都会访问父类中空参数的构造器

class Son extends Father{
	public Son() {
	/*
	 *在子类构造器的第一行有一个默认隐式语句super(),子类中所有的构造器默认都会访问父类中空参数的构造器
	*/
	System.out.println("son");
	}

构造方法(构造器)constructor
特点:
①构造器的名称与类名相同
②不用定义返回值类型,但不能用void声明构造函数
③没有具体的返回值
作用:
给对象进行初始化
注意:
①默认构造器的特点
②多个构造器是以"重载"的形式来体现的

静态变量与普通变量(非静态变量)区别

  • static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
  • 还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化

静态变量和实例变量区别

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

静态变量和成员变量的区别

①两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的被回收而释放
静态变量随着类的加载而存在,随着类的消失而消失
②调用方式不同
成员变量只能被对象调用
静态变量可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式调用
③别名不同
成员变量也称为实例变量
静态变量也称为类变量
④数据的存储位置不同
成员变量存储在堆内存的对象中,所以也叫做对象的特有数据
静态变量存储在方法区中的静态方法区中,所以也叫做对象的共享数据

静态方法和实例方法有何不同?

静态方法和实例方法的区别主要体现在两个方面:
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而
实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访
问实例成员变量和实例方法;实例方法则无此限制

在什么时候用静态方式

①静态变量
当分析对象中所具备的成员变量的值都是相同的时候,这时这个成员变量可以被静态修饰符
②静态方法
方法是否用静态,就参考一点,该方法的功能是否有访问到对象的特有数据,如果有就不能定义成
静态的,如果没有就可以定义成静态方法

静态方法和实例方法有何不同?

静态方法和实例方法的区别主要体现在两个方面:

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

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

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

什么是方法的返回值?返回值的作用是什么?

方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!

静态变量 静态代码块,构造代码块,构造器,它们执行的先后顺序

父类结构
 ①静态变量
 ②成员变量
 ③静态代码块
 ④构造代码块
 ⑤构造器
子类 继承父类 其结构
①静态变量
②成员变量
③静态代码块
④构造代码块
⑤构造器

执行的先后顺序

父类-静态变量
父类-静态初始化
子类-静态变量
子类-静态初始化
父类-成员变量
父类-构造代码块
父类-构造器
子类-成员变量
子类-构造代码块
子类-构造器

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值