内部类:
将一个类定义在另一个类的内部,内部的类称为内部类;
如:
public class A{
public class B{
//省略
}
}
特点:
- 内部类可以很好的实现隐藏,可以使用protect、private修饰。
- 内部类可以访问外部类的所有成员,包括私有成员。
- 外部类不能直接访问内部类的成员,必须要建立内部类的对象才可访问。
- 内部类可以解决一些问题,比如间接的去实现多继承。可以避免修改接口而实现同一个类中两个同名的方法调用。
成员内部类
特点:
- 成员内部类属于外部类的实例成员,成员内部类可以有public、private、default、protect权限修饰符。在成员内部类中访问外部类的方法和属性,要用"外部类名.this.成员方法"和"外部类名.this.成员属性"的形式。
- 创建成员内部类的实例使用"外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)"的形式
限制:
- 成员内部类不能与外部类重名;
- 不能再内部类定义static属性、方法 和类(static fianl形式的常量定义除外)。因为一个成员内部类必定与一个成员外部类实例关联,static成员完全可以移除到外部类去;
class Main{
public static void mian(String [] args){
//创建外部类对象
Outer outer = new Outer();
//创建内部类对象
Outer.Inner inner = outer.new Inner();
inner.innerShow();
}
}
class Outer{
private String name = "李四";
private int age = 10;
public void outerShow(){
System.out.printf(name );
System.out.printf(age );
// System.out.printf(hiegt); 外部类不能直接访问内部类属性
}
class Inner{
private String name = "张三";
private int hiegt =55;
public void innerShow(){
System.out.printf(name);
System.out.printf(Outer.this.name); //内部类访问外部类属性
outerShow(); //内部类可以直接访问外部类方法
System.out.printf(hiegt);
}
}
}
静态内部类
特点:
- 使用static修饰的成员内部类叫静态内部类;
- 静态内部类跟外部类无任何关系,只是在生成类名和类定义时有影响。静态内部类可以看作与外部类平级的类。使用方法与外部类完全相同。
- 创建静态内部类的实例使用 外部类名.内部类名 实例名 = new 外部类名.内部类名(参数);
限制:
- 静态内部类不能与外部类重名;
- 静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问内部类的非静态的属性和方法;
class Main{
public static void mian(String [] args){
//创建一个静态内部类对象
Outer.Inner inner = new outer.Inner();
inner.innerShow();
}
}
class Outer{
private String name = "李四";
private int age = 10;
private static int weight = 10;
public void outerShow(){
System.out.printf(name );
System.out.printf(age );
}
public static class Inner{
private String name = "张三";
private int hiegt =55;
public void innerShow(){
System.out.printf(name);
// System.out.printf(Outer.this.name); 静态内部类不能访问外部类非静态成员
System.out.printf(Outer.weight);
}
}
}
匿名内部类
特点:
- 匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部风来说声明并创建它们的实例
- 匿名内部类必须继承一个个类(抽象、非抽象的)或实现一个接口。如果父类是抽象类,则内部类必须实现其所有抽象方法
- 匿名内部类可以定义代码块,用与实例的初始化,但不能定义静态代码块
语法:
new interfance/superclass(){ // 类体 }
这种形式的new语句声明一个新的匿名类,它对一个给定的类进行拓展,或者实现一个给定的接口,并同时创建该匿名类的新实例。
public class Mian{
public static void main(String [] args){
A a = new A();
// B c = new C();
// a.feed(c);
//匿名内部类写法
a.feed(new B(){
public void eat(){
System.out.printf("吃东西");
}
});
}
}
class A{
public void feed(B b){
b.eat();
}
}
class B{
public abstract void eat();
}
/*
class C extends B{
public void eat(){
System.out.printf("吃东西");
}
}*/
局部内部类
特点:
- 定义在代码块、方法体内的类叫局部类
- 局部内部类访问外部类的属性、方法使用“外部类名.this.属性名” 和“外部类名.this.方法名(参数)”
- 对外部世界完全隐藏,只能在其作用域内生成对象
限制:
- 局部内部类不能加访问修饰符,因为他们不是类成员。
- 局部内部类不能与外部类重名
- 局部内部类访问的作用域的局部变量,该局部变量需要用final修饰
class Main{
public static void main(String [] args){
Outer outer = new Outer();
outer.showOuter();
}
}
class Outer{
private String name = "张三";
Private int num =10;
private static int num1 =19;
public void showOuter(){
fianl int num3 = 50;
//局部内部类不能加访问修饰词
class Inner{
private int name4 = 60;
Private int num =130;
public void showInner(){
System.out.printf(num4);
System.out.printf(Outer.num1); //访问外部类静态属性
System.out.printf(Outer.this.num); //访问外部类属性
System.out.printf(num3 ); //局部内部类只能访问声明其方法中的常量
}
}
Inner inner = new Inner();
inner.showInner();
}
}
使用内部类开发一个存放数据的容器:
public class Main{
public static void main(String [] args){
MyContainer myContainer new MyContainer ();
myContainer.put("wsd","kl");
myContainer.put("wsdsd","uyrt");
myContainer.put("wsfwewed","ytn");
myContainer.put("wstrwyed","4v");
myContainer.put("wcssd","ggkl");
MyContainer.Entry [] entrys = myContainer.entryArrays();
for(int i=0;i<entrys.length;i++){
MyContainer.Entry entry =entrys[i];
System.out.printf(entry.getKey() +"---"+entry.getValue());
}
}
}
class MyContainer{
priavte Entey [] enteys = new Entey [5];
private int count =0;
//对外提供一个接口向容器中存放封装好的数据(Entey 对象)
public void put (String key,String value){
Entey entey = new Entey();
entey.setKey(key);
entey.setValue(value);
enteys[count++] = entey;
//数组的扩容
if(enteys.length <= count){
int newCapactiy =entrys.length*2;
//把老数组中的数据拷贝到新数组中去
entrys = Array.copyOf(entrys,newCapactiy );
}
}
//把容器中有数据的内容返回
public Entery[] entryArrays(){
return Arrays.copyOfRange(entrys,0,count);
}
//把键值封装在Entey 对象中
public static Class Entry{
private String key;
private String value;
public void setKey(String key){
this.key = key;
}
public void getKey(String key){
return key;
}
public void setValue(String value){
this.value= value;
}
public void getValue(String value){
return value;
}
}
}