内部类
1.简介:
大部分时候,类被定义为一个独立的程序单元,在某些情况下,也会把一个类放在另外一个类的内部定义,这种类就被称为内部类(嵌套类),包含内部类的类也被称为外部类(宿主类)
2.作用:
*内部类提供了更好的封装,可以将内部类隐藏在外部类之内,不允许同一个包中其他类访问该类。内部类只有在外部类中才有用
*内部类的成员可以直接去访问外部类的私有数据,因为内部类被当做外部类的成员变量,但是外部类不能访问内部类的实现细节(比如说内部类的成员变量)
*匿名内部类适合那些创建只使用一次的类
3.内部类和外部类的区别
*内部类比外部类可以多使用三个修饰符:private,protected,static
*非静态内部类不能拥有静态成员(不能用static修饰)
非静态内部类
1.定义
定义方法其实很简单,就是把一个类放在另外一个类内部定义即可
public class OuterClass{
//可以定义内部类
}
2.举个栗子
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 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 CowLeg(){}
//定义构造器
public CowLeg(double length,String color){
this.color=color;
this.length=length;
}
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public void test(){
CowLeg c1=new CowLeg(1.12,"黑白相间");
c1.info();
}
public static void main(String[]args){
Cow cow=new Cow(378.9);
cow.test();
}
}
*外部类只能使用public 或者默认限定,但是内部类可以使用 public private protected和default(默认)进行限定
*通过上述例子也可以证明内部类可以直接访问外部类的private属性、
*其实每一个内部类中都包含着其外部类的引用!!!,所以在内存中才可以将内部类和外部类进行联系
静态内部类
1.简介:
如果使用static来修饰一个内部类,这个内部类属于外部类本身(类相关),而不属于外部类的某个对象(实例相关)。所以使用static修饰的内部类称为静态内部类,也被称为类内部类。
2.使用原则:
静态内部类可以包含静态成员,也可以包含非静态成员。因为静态成员不能去访问非静态成员,所以静态内部类不能去访问外部类的实例成员,只能访问外部类的static成员
3.举个栗子:
/**
* static的作用是把类的成员变成类相关而不是实例相关(对象相关)
* 使用static修饰内部类后,静态内部类可以包含静态成员,也可以包含非静态成员。静态内部类不能访问外部类的实例成员(只能访问类成员)
*
* 类属性:
* 实例属性:
*
*/
public class StaticInnerClass {
private static int static_num = 1;
private int no_static_num = 2;
static class innerClass {
public void showStaticNum() {
System.out.println("get static num" + static_num);
}
public void showNum() {
//error
//System.out.println(no_static_num);
}
}
public static void main(String[] args) {
StaticInnerClass.innerClass innerClass = new StaticInnerClass.innerClass();
innerClass.showStaticNum();
}
}
*java允许在接口内定义内部类,接口中定义的内部类默认使用public static修饰(接口内部类只能是静态内部类,接口内部默认为public访问权限)
匿名内部类
1.使用条件:
匿名内部类必须要继承一个父类或者实现一个接口,但是最多只能继承一个父类或者实现一个接口
*匿名内部类不能是抽象类,系统在创建匿名内部类的时候会自动创建对象
*匿名内部类没有类名 不能定义构造器,但是可以定义初始化块来完成构造器需要做的事情
2.举个栗子
使用接口的匿名内部类
/**
* 使用匿名内部类
* 1.必须继承一个父类或者实现一个接口,但是最多只能继承一个父类或者实现一个接口
* 2.匿名内部类不能是抽象类,系统在创建匿名内部类时,会立即创建匿名内部类的对象
* 3.匿名内部类不能定义构造器,因为是匿名的 没有类名
* 4.在java8开始之前,java被要求局部内部类。匿名内部类访问的局部变量必须使用final修饰,在java8之后,自动化
*/
interface Product {
public double getPrice();
public String getName();
}
public class AnnoymousTest {
public void test(Product p) {
System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice());
}
public static void main(String[] args) {
AnnoymousTest ts = new AnnoymousTest();
/**
* 使用匿名内部类
* */
/**
* product只是一个接口,无法直接创建对象
* 如果只是要使用一个 可以使用匿名内部类
* 匿名内部类只有一个隐式的无参构造器
*
*
* c
* */
ts.test(new Product() {
@Override
public double getPrice() {
return 88.88;
}
@Override
public String getName() {
return "商品名";
}
});
/**
* 使用内部类
replaceCode
* */
class AnoymousProduct implements Product {
@Override
public double getPrice() {
return 0;
}
@Override
public String getName() {
return null;
}
}
}
}
继承父类(abstract)的匿名内部类
/**
* 待继承的父类
* */
abstract class Device{
private String name;
public abstract double getPrice();
public Device(){}
public Device(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class AnonymousInner {
public void test(Device d){
System.out.println("购买了一个"+d.getName()+",花掉了"+d.getPrice());
}
public static void main(String[]args){
AnonymousInner ai=new AnonymousInner();
/**
* 使用匿名内部类
* */
ai.test(new Device("toy") {
@Override
public double getPrice() {
return 66.6;
}
});
/**
* replaceCode
* */
Device device=new Device() {
//初始化块
{
System.out.println("匿名内部类的初始化块");
}
@Override
public double getPrice() {
return 66.6;
}
/***
*重写方法
*/
public String getName(){
return"toy2";
}
};
ai.test(device);
}
}