内部类:定义在其他类内部的类
外部类:包含内部类的类
内部类:
1.成员内部类
⑴静态内部类
⑵非静态内部类
2.局部内部类
优点;
1.提供了更好的封装,把内部类隐藏在外部类中,不允许同一个包中的其他类访问该类;
2.内部类成员可直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问;
3.外部类不能访问内部类的实现细节,如成员变量;
4.匿名内部类适合用于创建仅需要一次使用的类;
5.内部类比外部类可以多使用三个修饰符:public,protected,static——外部类不可以使用
6.非静态内部类不能拥有静态成员。
当调用非静态内部类的实例方法时,必须有一个非静态内部类的实例,这个实例必须寄生在外部类的实例里;
外部类静态成员不能访问非静态内部类;
如果外部类要访问非静态内部类的成员,必须显示创建非静态内部类对象来调用访问其实例成员。
静态内部类是外部类的一个静态成员,因此外部类的静态方法,静态代码块中可以使用静态内部类来定义变量,创建对象;
接口里也可以定义内部类,用public static修饰;
继承父类:
外部类:包含内部类的类
内部类:
1.成员内部类
⑴静态内部类
⑵非静态内部类
2.局部内部类
优点;
1.提供了更好的封装,把内部类隐藏在外部类中,不允许同一个包中的其他类访问该类;
2.内部类成员可直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问;
3.外部类不能访问内部类的实现细节,如成员变量;
4.匿名内部类适合用于创建仅需要一次使用的类;
5.内部类比外部类可以多使用三个修饰符:public,protected,static——外部类不可以使用
6.非静态内部类不能拥有静态成员。
非静态内部类
内部类定义:在类中的任何位置都可以,包括在方法中(在方法里定义个内部类被称为局部内部类);当调用非静态内部类的实例方法时,必须有一个非静态内部类的实例,这个实例必须寄生在外部类的实例里;
外部类静态成员不能访问非静态内部类;
public class Cow {
private double weight;
public Cow(){};
public Cow(double weight)
{
this.weight = weight;
}
private class CowLeg
{
private double length;
private String color;
public CowLeg(){}
public CowLeg(double length,String Color)
{
this.length = length;
this.color = Color;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void info()
{
System.out.println("颜色:"+color+";高:"+length);
System.out.println("体重:"+weight);
}
}
public void test()
{
CowLeg cl = new CowLeg(1.12,"黑白相间");
cl.info();
}
public static void main(String[] args) {
Cow cow = new Cow(666);
cow.test();
}
}
/* 输出结果:
颜色:黑白相间;高:1.12
体重:666.0
*/
public class DisVar {
private String prop = "外部类的实例变量";
private class inclass
{
private String prop = "内部类的实例变量";
public void inof()
{
String prop = "局部变量";
System.out.println(DisVar.this.prop);
System.out.println(this.prop);
System.out.println(prop);
}
}
public void test()
{
inclass in = new inclass();
in.inof();
}
public static void main(String[] args) {
new DisVar().test();
}
}
/*输出结果:
外部类的实例变量
内部类的实例变量
局部变量
*/
如果外部类要访问非静态内部类的成员,必须显示创建非静态内部类对象来调用访问其实例成员。
public class Outer {
private int out = 9;
class Inner
{
private int in = 5;
public void toOut()
{
System.out.println(out);
}
}
public void toIn()
{
//System.out.println(in); 报错
System.out.println(new Inner().in);
}
public static void main(String[] args) {
Outer o = new Outer();
o.toIn();
}
}
静态内部类
如果使用static修饰一个内部类,则成为静态内部类,这个内部类就属于外部类本身,而不属于外部类的某个对象;
静态内部类可以包含静态成员,也可以包含非静态成员,由于静态成员不能访问非静态成员,故静态内部类不能访问外部类的实例成员,只能访问外部类的类成员;
静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。
public class StaticInner
{
private int p = 5;
private static int m = 2;
static class staIn{
private static int age;
public void toOut()
{
//System.out.println(p); 报错
System.out.println(m);
}
}
}
public class Access
{
static class StaticInner
{
private static int p = 5;
private int m = 2;
}
public void access()
{
//System.out.println(p); 报错
System.out.println(StaticInner.p);
//System.out.println(m); 报错
System.out.println(new StaticInner().m);
}
}
接口里也可以定义内部类,用public static修饰;
使用内部类
外部类以外地方定义内部类:
OuterClass.InnerClass varName
1.在外部类中使用内部类
2.在外部类外使用非静态内部类
OuterInstance.new InnerConstructor()
如果要在外部类以外的地方访问内部类,则内部类不能使用private修饰,private修饰的内部类只能在外部类中使用;
省略访问控制符,只能被与外部类处于同一包中的其他类访问;
使用protect修饰的内部类,可被与外部类处于同一包中的其他类和外部类的子类所访问;
使用public修饰的内部类,可以在任何地方被访问;
class Out
{
class In
{
public In(String s)
{
System.out.println(s);
}
}
}
public class CreateInner
{
public static void main(String[] args)
{
Out.In in = new Out().new In("Hello");
/*Out.In in;
Out out = new Out();
in = out.new In("hehe");*/
}
}
3.在外部类外使用静态内部类
在外部类以外的地方创建静态内部类实例语法:
new OuterClass.InnerConstrustor();
class Out
{
static class StaticIn
{
public StaticIn()
{
System.out.println("静态内部类的构造器");
}
}
}
public class test
{
public static void main(String[] args)
{
Out.StaticIn in = new Out.StaticIn();
//Out.StaticIn in;
//in = new Out.StaticIn();
}
}
局部内部类
把一个内部类放在方法里定义,局部内部类仅在该方法里有效,局部内部类不能在外部类的方法以外的地方使用,故不能使用访问控制符和static修饰;
局部内部类的上一级程序单元是方法,不是类;
public class LocalInnerClass
{
public static void main(String[] args)
{
class InnerBase
{
int a;
}
class InnerSub extends InnerBase
{
int b;
}
InnerSub is = new InnerSub();
is.a = 5;
is.b = 6;
System.out.println(is.a + " " + is.b);
}
}
匿名内部类
匿名内部类适合创建那种只需要一次使用的类,创建匿名内部类时会创建一个该类的实例,这个类定义即消失,不能重复使用;
格式:
new 父类构造器(实参列表)|实现接口()
{
//匿名内部类的类体部分
}
匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类或实现一个接口。
规则:
1.匿名内部类不能是抽象类;
2.匿名内部类不能定义构造器,因为没有类名,若是接口,括号里也不能有参数;可以定义实例初始化块来完成构造器需要完成的事情;
3.匿名内部类需要访问外部类的局部变量,必须用final来修饰外部类的局部变量。
interface Product
{
public double getPrice();
public String getName();
}
public class Test
{
public void test(Product p)
{
System.out.println("Price: "+ p.getPrice() + " Name: " + p.getName());
}
public static void main(String[] args)
{
Test t = new Test();
t.test(new Product()
{
public double getPrice()
{
return 100;
}
public String getName()
{
return "hehe";
}
});
}
}
继承父类:
abstract class Device
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract double getPrice();
public Device(){};
public Device(String name)
{
this.name = name;
}
}
public class Outer
{
public void test(Device p)
{
System.out.println("Price: "+p.getPrice()+" Name: "+p.getName());
}
public static void main(String[] args)
{
Outer t = new Outer();
t.test(new Device("hehe")
{
public double getPrice()
{
return 6.21;
}
});
Device d = new Device()
{
//初始化块
{
System.out.println("匿名内部类的初始化块");
}
//实现抽象方法
public double getPrice()
{
return 55.5;
}
public String getName()
{
return "whoami";
}
};
t.test(d);
}
}