Java面向对象、抽象类、接口、多态、匿名内部类、Lambda表达式

 

封装:隐藏细节,暴露功能。

封装用访问修饰符实现。

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

如:成员变量用private修饰,提供对应的set、get方法。

封装的好处:

通过方法来控制对成员变量操作,提高代码安全性。

把代码用方法进行封装,提高代码复用性。

 

继承:

子类拥有父类非 private 的属性、方法。

子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

子类可以根据自己的需求重写父类的方法。

Java 支持单继承,不支持多继承,但是多层继承(链式继承)。


 

 

多态:同一个类中的同一个方法,根据不同的调用产生多种状态的现象。

多态的两种实现方式:方法重写,方法重载。

重载:方法名相同,参数列表不同。参数列表不同包括:参数个数、参数类型、不同类型参数的顺序不同。

static修饰的方法没法被重写,如果在子类定义一个一模一样的static方法,现象上根重写一样,实际上是子类自己定义的一个方法,不是重写。用父类名.调用父类的static方法。

final修饰的方法不能被重写。

 

类:

类是对现实生活中一类具有共同属性和行为的事物的抽象。

类是对象的数据类型。

属性:对象有什么特征

方法:对象能干什么

 

访问修饰符

public:所有类都能访问。

private:只能在类内访问。

protected:子类和同一个包下的类才能访问。

friendly:不写的话默认是friendly,在同一个包的类可以访问,不同包不能访问。

 

在子类内部调用super表示父类,子类构造函数第一条语句一定是super(),表示调用父类的空参构造。 如果显式调用super(args)则调用父类有参构造不调用空参构造,不显式调用则默认调用父类空参构造,如果父类里没有空参构造,会报错。

 

子类可以自动转成父类,父类需要强制转成子类。

强转的前提:父类实例是一个子类的实例,如Father f = new Child(); Child c = (Child)f; 如果不是会报错。

因为子类转成父类只需要屏蔽掉子类扩展的特有的方法和属性,而父类转成子类则没法凭空造出那些方法和属性,因此不能转。

子类对象转成父类对象后,子类特有的方法和属性将不能访问,但是重写的方法可以访问;再把该父类对象强转成子类对象后,子类特有的方法和属性依然可以访问。

 

垃圾回收:

在堆内存中的对象或数组,其地址通过任何方式都不能被找到,就会被判定为内存中的垃圾。

Java的垃圾回收器在空闲的时候会自动清理内存中的垃圾。

System.gc();调用JVM垃圾回收机制,实际上只是通知JVM有垃圾需要回收,是否要回收,什么时间回收,是由JVM自己判断的,因为回收垃圾也是消耗资源的,不是有一点垃圾就回收。

 

成员变量:

类中的位置:类中方法外

内存中的位置:堆内存(对象在堆中)

生命周期:随着对象的产生而产生,随着对象的消失而消失

初始值:有默认初始值

局部变量:

类中的位置:方法内,

内存中的位置:栈内存(方法执行时会进栈)

生命周期:随着方法的调用而产生,随着方法调用完毕而消失

初始值:没有默认初始值,必须先赋值才能使用

 

private、set、get的意义:

如果直接访问对象的成员变量,可能造成非法操作,如stu.age = -10

因此把age用private修饰,在类内才能访问,对外提供set、get方法

虽然用户也能输入setAge(-10),但是在set方法内我们就可以进行逻辑判断了,检查到非法赋值就提示错误

 

标准的JavaBean:

所有属性用private修饰,提供public的setter、getter方法

JavaBean里不要用int,用封装类Integer,因为未赋值==null好判断,而且null在页面上体现是空,不显示,而int未赋值==0,在页面上

 

什么时候用this:

解决局部变量和成员变量同名导致成员变量隐藏
 

 

静态static:

普通成员在类new的时候才能实例化,而静态成员在类加载的时候就完成实例化。

将.class文件从硬盘读取到内存的过程,叫做类加载,发生在代码中出现类名的时候。

静态成员在内存中只分配一块内存,所有实例共享此块内存。

静态成员有静态属性、静态方法、静态代码块static{  ……  }

静态代码块必然是在构造函数前运行,只运行一次,在类加载时。

静态属性、静态方法(类属性、类方法)只能用类名.直接调用,不能用实例.调用。静态方法中只能访问静态变量不能访问普通变量,因为静态方法、静态变量在类加载的时候就有了,这时候普通变量还没有,直到new的时候才有,根本访问不到。

静态方法定义成public,那么可以在外部用类名.调用,静态方法定义成private,那么只能在本类内部调用。

static不能修饰类。

 

final:

final修饰的常量只能赋一次值,赋完值就不可以改变。

常量一般的定义方式:static final STU_SEX = 0;定义时直接初始化。

或static final STU_SEX;    static{  STU_SEX = 0;  } 在静态代码块中初始化。

final修饰的方法,在子类里不能重写。

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

 

this:

this指当前调用本方法的对象,this( )是当前类的构造方法。

this( )和super( )如果显式调用,都必须放在构造方法的第一句,因此二者不能共存。

 

为什么子类的构造方法会先调用父类的构造方法:

子类对象有可能用到父类的数据,因此子类对象初始化前一定要先完成父类对象初始化,而怎样完成对象初始化:构造方法。因此子类在初始化之前一定要访问到父类的构造方法,完成父类初始化。系统在每一个构造方法的第一句默认隐藏一句super();

 

package包:在最宽泛的范围内实现了封装。

package必须是.java文件的第一句有效代码。

 

 

抽象类、抽象方法:

抽象类只是为抽象方法提供了一个存活的环境。

抽象方法没有方法体,有abstract修饰符,类也要有abstract修饰符。

抽象类不能创建实例。

抽象类的子类,要么重写父类所有的抽象方法,要么子类自己也变成抽象类。

抽象类可以没有抽象方法,但是有抽象方法的类一定是抽象类。

 

可以用抽象类对象接收一个实现了他的子类实例。其实就是父类引用指向子类对象,多态。

 

用一个匿名类实现了抽象类并创建了匿名类对象,用抽象类引用接收。实际上new的是抽象类的子类。

 

 

设计模式:就是一套良好的编码风格。

抽象类就是模板模式的应用。

 

接口:所有方法都是抽象方法。

接口是类的功能模板,是类的说明书。

接口的作用:强内聚,低耦合。模块化开发。

声明规则一般用接口来声明。

接口不能实例化,要有一个类来实现它,这个类叫该接口的实现类。实现类要么实现所有抽象方法,要么也是抽象类。

继承只支持单继承,但是实现支持多实现,多个接口按逗号隔开。

一个类实现的多个接口里有同名的抽象方法不会造成冲突,因为这几个接口的抽象方法都没有方法体,在实现类里只要实现一次就相当于都实现了。

注意:

接口中的成员变量只能是常量,因为系统默认为接口成员变量添加public static final修饰符。因此接口的成员变量可以被实现类直接访问,可以通过接口.调用,赋值后不可以修改。

接口中的成员方法只能是抽象方法,因为系统默认为接口成员方法添加public abstract修饰符。实现类重写方法也必须是public,否则报错。

 

JDK8及以后版本,接口中可以定义非抽象方法。

改版的原因:解决接口升级的问题。假如有一天,某个接口要升级,增加四个方法,那么它的所有实现类都要改,都要去实现这四个方法。这就造成了麻烦。

因此JDK8以后可以在接口中定义有方法体的方法,必须用default修饰,系统默认添加public修饰符。

default方法的作用:丰富接口功能的同时,又不需要修改子类代码。

实现类实现接口后,可以调用default方法,不强制重写default方法,可以重写,重写后不能带default,但一定要带public。

若实现类实现了两个接口有同名default方法,那么实现类必须重写default方法。(冲突了,那我谁的都不用,我用我自己的)

 

JDK8及以后,接口中可以定义静态方法。

不能带default。

注意:

实现类实现的两个接口有同名静态方法,会引起冲突吗——不会,因为接口的静态方法只能通过接口名.调用,就算实现了两个接口有同名静态方法,实现类根本调用不了,也就不会有冲突。

 

JDK9及以后版本,接口可以定义私有方法。

因为接口允许出现方法体之后,就自然而然涉及到代码复用问题,因此在接口里定义私有方法,只能在接口内部调用,以便提高接口default方法、static方法的代码复用性。

 

一个类继承了父类又实现了接口,父类和接口里有同名方法,那么子类调用该方法时优先调用父类中的方法。

接口与接口之间可以继承,且支持多继承,子接口继承了两个父接口,若两个父接口有同名方法,则子接口必须重写该方法,重写成default。实现类实现了子接口后,必须实现接口和父接口的所有抽象方法。

 

多态

向上转型:父类引用指向子类对象。向下转型:把刚才的父类引用再转为子类引用。

多态使用子类特有功能:向下转型,强转。Child c = (Child)f; 强转完就可以调用子类特有方法。

 

向下转型的风险:

如果方法的参数是Animal,接收了一个Dog,方法内部向下转型转成Cat,运行时会报错ClassCastException类型转换异常。

解决方法:用instanceof判断:

 

内部类

私有内部类:

如果内部类被私有化,那么不能在外部类以外被创建和调用,想调用的话,只能在外部类中创建方法,访问内部类,在外部类外面创建外部类对象.方法访问内部类。

静态内部类:外面可以访问,但实例化的方式有所变化:

调用静态内部类的静态方法:外部类名.内部类名.方法名()

局部内部类:

匿名内部类:将继承/实现,方法重写,创建对象放在一步执行。匿名内部类new的是子类/实现类对象。

如果接口中有多个方法,可以用多态+内部类的方式调用多个方法。

匿名内部类的应用场景:当方法的形参是接口或抽象类,可以将匿名内部类作为实参传入方法中。

 

Lambda表达式

匿名内部类和Lambda表达式转化:

Lambda表达式的前提条件:

必须有一个接口(只能操作接口);

接口只有一个方法。

 

这里调用了useShowHandler方法,参数是实参,是一个子类/实现类对象;

定义了show方法,参数是形参:

 

这里定义了useShowHandler方法,参数是形参:

如果这里show("asdfghjkl");那么字符串是show的实参;如果userShowHandler(S s, int a, int b){},那么a,b是show的形参。

 

一个方法,他操作的是接口,且接口只有一个方法,那么就可以用Lambda表达式。

其实Lambda表达式很清楚地表达了:方法需要的是一个show方法体。

 

运行的时候自动的在内存中生成,不会保存到磁盘中。

选中一个.java文件,右击,Open In,Explorer,就能打开该.java文件所在目录,往上级翻,到out文件夹,是专门存.class文件的,按照目录找到该.class文件。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值