[java核心篇02]__内部类
- 前言
其实我们在前面已经初步接触到内部类了,但是我们去对它的作用并不胜了解.只是简单的知道了类的定义也是可以嵌套的,定义在一个类里面的类就是内部类.
class out{
private String name;
private int age;
class in{
private String sex;
}
public String getName(){
return this.name;
}
}
但是关于内部类有什么作用,有什么分类都不是很了解,通过这篇文章来对java内部类的学习进行加深.
- 内部类的特点
1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
3、创建内部类对象的时刻并不依赖于外围类对象的创建。
4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。
6、内部类可以访问包括私有成员在内的外部类的所有成员。
- 内部类的作用
书上的描述并不详细,于是google了下相关的文章,感觉还是说法不一, 具体的作用有很多,于是大致总结两点:内部类并不象外部类一样,它可以使用provate,proteced,这意味着它可以更好的封装,更好的隐藏起来,在我们需要隐藏某些方法的实现细节时,可以使用到内部类.而外部类则不行.
另外一个作用就是能够更好的解决java多继承的问题,我们知道,在java语言中秉性的是单继承,而内部类与外部类的继承关系是互不干扰的,我们在前面知道了,java类可以通过接口的多继承解决多继承的问题,但那并没有彻底解决这个问题,而通过内部类则可以彻底解决这个问题,我们可以通过内部类实现类的多继承(可以定义多个内部类继承多个抽象类或具体类)
内部类的分类
- 静态内部类与非静态内部类
内部类更具其定义方法分为静态内部类和非静态内部类.其区别:- 静态内部类可以有静态成员变量,而非静态内部类则不能有静态成员变量。
- 静态内部类可以访问外部类的静态变量,但不可访问外部类的非静态变量;
- 非静态内部类的非静态成员方法可以访问外部类的非静态变量,也可以访问静态变量。
- 静态内部类的创建不依赖于外部类,而非静态内部类必须依赖于外部类的创建而创建。
- 静态内部类与非静态内部类
我们通过一个例子看看:
public class sty_internalClass {
public static void main(String[] args) {
// 创建内部类实例化对象的第一种方式..
textclass text = new textclass(); // 实例化外部类对象
textclass.internaltextclass internaltextclass = text.new internaltextclass(); // 实例化内部类的对象要通过外部类对象来实现.
// 创建内部类的实例化对象的第二种方式
textclass.internaltextclass internaltextclass1 = new textclass().new internaltextclass();
// 创建静态内部类实例化对象
textclass.astaticinclass astaticinclass = new textclass.astaticinclass(); // 静态内部类的实例化不需要依赖外部类.
}
}
class textclass{
private String name;
static private int age;
public class internaltextclass{ // 内部类
String sex="男";
internaltextclass(){ // 构造方法
name = "小舍";
age = 23;
}
void input(){
System.out.println("这是内部类的一个方法");
System.out.println(age);
}
}
public static class astaticinclass{
void funtion(){
System.out.println(age);
}
}
public internaltextclass getinternaltextclass(){
return new internaltextclass();
}
void ainput(){ // 外部类的一个方法,调用内部类的属性和方法.
internaltextclass internaltextclass = new internaltextclass();
internaltextclass.sex = "男";
}
}
我们可以观察出:非静态内部类的实例化必须依赖外部类(需要通过一个外部类的实例化对象创建对象)
而静态内部类是不依赖外部类的(可以直接创建实例化对象)
非静态内部类:
- 成员内部类
- 方法(局部)内部类
- 匿名内部类
成员内部类
就其文字含义而言,它就是作为一个类的成员存在的内部类.我们可以将它看做一个类的一个成员,只不过这个成员的类型是一个类而已.
class textclass{
private String name;
static private int age;
public class internaltextclass{ // 内部类
String sex="男";
internaltextclass(){ // 构造方法
name = "小舍";
age = 23;
}
void input(){
System.out.println("这是内部类的一个方法");
ainput(); // 可以没有任何限制的调用外部类的方法.
}
}
void ainput(){ // 外部类的一个方法,调用内部类的属性和方法.
internaltextclass internaltextclass = new internaltextclass();
internaltextclass.sex = "男";
}
}
我们甚至可以通过定义get方法来获得一个成员内部类的对象.
public internaltextclass getinternaltextclass(){
return new internaltextclass();
}
我们可以观察到:
- 成员内部类的定义是更成员变量并列的,所以可以看成是外部类的一个成员.
- 成员内部类的好处就是可以没有任何限制的访问外部类的属性和方法.不管是静态还是非静态.
- 用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限,更好的封装隐藏性。
(成员内部类不能有静态成员变量和方法,这是因为成员内部类不能被定义为静态的,定义为静态就成了静态内部类了,而之所以静态内部类不叫静态成员内部类,这应该是因为静态内部类对象的创建不依赖于外部类,所以严格来说算不上是外部类的一个成员.)
- 方法(局部)内部类
很多文章都喜欢将它称为局部内部类,但是我觉得这样并不贴切,很模糊概念.其实局部内部类就是定义在一个方法体中的内部类.它与局部变量类似,其作用范围也只有方法体大小,其访问权限也只有方法体大小,这里我们就可以察觉到,那么局部内部类真的是太适合封装了,其隐蔽性更加高了.
我们放大上面例子中的ainput方法(外部类的普通方法),在里面加入一个局部内部类:
void ainput(){ // 外部类的一个方法,调用内部类的属性和方法.
final String[] a = new String[0];
internaltextclass internaltextclass = new internaltextclass(); // 通过实例化内部类来调用内部类的成员变量.
internaltextclass.sex = "男";
// 定义局部内部类
class Localinclass{
void Local(){
a[0] = "外部方法体中的变量";
System.out.println("局部内部类中的方法");
System.out.println(a[0]);
}
}
//在方法体中调用局部内部类.
Localinclass localinclass = new Localinclass();
localinclass.Local();
}
我们可以观察到,在方法体中的内部类,只能从上往下运行(调用只能再内部类的下面,否则无法识别到,这应该是是因为java运行的机制,在方法体中是从上到下的.)
另外,在局部内部类中,我们只能访问到方法体中的final型变量.
- 匿名内部类
匿名内部类比较特殊,它的创建不需要类名(当然也不需要class关键字),但其必须继承一个抽象类或是一个接口(只能是一个).
匿名内部类的定义是这样的:
new 父类构造器(参数){ // new一个父类的引用
类体部分
}
new 接口(){
类体部分
}
匿名内部类实际完成的工作其实就是实现抽象类或接口中的方法.然后作为一个实例的对象被创建.
我们来看一个例子.
package java02.day_4_14;
/**
* @outhor xiaoshe
* @date 2019/4/15 - @time 1:55
* 匿名内部类
*/
public class sty_anonymous {
public void outman(man m){
System.out.println(m.toout());
}
public static void main(String[] args) {
sty_anonymous styAnonymous = new sty_anonymous();
// 匿名内部类的使用
styAnonymous.outman(new man() {
@Override
String sex() {
return "男";
}
@Override
String name() {
return "男人";
}
@Override
String toout() {
return(this.name()+"\n"+this.sex());
}
});
}
}
// 定义一个抽象类
abstract class man{
private String name;
private String sex;
abstract String sex(); // 定义一个抽象方法
abstract String name(); // 定义一个抽象方法
abstract String toout();
}
我们可以看出,匿名内部类在这里的功能是实现抽象类中的抽象方法,应为抽象类是不能直接实例化的,所以这里通过了匿名内部类继承了抽象类man,而这里的new man{...}
就是整个匿名内部类,它在这里不是作为方法outman(man m)
中的man类实例对象m
二存在的(因为抽象类不能直接实例化对象), 而是作为一个继承了抽象类man的匿名内部类(即new man{...}
)的实例化对象而存在的.同时抽象类被继承后其抽象方法必须全部实现.
我们将整个匿名内部类收起来:
同时我们应该注意到,匿名内部类的使用范围是十分有限的,一个匿名内部类只能被使用一次(只在一个方法中当做一个实例化对象来使用)
ps:发现昨天核心以的关于抽象类和接口的知识点有很大差错,这次记住教训,学东西不能图快,切勿没完全整明白就跳过.明天重新总结,
检讨之
更新时间:
2019-4-15
2:30
[java核心篇02]__内部类的更多相关文章
- [Java初探实例篇02]__流程控制语句知识相关的实例练习
本例就流程控制语句的应用方面,通过三个练习题来深入学习和巩固下学习的流程控制语句方面的知识,设计到,if条件判断语句,switch多分支语句,for循环语句及其嵌套多层使用,while循环语句. 练习 ...
- Java基础篇(02):特殊的String类,和相关扩展API
本文源码:GitHub·点这里 || GitEE·点这里 一.String类简介 1.基础简介 字符串是一个特殊的数据类型,属于引用类型.String类在Java中使用关键字final修饰,所以这个类 ...
- java提高篇(十)-----详解匿名内部类
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
- java提高篇(九)-----实现多重继承
多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...
- java提高篇(九)-----详解匿名内部类
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
- 【转】java提高篇(十)-----详解匿名内部类
原文网址:http://www.cnblogs.com/chenssy/p/3390871.html 在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节 ...
- java提高篇(十)-----详解匿名内部类 ,形参为什么要用final
在java提高篇-----详解内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.如何初始 ...
- java提高篇(八)-----实现多重继承
多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...
- java提高篇(八)----详解内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...
随机推荐
- Programming for Everyone !
Hello Internet ! This blog is to store my algorithm practices. Since Evernote code blocks do not sho ...
- Git的安装和使用
在CentOS 6.x/7.x上安装git及最新版 方式一.yum安装 # yum install git 通过yum方式安装,版本比较旧,CentOS6.5上安装好是1.7.1版.如果想安装最新版或 ...
- mybatis中String参数的传递
mybatis中String参数的传递 Keywords selectKeywords(@Param("key") String key); 可以在mapper方法的参数钱添加 @ ...
- 破解某普通话测试app会员
设备要求 已root的Android手机 软件要求 反编译工具 jeb.APK改之理(APK IDE) hook工具 frida.xposed. 布局分析工具 Android Device Monit ...
- 修改云主机windows密码不生效
Step1:使用文本工具打开插件路径: 路径为:C:\Program Files\Cloudbase Solutions\Cloudbase-Init\Python\Lib\site-packages ...
- Problem creating zip: Execution exce ption (and the archive is probably corrupt but I could not delete it): Java heap space -> [Help 1]
今天mvn编译的时候报错: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-plugin:2.5.5:s ...
- Ubuntu 16.04上安装Global阅读源代码工具
参照10年前写的文档 (Linux源码阅读工具lxr和glimpse的安装与配置),想重新搭建一个源代码阅读工具,发现源里面都没有相关的工具了. 然后看到有更简单的安装工具Global可以使用,所以果 ...
- 洛谷 质因子分 p2043
#include <iostream>#include <algorithm>#include <cstring>using namespace std; cons ...
- ios系统的Date的兼容问题
内容来源网上,自己记录下 问题1: var date =new Date(); 这个是获取当前系统时间的对象,在各端都可以 但是: var date =new Date("2017-01-2 ...
- 【原创】IO流:读写操作研究(输入流)
默写代码(以下问题要求能默写,不翻书不百度) 输入 问题一:从文件abc.txt中读取数据到字节数组并打印出来. 分析:如果读取数据,首先第一个问题,数据有多少?如果数据量不确定,如果确定字节数组大小 ...