目录
访问外部类私有成员
内部类可以访问外部类的私有成员
package Lab4;
public class s {
public static void main(String[] args) {
// TODO 自动生成的方法存根
s S = new s();
s.A a= S.new A();
a.show();
}
private int id=1;
class A{
void show () {
System.out.println(id);
System.out.println(price);
}
}
private int price=10;
}
输出:
1
10
也就是说,内部类可以访问外部类任何位置的私有成员
成员内部类
在一个类(外部类)中将另一个类(内部类)当做其的私有成员
语法格式:
public class OuterClass{ //外部类
private class InnerClass{ //内部类
//...
}
}
当内部类为公有或默认访问时
法一:
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass out=new OuterClass();
OuterClass.InnerClass in=out.new InnerClass();
}
}
class OuterClass{
OuterClass(){
System.out.println("外部类!");
}
// public InnerClass in=new InnerClass();
public class InnerClass{
InnerClass(){
System.out.println("内部类!");
}
}
}
输出:
外部类!
内部类!
法二:
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass out=new OuterClass();
// OuterClass.InnerClass in=out.new InnerClass();
}
}
class OuterClass{
OuterClass(){
System.out.println("外部类!");
}
public InnerClass in=new InnerClass();
public class InnerClass{
InnerClass(){
System.out.println("内部类!");
}
}
}
输出:
内部类!
外部类!
当内部类是私有访问时
上述法一会失效,法二可以输出,即下面的代码可以输出
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass out=new OuterClass();
// OuterClass.InnerClass in=out.new InnerClass();
}
}
class OuterClass{
OuterClass(){
System.out.println("外部类!");
}
public InnerClass in=new InnerClass();
private class InnerClass{
InnerClass(){
System.out.println("内部类!");
}
}
}
局部内部类
内部类位于外部类方法成员里面
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterClass out=new OuterClass();
out.CreateInnerClass();
}
}
class OuterClass{
OuterClass(){
System.out.println("外部类!");
}
void CreateInnerClass() {
class InnerClass{
InnerClass(){
System.out.println("内部类!");
}
}
InnerClass in=new InnerClass();
}
}
输出:
外部类!
内部类!
值得注意的是,当内部类位于方法体内时,是没有private或是public的访问权限的,所以如果有访问权限的关键字时,编译器会报错。
匿名内部类
使用对象名来替代一个类,匿名内部类的所有实现方法均在大括号里面
使用前提和条件:必须存在继承和实现关系的时候才可以使用,其实这也很好理解,首先,匿名内部类没有名字,那该如何描述以及new个对象呢?对,没错,要通过继承它的父类或者实现一个接口来达成这一目的。
补充:
- 1、匿名内部类 :匿名内部类只是没有类名,其他的一概成员都是具备的。
之前说过匿名内部类存在的前提是要有继承或者实现关系的,但是并没有看到extends和implements关键字,这是怎么回事呢?
答:很简单,匿名内部类没有连类名都没有,使用关键字就更无从说起了。这些由jvm搞定了。
格式:
return new A() {
...//内部类体
};
A:对象名
继承父类
使用匿名内部类:
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
new ParentClass() {
void show() {
System.out.println("匿名内部类!");
}
}.show();
}
}
class ParentClass{
void show() {
// TODO Auto-generated constructor stub
System.out.println("继承父类!");
}
}
输出:
匿名内部类!
而不适用匿名内部类:
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ChildClass childClass=new ChildClass();
childClass.show();
}
}
class ParentClass{
void show() {
// TODO Auto-generated constructor stub
System.out.println("继承父类!");
}
}
class ChildClass extends ParentClass{
void show() {
System.out.println("匿名内部类!");
}
}
输出:
匿名内部类!
继承抽象类
当然既然能继承父类,那么自然就可以继承抽象类
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
new ParentClass() {
void show() {
System.out.println("匿名内部类!");
}
}.show();
}
}
abstract class ParentClass{
abstract void show();
}
匿名内部类是实现接口
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
new ParentClass() {//值得注意的是,这里是实现接口的类,而不是创建对象(因为接口不能创建对象)
public void show() {
System.out.println("匿名内部类!");
}
}.show();
}
}
interface ParentClass{
abstract void show();
}
以实参的形式使用
未使用匿名内部类
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Child child=new Child();//法一
run(child);//法一
// run(new Child());//法二
}
public static void run(ParentClass a)//使用static因为在main里没有test类的对象
{
a.show();
}
}
interface ParentClass{
abstract void show();
}
class Child implements ParentClass{
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("未使用匿名内部类");
}
}
使用匿名内部类
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
run(new ParentClass() {
public void show() {
// TODO Auto-generated method stub
System.out.println("匿名内部类");
}
});
}
public static void run(ParentClass a)//使用static因为在main里没有test类的对象
{
a.show();
}
}
interface ParentClass{
abstract void show();
}
当调用方法为多个时
我们知道匿名内部类中只有一个方法时,可以通过上面的方法实现
当调用多个方法时,我们可以通过向上转型的方法来调用
向上转型法(多态法)
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ParentClass aClass=new ParentClass() {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println("调用show");
}
@Override
public void haha() {
// TODO Auto-generated method stub
System.out.println("调用haha");
}
};
aClass.show();
aClass.haha();
}
}
interface ParentClass{
abstract void show();
abstract void haha();
}
this方法
package innerclass;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
new ParentClass() {
@Override
public ParentClass show() {//返回类型
// TODO Auto-generated method stub
System.out.println("调用show");
return this;
}
@Override
public void haha() {
// TODO Auto-generated method stub
System.out.println("调用haha");
}
}.show().haha();//注意顺序是先调用show,而不是先调用haha
}
}
interface ParentClass{
abstract ParentClass show();//注意返回类型
abstract void haha();
}
输出:
调用show
调用haha
静态内部类
在内部类前用static修饰,使其成为静态内部类,静态内部类中可以声明static成员,但是非静态内部类中不可以声明静态成员,这是他们的区别。
静态内部类不能使用外部类的非静态成员
可以这么认为,普通的内部类对象隐式地在外部保存了一个引用,指向创建它的外部类对象,但静态内部类有一下两个特点:
1. 创建静态内部类的对象,不需要其外部类的对象
2. 不能从静态内部类的对象中访问非静态内部类的对象
参考资料: