在本文中,我们将为您详细介绍Java内部类的相关知识,并且为您解答关于java内部类怎么写的疑问,此外,我们还会提供一些关于Eclipse快捷键;包;权限修饰符;内部类;抽象类;接口概念和定义(Jav
在本文中,我们将为您详细介绍Java 内部类的相关知识,并且为您解答关于java内部类怎么写的疑问,此外,我们还会提供一些关于Eclipse 快捷键;包;权限修饰符;内部类;抽象类;接口概念和定义 (Java Day09)、Effective Java - 嵌套类 (内部类)、Java - 内部类、java - 抽象类、接口、内部类的有用信息。
本文目录一览:- Java 内部类(java内部类怎么写)
- Eclipse 快捷键;包;权限修饰符;内部类;抽象类;接口概念和定义 (Java Day09)
- Effective Java - 嵌套类 (内部类)
- Java - 内部类
- java - 抽象类、接口、内部类
Java 内部类(java内部类怎么写)
以下是个人对 Java 内部类的一些认识,如有错误地方,欢迎大家指出,感谢!
内部类是定义在一个类中的类
- 内部类可对同一个包中的其他类隐藏起来
- 定义一个回调函数且不想编写大量代码时,匿名内部类比较便捷
- 内部类既可以访问自身的数据域和方法,也可以访问创建它的外部类的所有数据域和方法(闭包)
- 只有内部类可以是私有类(private),而常规类只能是包可见性(默认,什么都没写)或公有可见性(public)
- 只有内部类才能声明为 static
内部类好处
内部类完善多重继承,即一个类 A 虽然可以实现多个接口,但是只能继承一个类或抽象类。但是可以让类 A 的多个内部类分别继承多个类或抽象类,从而实现多重继承。
成员内部类
- 作为外部类的成员变量,外部类要访问内部类的所有成员变量 / 方法,需要通过内部类的对象来获取
- 成员内部类不能含有 static 的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己
- 在成员内部类要引用外部类对象时,使用
outer.this
来表示外部类对象
局部内部类
- 类定义在方法中,不能用 public 或 private 声明,作用域限定在此方法中,外部类的其他代码也无法访问
- 除了能访问外部类,还能访问此方法的局部变量,不过这些局部变量必须是
final
public void start(int a, final boolean flag) { class Inner { public void action() { System.out.println(flag); } } Inner inner = new Inner(); inner.action(); System.out.println(a); }
匿名内部类
- 只创建这个类的一个对象,不必命名(没有类名)
- 由于构造器的名字和类名相同,而匿名类没有类名,所以匿名类不能有构造器
- 匿名内部类的
this
指的是匿名内部类自身,要获得外部类的引用:outerClass.this
,其中 outerClass 为外部类的类名
public void start(int interval, final boolean beep)
{
ActionListener listener = new ActionListener() //类定义直接跟在接口后面
{
public void action()
{
//do something
}
};
listener.action();
}
public void execute()
{
// an object of an inner class extending Person class
Person count = new Person("lala"){...}
}
静态内部类
- 只是为了把一个类隐藏在另一个类的内部,不能引用外部类里的对象(只能访问外部类的静态数据域和方法)
- 生成一个静态内部类不需要外部类
Outer.Inner in = new Outer.Inner();
- 作为外部类的成员变量,不能放在方法中
Eclipse 快捷键;包;权限修饰符;内部类;抽象类;接口概念和定义 (Java Day09)
一,Eclipse 进阶
(一)内容辅助键
-
alt / :在想不起来代码的时候,可以使用这个按键来做代码的自动生成
应用:
main 配合 alt / :生成主方法
syso 配合 alt / :生成一个输出语句
Ctrl + 1 :补全代码
- 创建对象,可以使用内容辅助键,补全类名、构造方法,给变量起名字
遍历数组,for 配合 atl / :遍历最近的数组
(二)Eclipse 的常用的快捷键
1、ctrl + n:新建工程、包、类和文件等内容
2、Ctrl + shift + f:格式化代码
3、Ctrl + shift + o:自动导包、删除没有用的包
4、Ctrl + /:单行注释,取消单行注释
5、Ctrl + shift + / :多行注释
6、Ctrl + shift + \ :取消多行注释
7、Alt + ↑:向上移动一行
8、Alt + ↓:向下移动一行
9、Ctrl + alt + ↑:向上复制一行
10、Ctrl + alt + ↓ :向下复制一行
11、Ctrl + d:删除一整行
12、Alt + shift + r:整体修改某个标识符名称
13、F2:可以修改文件名称,并且将所有关联的位置一起修改
(三)快速生成一个自定义类的快捷键
1、成员变量需要自己手动定义
2、Alt + shift + s:
C:生成空参构造
O:生成有参构造
R:生成getset方法,配合alt + a、alt + r
二,包
- 概述:存放并分类管理代码文件的特殊文件夹。
- 包可以被编译器识别,其他普通文件夹不能被识别。
- 在开发工具中包默认在 src 的包下 ,src 提供给编译器识别包
- 作用:分类管理代码
- 命名:公司域名倒写,名称全部小写,包和包之间使用。隔开
- 特点:
- 全部单词小写
- 唯一
- 不同的包中可以出现相同的名称的类、接口等资源
- 声明:
- 使用关键字 package 进行声明
- 格式:package 包的具体路径;比如:package com.ujiuye.demo;
- 导包:
- 使用关键字 import + 具体包路径 比如:import java.util.Scanner;
- 运行:加载包当中相关的资源,通过导包的路径找到对应的资源。
三,权限修饰符
- 概述:修饰相关内容,使该内容的访问范围。在一定的范围我们可以访问使用,出了这个范围就不能访问
- 分类:
- private:私有的 只在本类中可以使用 【常用的 封装属性】
- 默认的:什么都不写 在本类可以使用,在同一个包下可以使用
- protected:受保护的 在本类可以使用;在同一个包下也可以使用;不在同一个包下可以继承但不能被使用
- public:公开的 没有范围限制 【最常用的】
代码示例
package com.ujiuye.demo;
public class Demo01 {
private int a = 10;//私有的
int b = 20;//默认的
protected int c = 30;//受保护的
public int d = 40;//公开的
//在本类中使用这些资源
public void show () {
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
------------------------------------------------------------
package com.ujiuye.demo;
public class Test {
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
//在测试类中使用四个变量
//System.out.println(demo01.a);私有的访问不了 出了本类这个范围但是在同一个包下
System.out.println(demo01.b);
System.out.println(demo01.c);
System.out.println(demo01.d);
}
}
=========================================================
package com.ujiuye.demo01;
import com.ujiuye.demo.Demo01;
public class Test {
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
//在测试类中使用四个变量
//System.out.println(demo01.a);//私有的访问不了 出了本类这个范围但是在同一个包下
//System.out.println(demo01.b);//默认的访问权限同包下,出了包的范围到其他包下访问不了
//System.out.println(demo01.c);//受保护的访问权限同包下可访问,出了包的范围到其他包下可继承不能访问
System.out.println(demo01.d);
System.out.println("===============");
//既然继承了使用子类对象访问这些属性
Demo demo = new Demo();
//还是直接访问 访问不了 子类还是在另外一个包中超出范围
/*System.out.println(demo.a);
System.out.println(demo.b);
System.out.println(demo.c)*/;
System.out.println(demo.d);
demo.print();
}
}
------------------------------------------------------------------
package com.ujiuye.demo01;
import com.ujiuye.demo.Demo01;
public class Demo extends Demo01{
public void print() {
//System.out.println(super.a);//私有的范围就是本类,这里其他包下访问不了 不能被继承
//System.out.println(super.b);//默认的范围是本包,这里其他包下访问不了 不能被继承
System.out.println(super.c);//受保护的范围是本包课访问,出包可继承
System.out.println(super.d);
}
}
四,内部类
- 概述:定义在一个类中的类叫做内部类。他类消失了一些类本身有的功能。
- 分类:
1. 从位置划分:
1.1. 成员位置:
1.1.1,普通成员内部类
1.1.2,私有成员内部类
1.1.3,静态成员内部类
1.2. 成员方法内部:
1.2.1,局部内部类
2. 从表示形式上划分:
2.1. 有名的内部类:位置划分的内部类都属于有名的内部类
2.2. 没有名字的内部类:匿名内部类【多态】
-
普通成员内部类
- 位置:类中的成员属性位置使用类的定义格式在定义一个类
- 定义格式:和类的格式是一样的: class 内部类的名称 {书写内部类的内容}
- 理解:我们可以把整个内部类看成是一个整体,整体看成外部类的一个特殊的属性,
- 访问的时候:使用外部类的对象。内部类的对象
- 成员内部类的内容说明:【内部类丧失一些类功能】
- 不能定义静态的资源
- 可以使用外部类的所有资源
- 外部类不能直接使用内部类的资源,要想使用必须先创建内部类对象
- 内部类资源使用:
- 外部类中:在外部类的方法中创建内部类的对象,使用对象访问内部类的资源
- 外部类外:首先创建外部类的对象,调用内部类的对象 【创建出来】
- 格式:成员内部类名字 内部类对象名 = new 外部类名().new 内部类类名()
代码
package com.ujiuye.demo;
public class Outer01 {
int a = 10;
static int b = 20;
int d = 200;
//成员内部类
class inner{
int a =100;
//static int c = 30; 成员内部类不允许定义静态资源
int c = 30;
public void show () { // 内部类可以访问所有的资源
System.out.println(a); //100 变量的就近原则
System.out.println(b); //20
System.out.println(c); //30
System.out.println(d); //200
print();
}
}
//外部类中使用内部类的资源必须创建内部类的对象
public void print () {
System.out.println(a);//就近原则访问自己的a 10 不是inner里面的a
// System.out.println(c);//c是inner里面的c 报错 访问不了
inner inner = new inner();
System.out.println(inner.c);
System.out.println("我是外部类的方法");
}
}
================================================================
package com.ujiuye.demo;
import com.ujiuye.demo.Outer01.inner;
//测试类
public class Outer01_test {
public static void main(String[] args) {
Outer01 outer01 = new Outer01();
outer01.print();
//直接使用成员内部类的资源【首先要进入外部类,再进入内部类】
inner inner = new Outer01().new inner();
System.out.println(inner.a);
System.out.println(inner.c);
inner.show();
}
}
注意:内部类访问外部类的同名变量:固定格式:外部类名.this. 变量名
-
私有成员内部类
- 位置:定义在成员位置上【类中方法外】被 private 修饰的成员内部类;
访问权限【范围就变小了】,只能在本类【外部类】中使用
- 特征:普通的成员内部类被 private 关键字修饰
- 定义格式:private class 名称 {内部类的内容}
- 内容的说明:
- 不能存在静态的资源
- 他可以使用外部类的所有资源
- 使用:只能被外部类使用,出了外部类其他类使用不了。
- 外部类内:
- 在外部类中定义方法,方法中创建私有内部类的对象,用对象去调用资源
- 如果外部类的外面也要使用内部类的资源怎么办?
- 在外部类中定义方法,方法中创建私有内部类的对象,用对象去调用资源
- 外面的类创建外部类的对象调用外部类的这个方法间接的访问内部类的资源
代码
package com.ujiuye.demo;
public class Outer02 {
int a = 10;
static int c = 20 ;
//私有成员内部类
private class Inner{
/*static*/ int d= 30;
public /*static*/ void show() {
//可以使用内部及外部类的资源
System.out.println(a);
System.out.println(c);
System.out.println(d);
}
}
public void useInner() {
//创建内部类的对象
Inner inner = new Inner();
//使用对象访问对应的资源
System.out.println(inner.d);
inner.show();
}
//提供一个外接访问内部类的方法
public Inner get () {
Inner inner = new Inner();
/*System.out.println(inner.d);
inner.show();*/
return inner;
}
}
====================================================
//测试类
package com.ujiuye.demo;
public class Outer02_Test {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.useInner();
//new Outer02().new Inner();不行,因为内部类私有化 出了类不能被访问 只能提供对外唯一访问方式
//Inner inner = outer02.get(); 报错 Inner是Outer02的私有内部类 外接无权访问这个类 找不到这个类
}
}
-
静态成员内部类
- 位置:类的成员位置【类中方法外】
- 特征:使用 static 修饰的普同成员内部类
- 定义格式:static class 名称 { 内部类的内容}
- 访问说明:
- 静态内部类可以访问外部类的所有的静态资源【遵守 static 的使用元素原则】
- 可以有自己的静态资源【比成员内部类好的地方】
- 创建对象方式:【使用】
3.1 在外部类的内部: new 内部类名();
3.2 在外部类的外部:new 外部类名。内部类名()
代码
package com.ujiuye.demo;
public class Outer03 {
int a = 10 ;
static int b= 20;
//静态成员内部类
static class Inner{
//内容
int c = 30;
static int d = 40;
//使用外部类的资源
public void show() {
//System.out.println(a);a在外部类中不是静态资源
System.out.println(b);
//使用自己的资源
System.out.println(c);
System.out.println(d);
}
}
//静态内部类的使用 外部类的内部
public void userInner() {
//创建内部类的对象
Inner inner = new Inner();
System.out.println(inner.c);
System.out.println(inner.d);
inner.show();
}
}
===========================================================
//测试类
package com.ujiuye.demo;
import com.ujiuye.demo.Outer03.Inner;
public class Outer03_Test {
public static void main(String[] args) {
//在外部类的外面直接的访问静态内部类的资源
Inner inner = new Outer03.Inner();
System.out.println(inner.c);
System.out.println(inner.d);
inner.show();
}
}
-
局部内部类
- 位置:定义在方法的方法体中
- 这个类属于方法,可以看做是方法局部的元素;
- 外部类不能直接访问局部内部类的元素;只能通过所在方法调用来使用,但是局部内部类可以使用外部类中的资源。
- 说明:
- 局部内部类中的成员访问时根据所在的方法不同而不同的
1.1 在静态方法中:
他只能访问外部类中的静态变量。
局部内部类中能出现静态资源?可以
1.2 在普通方法中:
他可以访问外部类中所有的资源
2. 内部类可以访问所在方法中的变量(局部变量)?可以的。
3. 出了局部内部类所在的方法范围外,无法访问局部内部类的内容的。
如何解决该问题? 在局部内部类所在的方法中创建内部类对象使用对象访问里面相关资源
代码示例
package com.ujiuye.demo;
public class Outer04 {
int a = 10;
static int b =20;
public void print() {
//局部内部类
class Inner{
int c = 30;
//static int d = 40 ;不允许出现静态的资源
public void show() {
//访问外部类的资源
System.out.println(a);
System.out.println(b);
}
}
//局部内部类的使用【在所在的方法中创建局部内部类的对象,使用对象调用对应的资源】
Inner inner = new Inner();
System.out.println(inner.c);
inner.show();
}
//外部类的方法想要使用内部类的资源
public void run() {
//System.out.println(c);
//new Inner()
//调用局部内部类所在的方法从而达到访问内部类资源的效果
print();
}
}
五,抽象类
-
抽象方法:
- 抽象方法:被关键字 abstract 修饰的并且没有方法体的方法
- 抽象:想象出来的,虚幻的,没有实体的
- 作用:对外声明行为。【广告】
- 特点:对外只声明自己的功能,不会去做这个功能
- 好处:方法的功能扩展性强
- 格式:修饰符 abstract 返回值类型 方法名(形式参数);
比如:public abstract GrilFriend getGrilFriend(int money);
注意:抽象方法必须存在于抽象类和接口中,要想具体化必须要被重写
-
抽象类
- 概述:被 abstract 修饰的类就叫做抽象类
-
抽象类的内容:
- 成员变量:描述事物属性的。和普通的变量时一样。
- 构造方法:和普通类的构造一样的【写法样式一样】
作用不一样了:不能创建对象了,给子类对象调用使用的抽象类有构造方法吗?
有,但是不能创建自己对象,是给子类使用的。子类创建对象的时候优先加载父类的构造方法
3. 成员方法
普通方法:正常的进行定义
抽象方法: 抽象类增加的一个方法【没有具体的执行语句】
4. 抽象类和抽象方法的关系:抽象类中不一定有抽象方法;有抽象方法的类一定是抽象类
5. 特点:
5.1 一定被 abstract 修饰
5.2 有构造但是不能创建自己的对象
5.3 抽象方法可有可无
5.4 有抽象方法类必须是抽象类
5.5 抽象方法必须要被子类重写
6. 使用场景:抽象类用作于父类,抽取子类中的一些共性行为,共性行为的动作不一样。
比如:
- 学生有工作的行为:学习
- 老师有工作的行为:讲课
- 把这个工作的行为提取父类中
代码示例: 创建抽象类
package com.ujiuye.demo;
//父类
public abstract class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//共性的行为 工作 抽象方法
public abstract void work();
}
=======================================================
//创建教师子类
package com.ujiuye.demo;
public class Teacher extends Person{
@Override
public void work() {
System.out.println("好好讲课,善待学员");
}
}
========================================================
//创建学生子类
package com.ujiuye.demo;
public class Student extends Person{
@Override
public void work() {
System.out.println("好好学习,天天向上");
}
}
===========================================================
//测试类
package com.ujiuye.demo;
public class Person_Test {
public static void main(String[] args) {
Student student = new Student();
Teacher teacher = new Teacher();
student.work();
teacher.work();
}
}
注意:抽象类有多个抽象方法,子类必须全部重写
练习
- 程序员类:属性(姓名、工号、工资、奖金),行为(工作:软件开发)
- 测试工程师:属性(姓名、工号、工资),行为(工作:软件测试)
- 项目经理类:属性(姓名、工号、工资、奖金),行为(工作:控制进度)
- 分析:
- 有共同相似的内容:姓名 工号 工资 行为(工作)可以向上抽取成为一个类 抽象类
- 分别定义程序员类 测试工程师类 项目经理类继承抽象类 重写行为
代码
//抽象类[父类]
package com.ujiuye.demo;
public abstract class Employee {
private String name;
private String id;
private double salary;
//共性行为 抽象方法
public abstract void work();
public Employee(String name, String id, double salary) {
super();
this.name = name;
this.id = id;
this.salary = salary;
}
public Employee() {
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
==============================================
//程序员类[子类]
package com.ujiuye.demo;
public class Coder extends Employee{
private double bonus;
//重写抽象方法
@Override
public void work() {
System.out.println("软件开发");
}
public Coder(String name, String id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public Coder() {
super();
}
public Coder(String name, String id, double salary) {
super(name, id, salary);
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
===============================================
//测试工程师[子类]
package com.ujiuye.demo;
public class Tester extends Employee{
//重写抽象方法
@Override
public void work() {
System.out.println("软件测试");
}
public Tester() {
super();
}
public Tester(String name, String id, double salary) {
super(name, id, salary);
}
}
============================================
//项目经理类[子类]
package com.ujiuye.demo;
public class Manager extends Employee{
private double bonus;
//重写抽象方法
@Override
public void work() {
System.out.println("项目的控制");
}
public Manager(String name, String id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public Manager() {
super();
}
public Manager(String name, String id, double salary) {
super(name, id, salary);
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
}
================================================
//测试类
package com.ujiuye.demo;
public class Employee_Test {
public static void main(String[] args) {
Coder coder = new Coder();
coder.work();
Manager manager = new Manager();
manager.work();
Tester tester = new Tester();
tester.work();
}
}
七,接口
-
概念:
- 接口是引用数据类型的一种,我把类可以看做是事物属性和行为以及构造器的集合体,接口就可以看做是不同类型的事物的相似行为的集合体。
- 举例:人可以走路 动物可以走路 机器人也可以走路,走路相似的行为,走路的方式不一样,就可以把不同事物的走路行为声明提取出来,放到一个集合中,由于方法体不一样就不写,把行为变为抽象的;这个集合命名为接口。
- 接口:就是行为规范的设定。就是规则集合,接口就是准则。
抽象类是对同一系列的事物的共性行为声明的提取,接口就是不同系列事物的共性行为声明提取
- 编译:参与编译,编译后也是.class 文件【类和接口编译后都是字节码文件】
- 接口的使用:
- 定义接口
- 使用类来实现,并重写方法
- 创建类对象调用重写后的方法
-
接口的定义:
格式:修饰符 interface 接口名称 {接口内容}
-
解释:
interface:就是关键字 表示就是接口
接口名称:自己命名。遵循见名知意、大驼峰格式
- 内容:
- 属性:接口的属性只能是常量 或者被 final 修饰的变量
注意:
1.1、属性是默认被 public static final 修饰的
1.2、声明属性的时候必须给他赋值 -
构造方法:接口没有构造方法,所以接口不可以创建对象
3. 行为:jdk1.8 之前接口只有抽象方法;【抽象方法就是行为声明的表现形式】
代码示例
package com.ujiye.demo;
public interface InterfaceA {
//接口内容
//属性
/*public static final*/
int a = 10;//默认被public static final 修饰
public static final int b = 30 ;
//行为
public abstract void run();
}
-
接口和抽象类的区别:
1、抽象类是对子类的共性行为声明的提取【子类要求是同一系列的类局限性小】
2、接口是对不同系列的事物的共性行为声明的提取【就没有局限性】
3、抽象类是被类继承的,接口只能被类实现
Effective Java - 嵌套类 (内部类)
嵌套类是指被定义在另一个类内部的类。
概念
嵌套类 (nested class) 是指被定义在另一个类内部的类。嵌套类的存在目的应该只是为外围类 (enclosing class) 提供服务。嵌套类有四种:
- 静态成员类 (static member class);
- 非静态成员类 (nonstatic member class);
- 匿名类 (anonymous class);
- 局部类 (local class)。
除了第一种外,其他三种都被成为内部类 (inner class)。静态嵌套类, 就是用 static 修饰的成员嵌套类。InnerClass, 也就是没有用 static 定义的 nested classes,Inner Classes 不能定义为 static,不能有 static 方法和 static 初始化语句块
静态成员类
- 可以访问外围类的所有成员,非静态成员需要实例化外围类才能访问。
- 如果静态成员类是私有的,只能在外围类的内部才能访问。
- 外围类外部实例化静态成员类:外围类。静态成员类,
OuterStaticInnerClass.PublicInnerCLass publisInnerCLass = new OuterStaticInnerClass.PublicInnerCLass();
- 私有静态成员类一种常见用法是用来代码外围类所代表的对象的组件。
`
代码示例
public class OuterStaticInnerClass {
private String teacher;
private static int grade;//年级
private static String className;//班级名称
public OuterStaticInnerClass() {
this.grade = 1;
this.className = "高三";
this.teacher="王莉";
}
public void outerPrint() {
System.out.println("OuterStaticInnerClass.outerPrint");
System.out.println(className + grade + "班的老师是:" + teacher);
}
public static class PublicInnerCLass {
private int age;//年龄
private String name;//名字
//构造方法
public PublicInnerCLass() {
}
public PublicInnerCLass(int age, String name) {
this.age = age;
this.name = name;
}
public String print() {
//静态类可以访问外围类的成员
new OuterStaticInnerClass().outerPrint();
System.out.println("OuterStaticInnerClass:PublicInnerCLass");
return name + " 年龄:" + age + ",班级:" + className + Integer.toString(grade)+"班,老师:"+new OuterStaticInnerClass().teacher;
}
}
private static class PrivateInnerCLass {
private int age;//年龄
private String name;//名字
public PrivateInnerCLass() {
}
public PrivateInnerCLass(int age, String name) {
this.age = age;
this.name = name;
}
public void print() {
System.out.println("OuterStaticInnerClass:PrivateInnerCLass");
System.out.println(name + " 年龄:" + age + ",班级:" + className + Integer.toString(grade) + "班,老师:" + new OuterStaticInnerClass().teacher);
}
}
}
实例化
/** * 静态成员类 */
public static void outerStaticInnerClassTest() {
OuterStaticInnerClass outerStaticInnerClass = new OuterStaticInnerClass();
//静态成员类实例化
OuterStaticInnerClass.PublicInnerCLass publisInnerCLass = new OuterStaticInnerClass.PublicInnerCLass(18, "lis");
//chapter4.item22.OuterStaticInnerClass.PrivateInnerCLass'' has private access in ''chapter4.item22.OuterStaticInnerClass
//如果静态成员类是私有的,只能在外围类的内部才能访问
//OuterStaticInnerClass.PrivateInnerCLass privateInnerCLass=new OuterStaticInnerClass.PrivateInnerCLass();
System.out.println(publisInnerCLass.print());
}
非静态成员类
- 非静态成员类的实例方法内部可以调用外围实例的方法。
- 在没有外围实例的情况下,创建非静态成员类的实例是不可能的。
- 非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。
代码示例
public class OuterNonStaticInnerClass {
private String teacher;
private static int grade;//年级
private static String className;//班级名称
public OuterNonStaticInnerClass() {
this.grade = 1;
this.className = "高三";
this.teacher = "王莉";
}
public void outerPrint() {
System.out.println("OuterNonStaticInnerClass.outerPrint");
System.out.println(className + grade + "班的老师是:" + teacher);
}
public class PublicInnerCLass {
private int age;//年龄
private String name;//名字
//构造方法
public PublicInnerCLass() {
}
public PublicInnerCLass(int age, String name) {
this.age = age;
this.name = name;
}
public String print() {
// 非静态成员类的实例方法内部可以调用外围实例的方法和变量。
outerPrint();
System.out.println("OuterStaticInnerClass:PublicInnerCLass");
return name + " 年龄:" + age + ",班级:" + className + Integer.toString(grade) + "班,老师:" + teacher;
}
}
private class PrivateInnerCLass {
private int age;//年龄
private String name;//名字
public PrivateInnerCLass() {
}
public PrivateInnerCLass(int age, String name) {
this.age = age;
this.name = name;
}
public void print() {
System.out.println("OuterStaticInnerClass:PrivateInnerCLass");
System.out.println(name + " 年龄:" + age + ",班级:" + className + Integer.toString(grade) + "班,老师:" + teacher);
}
}
}
实例化
public static void outerNonStaticInnerClassTest(){
//类内部实例化
// 非静态成员类的实例方法内部可以调用外围实例的方法。
//在没有外围实例的情况下,创建非静态成员类的实例是不可能的。
//非静态成员类的每个实例都隐含着与外围类的一个外围实例相关联。
OuterNonStaticInnerClass outerClass = new OuterNonStaticInnerClass();
//chapter4.item22.OuterNonStaticInnerClass.PrivateInnerCLass'' has private access in ''chapter4.item22.OuterNonStaticInnerClass
//OuterNonStaticInnerClass.PrivateInnerCLass privateInnerCLass = outerClass.new PrivateInnerCLass();
//privateInnerCLass.print();
OuterNonStaticInnerClass.PublicInnerCLass publicInnerCLass = outerClass.new PublicInnerCLass(18, "lis");
System.out.println(publicInnerCLass.print());
}
匿名内部类
- 匿名类没有名字,不是外围类的一个成员,不与其他成员一起被声明。
- 只能在使用的同时被声明和实例化,没有构造方法。
- 当且仅当匿名类出现在非静态的环境中时,才有外围实例。
- 即使匿名类出现在静态的环境中,也不可能拥有任何静态成员。
- 匿名类不能实现接口或者扩展一个类。
- 除了从它的超类型中得到之外,匿名类的客户端无法调用任何任何成员。
- 常见用法:①动态创建函数对象;②创建过程对象,比如 Runnable、Thread;③用于静态工程方法的内部
代码示例
public interface OuterAnonymousInnerInter {
public void print(int age, String name);
}
public abstract class OuterAnonymousInnerClass {
//成员方法
public abstract void innerMethod(int age, String name);
}
实例化
public static void outerAnonymousInnerInterTest() {
OuterAnonymousInnerInter innerInter = new OuterAnonymousInnerInter() {
private String teacher = "王莉";
@Override
public void print(int age, String name) {
System.out.println("OuterAnonymousInnerInter anonymous inner class");
System.out.println(name + " 年龄:" + age + "老师:" + teacher);
}
};
innerInter.print(18, "lis");
OuterAnonymousInnerClass outerClass = new OuterAnonymousInnerClass() {
private String teacher = "王莉";
@Override
public void innerMethod(int age, String name) {
System.out.println("OuterAnonymousInnerClass innerMethod");
System.out.println(name + " 年龄:" + age + "老师:" + teacher);
}
};
outerClass.innerMethod(18, "lis");
}
局部类
- 在任何 “可以声明局部变量” 的地方,都可以声明局部类。
- 是四种嵌套类中用的最少的。
- 局部类不能有访问控制符 (private,public,protected 修饰),可以是抽象的,也可以定义为 final。
代码示例
public class OuterLocalInnerClass {
private String teacher;//老师
private static int grade;//年级
private static String className;//班级名称
public OuterLocalInnerClass() {
this.grade = 1;
this.className = "高三";
this.teacher = "王莉";
}
//局部类
public void innerMethod() {
class InnerCLass3 {
private int age;//年龄
private String name;//名字
public InnerCLass3(int age, String name) {
this.age = age;
this.name = name;
}
}
InnerCLass3 innerCLass3=new InnerCLass3(18, "lis");
System.out.println(innerCLass3.name + " 年龄:" + innerCLass3.age);
System.out.println(className + grade + "班的老师是:" + teacher);
}
}
实例化
public static void outerLocalInnerClassTest(){
OuterLocalInnerClass outerClass=new OuterLocalInnerClass();
outerClass.innerMethod();
}
lis 年龄:18
高三1班的老师是:王莉
推荐
java 嵌套类 (Nested Classes) 总结
Java - 内部类
参考我最喜欢的一本书,李刚《疯狂 java 讲义》第 6 章
一。内部类的访问控制修饰符
1. 外部类的上一级单元是包,所以它只有两个作用域:同一个包内和任何位置。所以外部类有包访问权限(即默认的,没有修饰符)和 public。
2. 内部类的上一级程序单元是外部类,它有四个作用域:同一个类 private,同一个包 default,父子类 protected 和 public
二。非静态内部类
1. 非静态内部类的方法访问某个变量时,系统查找顺序为:
该方法内的局部变量 --〉 内部类的局部变量 --〉 外部类的成员变量,都查找不到则编译出错。
如果外部类成员变量、内部类成员变量、内部类里的方法的局部变量重名,则可用外部类类名.this、this 作为限定来区分。
1 public class OutClass {
2 private String str = "外部类的成员变量";
3 private class InClass{
4 private String str = "内布类的成员变量";
5 public void test(){
6 String str = "局部变量";
7 //通过外部类类名.this.varName 访问外部类实例变量
8 System.out.println(OutClass.this.str);
9 //通过this.varName 访问内部类实例变量
10 System.out.println(this.str);
11 //直接访问局部变量
12 System.out.println(str);
13 }
14 }
15
16 public static void main(String[] args) {
17 new OutClass().new InClass().test();
18 }
19 }
输出结果为:
外部类的成员变量
内布类的成员变量
局部变量
2. 非静态内部类的成员可以访问外部类的 private 成员,但反过来就不成立了。而且非静态内部类 public 成员也不可以被外部类直接访问。
非静态内部类的成员只有在非静态内部类范围内可知,并不能被外部类直接使用。可以通过创建非静态内部类对象来调用访问其实例成员。
** 非静态内部类对象必须寄生在外部类对象里,而外部类对象则不一定有非静态内部类对象寄生其中。因此外部类对象访问非静态内部类成员时,可能非静态内部类对象根本不存在!而非静态内部类对象访问外部类成员时,外部类对象一定存在。
3. 非静态内部类里不能有静态方法、静态成员变量、静态初始化块,可以包含普通初始化块。
二。静态内部类
1. 静态内部类访问外部类
静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实力成员,只能访问外部类的类成员,即使是静态内部类的实例方法也不可访问外部类的实例成员。
2. 外部类访问静态内部类
外部类依然不能直接访问静态内部类成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的静态成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员。
* 静态内部类是外部类的类相关的,而不是外部类的对象相关的。也就是说,静态内部类对象不是寄生在外部类的实例中,而是寄生在外部类的类本身中。当静态内部类对象存在时,并不存在一个被它寄生的外部类对象。静态内部类对象只持有外部类的类引用,没有外部类对象的引用。
三。在外部类以外使用内部类
1. 访问权限
默认(default):只能被与外部类处于同一个包中的其他类访问。
protected:可被与外部类处于同一个包中的其他类和外部类的子类访问。
2. 在外部类以外使用非静态内部类
非静态内部类需要寄生在外部类的对象里,所以创建非静态内部类对象之前需要先创建外部类对象,语法如下:
Out.In in = new Out ().new In (); 也可以拆成两步,即:
Out out = new Out();
Out.In in = out.new In();
3. 在外部类以外使用静态内部类
因为静态内部类是外部类的类相关的,因此创建静态内部类对象时无需创建外部类对象,语法如下:
Out.StaticOutIn in = new Out.StaticIn();
四。匿名内部类
1. 语法:
new 接口 ()| 抽象类构造器 (参数列表)| 父类构造器 (参数列表){
// 匿名内部类的类体部分
}
由此可知:匿名内部类必须且只能继承一个父类或实现一个接口或者实现一个抽象类。
由于匿名内部类没有类名,所以不能定义构造器,但匿名内部类可以定义初始化块来完成构造器需要完成的事情。
2.final 修饰的局部变量才可被匿名内部类使用
1 package test;
2
3 public class Test {
4 public void testClass(TestClass t){
5 System.out.println("已进入testClass------------------------");
6 t.test();
7 }
8
9 public void testAbstract(TestAbstract t){
10 System.out.println("已进入testAbstract------------------------");
11 t.test("===抽象类测试方法");
12 }
13
14 public void testInterface(TestInterface t){
15 System.out.println("已进入testInterface------------------------");
16 t.test("===接口测试方法");
17 }
18
19 public static void main(String[] args) {
20 Test t = new Test();
21 //final修饰的局部变量才可被匿名内部类使用,(Java8更智能可以自己加)
22 final String str = "局部变量";
23 //测试继承类,并在匿名内部类中重写父类测试方法
24 t.testClass(new TestClass("---被匿名内部类测试中。。。"){
25 public void test(){
26 System.out.println("继承类时的匿名内部类重写测试方法");
27 System.out.println("测试在匿名内部类中使用局部变量-=-=-"+str);
28 }
29 });
30
31 //测试实现抽象类,并在匿名内部类中重写抽象类测试方法
32 t.testAbstract(new TestAbstract("---被匿名内部类测试中。。。"){
33
34 @Override
35 //匿名内部类实现抽象类时必须重写其抽象方法
36 void test(String str) {
37 // TODO Auto-generated method stub
38 System.out.println("匿名内部类重写的抽象类测试方法"+str);
39 }
40
41 });
42
43 //测试实现接口
44 t.testInterface(new TestInterface(){
45
46 @Override
47 //匿名内部类实现接口时必须重写其抽象方法
48 public void test(String str) {
49 // TODO Auto-generated method stub
50 System.out.println("匿名内部类重写的接口测试方法"+str);
51 }
52
53 });
54
55 }
56 }
57
58 class TestClass{
59 public TestClass(String str){
60 System.out.println("父类有参构造器"+str);
61 }
62
63 public void test(){
64 System.out.println("父类测试方法");
65 }
66 }
67 abstract class TestAbstract{
68 public TestAbstract(String str){
69 System.out.println("抽象类有参构造器"+str);
70 }
71 abstract void test(String str);
72 }
73 interface TestInterface{
74 void test(String str);
75 }
76 运行结果:
77 父类有参构造器---被匿名内部类测试中。。。
78 已进入testClass------------------------
79 继承类时的匿名内部类重写测试方法
80 测试在匿名内部类中使用局部变量-=-=-局部变量
81 抽象类有参构造器---被匿名内部类测试中。。。
82 已进入testAbstract------------------------
83 匿名内部类重写的抽象类测试方法===抽象类测试方法
84 已进入testInterface------------------------
85 匿名内部类重写的接口测试方法===接口测试方法
java - 抽象类、接口、内部类
微博:http://weibo.com/xtfggef
出处:http://blog.csdn.net/zhangerqing
抽象类与接口:
这两个概念总是被放在一起讨论,因为他们有很多相似的地方,可以说接口本身就是完全抽象的,它要比抽象类更加 “抽象”,为什么这么说?抽象类是一种类,里面除了有抽象方法外,还可以有具体的方法,而接口里面必须都是抽象的方法(有时可以在接口里定义类,后面会讲),尽管有时并没有显示的用 abstract 关键字声明。此处我们提到抽象方法,在 Java 中,凡是声明为形如:abstract void function () 的方法,都是抽象方法,包含抽象方法的类就是抽象类,可以这么总结:抽象类中是可以没有抽象方法的;有抽象方法的类必须是抽象类;抽象类不一定有实体方法。
public class Run {
public Runnable run22() {
return new Runnable() {
public void run() {
System.out.println("run~~");
}
};
}
public static void main(String[] args) {
new Run().run22().run();
}
}
- public class B extends A {
- @Override
- void a() {
- System.out.println();
- }
- }
- abstract class A {
- abstract void a();
- void b(){
- }
- }
当我们继承抽象类时,必须重写其抽象方法。因为上述原因,所以抽象类不能被声明为 final 类型的,因为加 final 关键字的类保证不能被继承,因此为抽象类加 final 关键字,这个类就没法用了。抽象类只能被继承,不能被实例化!
声明为 interface 的类为接口,比抽象类更加抽象的一种机制。在接口中,我们不能提供任何实现,所有方法必须都是抽象的,可以不加 abstract 关键字,但是编译器对于接口中的方法,都是直接按抽象方法处理的。我们通过 implements 来实现某个接口。当我们实现某个接口时,必须重写其所有方法。
Java 多继承
之前我们知道,采用 interface 为我们提供了一种将抽象与实现分离的结构化的方法,但是 interface 的作用远不止此,在 Java 中接口解决了一个非常重要的问题:多继承。在 C++ 中,实现多重继承是比较简单的事儿,但是 Java 继承机制不允许多重继承,所以如果想要整合不同类的功能,就需要使用接口,我们来看个例子:
- interface CanFight {void fight();}
- interface CanFly {void fly();}
- interface CanSwim {void swim();}
- class ActionCharacter {public void fight(){}}
- class Hero extends ActionCharacter implements CanFight, CanFly, CanSwim {
- @Override
- public void swim() {}
- @Override
- public void fly() { }
- }
- public class Adventure {
- public static void t(CanFight x){x.fight();}
- public static void u(CanSwim x){x.swim();}
- public static void v(CanFly x){x.fly();}
- public static void w(ActionCharacter x){x.fight();}
- public static void main(String[] args) {
- Hero h = new Hero();
- t(h);
- u(h);
- v(h);
- w(h);
- }
- }
我们可以看到:
1、Hero 类中拥有了所有类的功能。
2、Hero 可以和它实现的这些接口进行相互转换,当我们将 hero 对象做参数,传入 Adventure 类的各个方法时,Hero 类向上转型了。(此处我们得出了一句话:在 Java 中,接口可以和实现了该接口的类相互转换)。讲到此处,我想总结下使用接口的好处:
1、接口可以实现向上转型,多个具有共同属性的类可以将它们的共同点提取出来,做成抽象,这样层次分明,统一管理。
2、接口不具有任何实现,最适合做基类。
总结一下抽象类与接口的区别和联系:
a) 抽象类是类,可以有实体方法。
b) 抽象类不能实现多继承,而接口可以。
c) 如果需要创建不带任何方法定义和成员变量的基类,则使用接口,如果类中需要有部分具体的实现,则使用抽象类。
d) 如果事先想要将某类设计为一个基类,那么首选接口。(注意 c 和 d 是接口的使用场景)
接口可以通过继承 (extends) 接口,来拓展功能。接口中的域默认是 final、static 的,我们可以通过类名来直接引用。
内部类
创建:内部类的意思就是将类的定义放在另一个类的内部。有时合理的内部类使用会使代码更加简洁,令程序更加巧妙。而且作为外部类的成员,内部类可以访问外部类私有的成员变量。我们先来看看内部类的创建,分这么几种情况:
1、在外部类的非静态方法中创建内部类的实例。
- public class InnerClass {
- class A{
- int a = 10;
- void b(){
- System.out.println("this is A.b()!");
- }
- }
- void build(){
- A a = new A();
- a.b();
- }
- public static void main(String[] args) {
- InnerClass ic = new InnerClass();
- ic.build();
- }
- }
2、在外部类的静态方法中创建内部类的实例。
当在外部类的静态方法中创建内部类时,当内部类是静态的:
- public class InnerClass {
- static class A{
- int a = 10;
- void b(){
- System.out.println("this is A.b()!");
- }
- }
- public static void main(String[] args) {
- InnerClass.build();
- }
- static void build(){
- A a = new A();
- a.b();
- }
- }
当内部类是非静态的:
- public class InnerClass {
- class A{
- int a = 10;
- void b(){
- System.out.println("this is A.b()!");
- }
- }
- public static void main(String[] args) {
- InnerClass ic = new InnerClass();
- InnerClass.A aa = ic.new A();
- aa.b();
- }
- }
3、在内部类的非静态方法中创建外部类的实例。(使用外部类.this 来创建外部类的实例)
- public class InnerClass {
- class A{
- int a = 10;
- void build(){
- InnerClass ic = InnerClass.this;
- ic.a();
- }
- }
- void a(){
- System.out.println("this is InnerClass.a()!");
- }
- }
4、在内部类的静态方法中创建外部类的实例。(直接通过 new 来创建)
- public class InnerClass {
- static class A{
- int a = 10;
- static void build(){
- InnerClass ic = new InnerClass();
- ic.a();
- }
- }
- void a(){
- System.out.println("this is InnerClass.a()!");
- }
- }
5、在其它类中创建内部类实例。(重点)
- public class InnerClass {
- class A{
- void a(){
- System.out.println("this is A.a()!");
- }
- }
- static class C{
- void c(){
- System.out.println("this is C.c()!");
- }
- }
- }
- class B{
- public static void main(String[] args){
- /* 创建非静态内部类 */
- InnerClass ic = new InnerClass();
- A a = ic.new A();
- a.a();
- /* 创建静态内部类 */
- C c = new C();
- c.c();
- }
- }
来看个深层嵌套的:
- public class ABC {
- void a() {
- System.out.println("this is A.a()!");
- }
- class B {
- void b() {
- System.out.println("this is B.b()!");
- }
- class C {
- void c() {
- a();
- b();
- System.out.println("this is C.c()!");
- }
- }
- }
- public static void main(String[] args) {
- ABC abc = new ABC();
- ABC.B b = abc.new B();
- ABC.B.C c = b.new C();
- c.c();
- }
- }
感觉越来越有意思了!此处最重要的就是这个”.new” 操作符。同时,在类 C 内部调用 a () 和 b () 都很轻松,就说明内部类就相当于一个普通的变量,哪怕是 private 权限的,也一样,直接调用,因为它们在同一个类中。匿名内部类的创建:
- interface A {
- void a();
- }
- public class InnerClass_NoName {
- public A test() {
- return new A() {
- public void a() {
- System.out.println("");
- }
- };
- }
- public static void main(String[] args) {
- InnerClass_NoName icn = new InnerClass_NoName();
- A a = icn.test();
- a.a();
- }
- }
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了 “多重继承”。一般情况,内部类不宜过长,否则就会显得头重脚轻。
使用匿名内部类应该注意:
a) 匿名内部类不能有构造方法
b) 匿名内部类不能定义任何静态成员、方法和类。
c) 匿名内部类不能是 public,protected,private,static。
d) 只能创建匿名内部类的一个实例。
e) 一个匿名内部类一定是在 new 的后面,用其隐含实现一个接口或实现一个类。
f) 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
嵌套类:
普通的内部类持有外围类的一个引用,所以可以与外部类保持联系,而当我们需要嵌套类的时候,我们需要使用 static 关键字,这样内部类就断开了和外部类的联系,不能从内部类的对象中访问非静态的外部类。
- public class InnerClass {
- static class A{
- static int a = 10;
- static void a(){
- System.out.println("this is A.a()!");
- }
- }
- }
接口内部的类:
- public interface Interface_Class {
- void say();
- class IC implements Interface_Class{
- @Override
- public void say() {
- System.out.println("hello");
- }
- public static void main(String[] args) {
- new IC().say();
- }
- }
- }
适合于创建公共代码,供所有实现了该接口的类使用。
内部类的继承,我们说过,内部类持有对外部类的引用,所以,在继承的时候,我们需要初始化这个 “隐藏” 着的引用,请看下面的代码:
- class AAA {
- class BBB {
- }
- }
- public class InnerClass_Extends extends AAA.BBB {
- public InnerClass_Extends(AAA aaa) {
- aaa.super();
- }
- public static void main(String[] args) {
- AAA aaa = new AAA();
- InnerClass_Extends ice = new InnerClass_Extends(aaa);
- }
- }
最后,我们总结下使用内部类的原因:每个内部类都能独立继承自一个接口的实现,和外部类没有任何关系(不论外部类是否实现了该接口)。
说的再简单一点就是,内部类是 Java 多继承机制的完美补充,为什么这样说?我们说过,实现多继承靠的是接口,光从类的角度说是没有多继承一说的。但是,如果现在非得用抽象类实现多继承,很明显是不可能的,此处就必须使用内部类。举个例子:
- class AA{
- }
- abstract class BB{
- }
- class CC extends AA{
- BB makeB(){
- return new BB(){
- };
- }
- }
- public class Multi_Extends {
- static void takesA(AA a){}
- static void takesB(BB b){}
- public static void main(String[] args) {
- CC c = new CC();
- takesA(c);
- takesB(c.makeB());
- }
- }
这样就实现了继承内部类。
我们今天的关于Java 内部类和java内部类怎么写的分享就到这里,谢谢您的阅读,如果想了解更多关于Eclipse 快捷键;包;权限修饰符;内部类;抽象类;接口概念和定义 (Java Day09)、Effective Java - 嵌套类 (内部类)、Java - 内部类、java - 抽象类、接口、内部类的相关信息,可以在本站进行搜索。
本文标签: