1. java内部类
什么是内部类?将一个类的定义放在另一个类的内部,就是内部类。Java的内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。
public class 外部类的名称{
//外部类的成员
public class 内部类的名称{
//内部类的成员
}
}
内部类的作用;
1)实现多重继承;
2)内部类可以很好的实现隐藏:一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
3)减少了类文件编译后的产生的字节码文件的大小
注意:内部类在编译完成后也会产生.class文件,但文件名称是:外部类名称$内部类名称.class
内部类的种类:成员内部类、静态内部类、局部内部类、匿名内部类。
1.1 成员内部类
1、成员内部类是最普通的内部类,就是一个普通的类定义在另一个类的内部,也叫实例内部类。应用场合:每一个外部类对象都需要一个内部类的实例,内部类离不开外部类存在(相当于心脏对人体)
2、成员内部类的特征:
- 作为外部类的一个成员存在,与外部类的属性、方法并列
- 成员内部类持有外部类的引用
- 成员内部类中不能定义static变量和方法
示例1:
public class StaticInnerClass {
public static void main(String[] args){
Body body=new Body("两个胳膊","两条腿","血");
Body.Heart heart=body.new Heart();
heart.work();
}
}
class Body {
String arm;
String leg;
String blood;
public Body(String arm, String leg, String blood) {
super();
this.arm = arm;
this.leg = leg;
this.blood = blood;
}
//成员内部类Heart
class Heart{
String name;
void work() {
System.out.println("心脏正在给"+arm+leg+"输"+blood);
}
}
}
运行:
心脏正在给两个胳膊两条腿输血
示例2:
public class StaticInnerClass {
public static void main(String[] args){
Outer outer=new Outer();
outer.print();//调用外部类的方法
}
}
class Outer {
private String name="Hello World";
public class Inner{
public void print(){
System.out.println(name); //内部类调用外部类属性
}
}
public void print(){ //定义外部类方法
new Inner().print();//通过内部类的实例化对象调用方法
}
}
运行:
Hello World
1.2 静态内部类
1、内部类如果使用static声明,则此内部类就称为静态内部类。(其实也相当于外部类)可以通过外部类 . 内部类
来访问。
2、静态内部类使用场合:内部类不需要外部类的实例(注意区分成员内部类),静态内部类存在仅仅为外部类提供服务或者逻辑上属于外部类,且逻辑上可以单独存在。
3、静态内部类的特征:
- 静态内部类不会持有外部类的引用
- 静态内部类可以访问外部的静态变量,如果访问外部类的成员变量必须通过外部类的实例访问
4、Java中只有内部类才可以是静态的
使用格式:Outer.Inner inner = new Outer.Inner();
示例1:
public class StaticInnerClass {
public static void main(String[] args){
Company.Clear zcl=new Company.Clear();
zcl.work("shen_hua");
}
}
class Company {
String companyNam;
static String country;
static class Clear{ // 静态内部类
String name;
//无参数的构造函数
public Clear() {
// TODO Auto-generated constructor stub
System.out.println("无参对象初始化");
}
//带参数的构造函数
public Clear(String name) {
super();
this.name = name;
}
// 内部类的非静态方法
public void work(String name){
String na=new Company().companyNam="联想"; // 静态内部类实例化外部类,调用外部类的非静态属性
country="中国"; // 内部类访问外部静态属性
System.out.println(name+"为"+na+"打扫卫生,该公司属于"+country);
}
}
}
运行:
无参对象初始化
shen_hua为联想打扫卫生,该公司属于中国
示例2:
public class StaticInnerClass {
public static void main(String[] args){
Outer.Inner inner=new Outer.Inner();
inner.show();
}
}
class Outer {
private static String info="Hello World";
private int i=8;
static class Inner{
int num=new Outer().i; //通过新建外部类获取外部类的非静态成员变量,而静态成员变量可以直接使用
public void show() {
System.out.println(info+"---"+num);
}
};
}
运行:
Hello World---8
1.3 局部内部类
1、局部内部类也叫区域内嵌类,局部内部类与成员内部类类似,不过,区域内嵌类是定义在一个方法中的内嵌类。
2、使用场合:如果内部类对象仅仅为外部类的某个方法使用,使用局部内部类
3、特征:
- 用在方法内部,作用范围仅限于该方法中
- 根据情况决定持有外部类对象引用
- 不能使用private,protected,public修饰符
- 不能包含静态成员
public class StaticInnerClass {
public static void main(String[] args){
School qinghua=new School("清华","互联网培训",1000);
qinghua.show();
}
}
class School {
String schoolName;
String buss="培养人才";
int studentNum;
public School() {
// TODO Auto-generated constructor stub
}
public School(String schoolName, String buss, int studentNum) {
super();
this.schoolName = schoolName;
this.buss = buss;
this.studentNum = studentNum;
}
// 成员方法:宣传
public void show(){
final double tvMoney=10000;
final double netMoney=20000;
// 局部内部类
class AdverTeam{
String teamName="shen_hua";
public void tvShow(){ //电视宣传
System.out.println("宣传队是:"+teamName);
System.out.println("这是电视宣传,学校名称"+schoolName+",业务内容:"+buss+",学校人数:"+studentNum+",宣传所需费用"+tvMoney);
}
public void netShow(){ //网络宣传
System.out.println("宣传队是:"+teamName);
System.out.println("这是网络宣传,学校名称"+schoolName+",业务内容:"+buss+",学校人数:"+studentNum+",宣传所需费用"+netMoney);
}
}
new AdverTeam().tvShow(); //新建局部类,并调用局部类的方法
new AdverTeam().netShow();
}
}
运行:
宣传队是:shen_hua
这是电视宣传,学校名称清华,业务内容:互联网培训,学校人数:1000,宣传所需费用10000.0
宣传队是:shen_hua
这是网络宣传,学校名称清华,业务内容:互联网培训,学校人数:1000,宣传所需费用20000.0
1.5 匿名内部类
1、如果一个内部类在整个操作中只使用一次的话,就可以定义为匿名内部类。匿名内部类也就是没有名字的内部类,这是java为了方便我们编写程序而设计的一个机制,因为有时候有的内部类只需要创建一个它的对象就可以了,以后再不会用到这个类,这时候使用匿名内部类就比较合适。
2、使用场合:简化内部类的使用
3、特征:
- 使用new创建 ,没有具体位置
- 创建的匿名类,默认继承或实现new后面的类型
- 根据使用情况决定是否持有外部类对象引用
- 内嵌匿名类编译后生成的.class文件的命名方式是”外部类名称$编号.class”,编号为1,2,3…n,编号为x的文件对应的就是第x个匿名类
public class StaticInnerClass {
public static void main(String[] args){
Person p=new Person() {
public void run() {
System.out.println("匿名内部类实现的");
}
};
p.run();
}
}
interface Person {
public void run();
}
运行:
匿名内部类实现的
2. 另一个学习示例 :
package test;
public class StaticInnerClass {
public static void main(String[] args){
Mother mother=new Mother("lucy"); //实例化母亲
mother.getAge();
mother.eat("苹果"); //实例调用非静态方法
new Mother().motherTest1(); // 非静态方法的类调用形式必须是new XXX().XXX()形式调用
Mother.motherTest2(); // 静态方法的类调用的形式可以直接用类名.XXX()或new XXX().XXX()调用
Mother.Baby baby=new Mother.Baby();
Mother.Baby.eat(); // 内部静态类中的类调用静态方法
baby.eat(); // 内部静态类中的实例调用静态方法
new Mother.Baby().childTest1();// 内部静态类中的非静态方法调用
baby.childTest1(); // 内部静态类中的非静态方法调用
baby.childTest2(); // 内部静态类新建外部类对象
}
}
class Mother
{
//定义一个实例变量和一个静态变量
private String name;
private int age; // 私有变量,在类的外部不能访问
private static String food;
private String fruit;//母亲吃的食物
public Mother(){ // 空参构造函数
food="米饭";
}
public Mother(String name){ // 带参构造函数
this.name=name;
}
public String getName(){ //定义非静态方法
return this.name;
}
public void setName(String name){
this.name=name;
}
public void eat(String fruit) {
this.fruit=fruit;
System.out.println(this.name+" 吃了 "+this.fruit);
}
public void getAge(){ //定义非静态方法,外部类对象可以直接私有变量
age=20;
System.out.println("年龄:"+age);
}
public void motherTest1(){ //定义非静态方法 (实例方法)
System.out.println("非静态方法调用静态变量:"+food);
System.out.println("类调用非静态方法");
}
public static void motherTest2(){ //定义静态方法
System.out.println("类调用静态方法");
}
public static void motherdo(){ //静态方法调用静态变量
System.out.println("母亲在吃"+food);
}
// 内部静态类
static class Baby{
static String childfood; // 在静态内部类中定义一个静态变量
int dd; // 一个实例变量
{ //定义一个匿名代码块
System.out.println("我在匿名代码块里。。");
}
static{ //一个静态代码块
System.out.println("我在静态代码块里。。");
}
public static void run(){ // 非静态方法调用
System.out.println("孩子在奔跑。。");
}
public static void eat(){
System.out.println("孩子从母亲吃的 "+ food +" 中吸收营养");
}
public void childTest1(){
//dd=age; //在静态内部类中调用外部类的非静态属性编译出错
childfood=food;
System.out.println("childfood:"+childfood); //在静态内部类中调用外部类的静态属性
motherdo(); //可以直接调用外部类的静态方法
//motherTest1(); //在静态内部类中调用外部类的非静态方法编译出错
}
public void childTest2(){
Mother mm=new Mother();
dd=mm.age;
mm.motherTest1(); //可以通过创建外部类实例来调用外部类的非静态方法
System.out.println("内部类:"+dd); //可以通过创建外部类实例来调用外部类的非静态属性
}
}
}
运行:
年龄:20
lucy 吃了 苹果
非静态方法调用静态变量:米饭
类调用非静态方法
类调用静态方法
我在静态代码块里。。
我在匿名代码块里。。
孩子从母亲吃的 米饭 中吸收营养
孩子从母亲吃的 米饭 中吸收营养
我在匿名代码块里。。
childfood:米饭
母亲在吃米饭
childfood:米饭
母亲在吃米饭
非静态方法调用静态变量:米饭
类调用非静态方法
内部类:0
总结:
1、静态内部类中可以写哪些内容
- 匿名代码块
- 静态代码块
- 静态变量和非静态变量
- 静态方法和非静态方法
注意:不能在静态内部类中写抽象方法
2、外部类如何调用静态内部类中的属性和方法
- 外部类可以通过创建静态内部类实例的方法来调用静态内部类的非静态属性和方法
- 外部类可以直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法
3、静态内部类如何调用外部类的属性和方法
- 静态内部类可以直接调用外部类的静态属性和方法
- 静态内部类可以通过创建外部类实例的方法调用外部类的非静态属性和方法
4、如何创建静态内部类实例
- 在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
- 在外部类中:内部类名 name = new 内部类名();