java学习(6)-多态和内部类



说明

因为是个人复习java的总结,所以结构稍显杂乱,有些语句过于口语化.


多态

  多态其实就是父类引用指向了子类对象,从内存上可以很好的理解,其实就是在栈中创建了一个父类的引用指向的是堆中创建的子类对象,但是这时子类对象中的内容其实是加载子类覆盖之后的父类内容.
  也就是说父类的引用可以访问到子类对于父类重写的部分和父类部分,但是不能访问到子类特有的部分,
  但是对于成员变量来说,父类引用只能访问父类的变量,因为变量这个概念没有覆盖重写.

  总结就是父类引用的子类对象其实持有的是加载一遍子类覆盖重写之后的父类对象内容.
  由此也可理解多态的好处,在对于共同父类的子类做相同的操作的时候,他们的引用可以是相同的类型,有利于泛型或者是其他编程的使用.
  但是这种方式也存在一些问题,将子类对象赋给父类引用,代表着向上转型,这回导致丧失一些子类的特有的方法或者特性.这时可以通过向下转型还原对象的引用.也就是强制转换将父类引用转回子类,但是需要前提父类引用持有的子类对象和强转的子类类型是一样的.
  从内存上理解就是堆中的子类对象其实没有改变,改变的只是父类引用对于子类中调用持有的指针的不同,调用的部分不同,重新转换之后仍可以调用原本的子类.



instanceof

其实就是用于判断引用中对象的类型到底是什么的关键字.



接口对于多态的使用

  譬如说对于一台电脑有usb接口,那么将usb标准作为一个接口,使得键盘等使用usb的实现接口,然后根据多态就可以在创建实现类对象的时候向上转型,这样接口类型的引用就可以调用实现类中重写接口的方法,而且这个类型不会因为链接的设备不同而改变.那么电脑中的所有调用usb的方法都可以使用usb作为适配类型,就不用设置很多的方法.
  直接使用usb作为参数就传递usb的实现类鼠标类键盘类等,因为他会自动实现向上转型,转换成usb类的引用.
  同时在写使用设备方法的时候就可以再向下转型然后调用对应设备的方法.



final

其实就是一个最终的概念,即被标识的东西不能再进行更改

可以用来修饰类,方法,局部变量和成员变量.
当修饰类的时候,这个类就不能被继承
当修饰方法的时候,那么子类不能对父类中的final方法重写覆盖
同时final和abstract不能共同使用,很容易理解,一个是必须重写,一个是不能重写.
当修饰局部变量的时候,局部变量一次赋值之后就不能改变.
当修饰成员变量的时候,也是成员变量不能改变.

  其实不能改变的变量包括引用变量和基本类型变量,一个是其中引用的地址值不能改变,一个是其中的内容不可变.
  但是需要注意final修饰都必须在使用之前赋值,对于局部变量可以在使用之前赋值一次只要不改变就行.对于成员变量则是必须在定义是初始化或者在所有构造器中定义赋值,注意是所有构造函数.并且两种方式只能选其一,因为final修饰之后不能改变,构造器中赋值,又有初始化就是两次赋值了.



四种权限修饰符

			  Public   	Protect		Default		Private
同一个类			YES			YES			YES			YES
同一个包			YES			YES			YES			NO
不同包子类		YES			YES			NO			NO
不同包非子类		YES			NO			NO			NO


内部类

其实就是一个类内部存在另外一个类,也就是人体和心脏的关系



成员内部类

也就是在类中定义一个类

public class 外部类名称{
	public class 内部类名称{}
}

  内部类中可以随意访问外部类,但是外部类必须使用内部类对象访问内部类.
  也就是说内部类可以访问外部类的任意信息包括私有标记的
  因为实际上在内存上是内部类对象创建了一个指向外部类对象的指针,那么通过这个指针获取到外部类的数据就相当于外部类对象获取自身数据,没有限制.

  实际上调用外部类的时候是 外部类.this.属性或者方法 这种格式调用
  但是对于没有重名的方法或者变量的时候可以直接在内部类使用方法名或者变量名调用,会自动向上寻找,但是如果出现同名就需要选择使用哪个的开头调用哪个方法.
  外部类调用内部类的时候则需要创建内部类对象调用,在实际使用中可以分为在外部类方法中创建内部类对象调用内部类方法,然后就可以直接使用外部类对象调用方法达到调用内部类方法的效果.或者直接创建内部类对象,调用方法,具体格式如下:

外部类.内部类 对象名 = new 外部类.new 内部类

  这样对象直接是内部类对象可以调用内部类方法.



静态内部类

  其实就是static修饰的内部类成员内部类
  可以使用外部类的静态域但是不能使用外部类的非静态域.
  因为外部类的非静态与属于对象.而非静态内部类使用是需要和外部类的对象绑定在一起的,所以可以调用外部的非静态域.
  并且静态内部类只有在外部类调用到内部类的时候才会加载到方法区.
  另外静态域可以避免内存泄漏,也就是说非静态内部类对象可以调用外部类的非静态方法,那就出现一个问题,如果外部类存在时间比内部类短,那么这个引用就会导致外部类无法销毁,内部类对其引用导致存在.而如果使用静态内部类就不会有这个问题,因为不允许调用外部类的非静态域.
  也就是说静态内部类相当于一个独立的类,而非静态内部类是关联外部类的类,那么静态内部类和外部类之间的关系相当于普通类,而非静态内部类是寄存在外部类对象中的.



局部内部类(使用不多 了解一下)

  定义在方法中的局部类就是局部内部类
  如果要访问方法的局部变量就要求这个变量必须是final的,jdk8之后可以省略final,但是要求这个变量实际上没有改变.
  这是因为从内存上看,方法的局部变量是在栈中,且随着方法的消失而消失,但是对于局部内部类来说,局部内部类的对象是创建在堆中的,随着垃圾回收而消失,这就造成了一个问题,方法的出栈也就是局部变量的消失往往比对象来得早,因此就需要这个变量是不会改变的,然后堆中局部内部类的对象copy一份变量到常量池使用,从而避免出现方法结束,对象存在却找不到变量的问题.



内部类的权限要求

外部类:public或者default
成员内部类:所有权限
局部内部类:什么都不能写



匿名内部类

  如果接口的实现类或者父类的子类只使用唯一的一次,就可以省略掉这个类的定义.
  就是对于只使用一次的接口或者子类,不写接口的实现类来用,而是直接在创建接口引用的时候创建一个匿名内部类作为对象
具体格式如下:

接口名称 对象名 = new 接口名称(){
	覆盖重写接口所有抽象方法
}

  这样可以省略一些内容较简单的接口的实现类,比如说usb只有启动一个方法,却要为了使用这个接口而创建上百种不同的设备对于usb接口的实现类.这就很麻烦.使用匿名内部类就可以简化很多流程.

匿名内部类只使用一次,所以需要注意使用
匿名内部类不能定义任何静态成员、方法。
匿名内部类中的方法不能是抽象的;
匿名内部类必须实现接口或抽象父类的所有抽象方法。
匿名内部类访问的外部类成员变量或成员方法必须用static修饰;

  因为匿名内部类是一个短期使用的类,并且一定会创建一个对象,所以静态修饰就没有意义,因为静态希望在不创建对象的时候能通过类名调用属性或者方法,但是匿名内部类一定有对象.并且没有名字.所以二者完全冲突.



匿名内部类和匿名对象的区别

  匿名内部类是实现一个接口或者类的实例化,这个对象可以赋值给某个栈中的引用.
  而匿名对象则是单纯的没有赋值给某个引用的匿名内部类的对象.



如有错误欢迎读者批评指正!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值