内部类
1.内部类定义:
(1)将一个类A定义到类B的内部,那么类A就叫做内部类,类B就叫做外部类
(2)对内部类进行划分还分为局部内部类和成员内部类,和局部变量和成员变量的定义其实是差不多的
成员内部类:定义在类中方法外的类
局部内部类:定义在外部类中的成员方法中,注意是成员方法,没有静态方法
2.内部类特点:
(1)内部类可以直接访问外部类的成员,包括私有成员,成员方法
(2)内部类也可以直接new外部类,其实虽然内部类在外部类的内部,都在本外部类里面,但是他俩还是不同的两个类,只是一个类嵌套进外部类了.
public class Test {
public static void main(String[] args) {
// 内部类:将一个类A定义到类B的内部,那么类A就叫做内部类,类B就叫做外部类
// 对内部类进行划分还分为局部内部类和成员内部类,和局部变量和成员变量的定义其实是差不多的
// 成员内部类:定义在类中方法外的类
// 局部内部类:定义在外部类中的成员方法中,注意是成员方法,没有静态方法
// ====================================================
// 创建成员内部类对象的语法:
A.B b=new A().new B();
b.heihei();
System.out.println(b.h);//new出来之后就直接调用就行了,但是new出来的内部类的引用无法调用外部类的东西
System.out.println(b.k);
A a =new A();
a.xixi();
// 内部类私有后就创建不出来内部类对象了,但是可以通过new 外部类简介访问内部类的对象,比如:
A v=new A();
v.luelue();
// ================================================================================
// 定义在内部的静态内部类创建方法跟非静态的不一样,如下:
A.G g=new A.G();
g.kkk();
}
}
class A{//外部类
int a=100;
private int b=60;
final static int lll=555;
public void xixi(){
B b = new B();
System.out.println(b.k);//外部类访问内部类也需要new 内部类才行
System.out.println(b.h);
F f = new F();
f.fff();
System.out.println(f.ddd);
G g =new G();
g.kkk();
}
public void luelue(){
F f = new F();
f.fff();
}
private void gaga(){
System.out.println("外部类的方法启动了");
}
class B{//内部类(成员内部类)
F f= new F();
int k=90;
int h=80;
public void heihei(){
System.out.println(a);
System.out.println(b);//内部类可以调用外部类的成员变量和方法,私有的都可以掉,其实就可以看成外部类就是内部类的本类
xixi();
gaga();
f.fff();//只要在本类中,哪怕内部类所有的东西都是私有的,也可以调用
}
}
private class F{//内部类中可以加private修饰符修饰
// 加上私有权限修饰符后,只能本类访问(即外部类或外部类中的平行内部类),出了外部类谁都不能访问了。
int ddd=100;
private void fff(){
System.out.println("私有内部类的私有方法被调用了");
}
}
public static class G{//静态内部类里面也可以访问
// 静态内部类只能访问外部类的静态成员
int aaaa=1000;
public void kkk(){//静态内部类也可写有非静态的方法,因为静态的是先有的,非静态的是后有的,记住,类,方法,变量常量都是
// 一样的,静态内部类可以自己定义非静态的变量和方法,但是方法调用别的类的时候只能调用其类的静态方法和静态变量
System.out.println("静态内部类被调用了");
// System.out.println(a);//这个就访问不到
System.out.println(lll);//静态内部类只能访问非静态类的静态的东西
// B b = new B();//只能自己类内部定义非静态的,调用外部的只能是静态的方法或变量,new一个非静态类都不行,但是一个非静态类可以
// new 一个静态的内部类并且正常调用
}
}
public void hehe(){
class E{
// 这个是局部内部类
}
}
}
class C{//C和D类是平行类
}
class D{
}
静态内部类
public class Test {
public static void main(String[] args) {
//局部内部类在外界没有直接创建其的方法,只能通过间接的方法去调用
Outer outer = new Outer();
outer.haha(35);//调用这个方法从而实现间接调用局部内部类
}
}
class Outer{
int a=1000;
private double b=30.0;
public void haha( int aaa){
int c=50000;
class Inner {//局部内部类
public void hehe() {
System.out.println(b);//跟成员内部类一样,局部内部类也是可以直接访问外部类的成员,不论私有非私有,也可以先new
// 外部类,再去引用点访问也可以
System.out.println(c);//也可以直接去掉方法体中的变量
System.out.println(aaa);//局部内部类也可以调用形参
OutShow();//也可以调用外部方法,跟成员内部类一样
// ===============================================================
// 但是,在局部内部内部类中,方法内的局部方法 实际上都是跟普通的局部方法内的变量修饰不一样的,局部内部类所在的
// 方法修饰的变量,无论是形参还是局部变量(都叫局部变量),都是带着final修饰符的,所以这些变量在局部内部类中
// 不能被重新赋值,只能被使用,但是在这个方法内部,内部类外部的这些变量,是可以修改其变量的。在局部内部类里面不能
// 被修改,因为类的存活时间比较长,内部类还存在的时候,可能这个局部方法已经弹栈了,所以方法内部局部类外部的变量都
// 默认使用final修饰,由final修饰的变量放在了常量池中,就可以一直使用,这说的被final修饰的是在在方法内部,内部类外部
// 的变量,外部类内部,方法体外部的变量为成员变量,还是可以随意更改变量值的,只有方法中的不能随意更改了,因为方法
// 没有类的时间活的久
}
}
// 只能在局部内部类所在的方法内部去创建这个内部类,然后在从外部类进行new外部类对象掉外部类这个方法调用,如:
Inner inner = new Inner();
inner.hehe();//这在从主方法里new外部类对象
}
public void OutShow(){
System.out.println("外部方法启动");
}
}
在类中定义一个接口
public class Test {
public static void main(String[] args) {
B b=new B();
b.OutShow();//这里采用的是间接在外界创建内部接口的子对象
// 下面是直接在外界调用内部接口的子对象的方法
// =================================================
B.Myinterface myinterface = new B.Myinterface(){
@Override
public void aa() {
System.out.println("bbbbbbbbbbbbbbbbbbbb");
}
};//也是采用匿名内部类的方式访问内部接口子对象,前提是接口不是私有的
System.out.println(myinterface.b);
// B.Inner b=new B.Inner();//如果接口时私有的话就不能直接调用内部接口的子对象了,需要间接法
B a=new B();
a.ccc();//采用间接法去调用内部私有的接口的子对象
}
}
//可不可以在一个类里面定义一个接口,可以:
class B{
interface Myinterface{//创建内部接口
int b=50;
void aa();
}
private interface Inner{//私有的接口,不能直接外部去调,只能间接去掉
void aaaa();
}
public void OutShow(){
new Myinterface() {//创建匿名内部类
@Override
public void aa() {
System.out.println("aaaaaaaaaaaaaaa");
}
}.aa();
System.out.println( new Myinterface() {//创建匿名内部类
@Override
public void aa() {
System.out.println("aaaaaaaaaaaaaaa");
}
}.b);
}
public void ccc(){
new Inner(){
@Override
public void aaaa() {
System.out.println("llllllllllllllllll");
}
}.aaaa();
}
}
public class Test {
public static void main(String[] args) {
// 匿名内部类:是局部内部类的一种简化的写法
// 匿名内部类的本质:匿名内部类本质上是一个对象,是继承了该抽象类或实现了该接口的子类对象
// 例: 我想要得到抽象类的子类对象,则可以直接用匿名内部类的方法
new MyClass(){
@Override
public void aa() {
System.out.println("匿名内部类的实质是抽象类或者接口的子对象");
}
}.aa();//到这里就是一个匿名内部类,这你可以不用理解其中的原理,记住匿名内部类就是一个子对象,是抽象类或者接口的子对象
// .aa调用的是内部类中的方法,时刻记住,这就是个子类对象,记住记住!
new MyClass(){
@Override
public void aa() {
System.out.println("匿名内部类的实质是抽象类或者接口的子对象");
}
};//这里就是另一个匿名内部类,是MyClass的子类对象,调用方法时是调用的子类本身的方法,即子类点方法
// 匿名内部类方法就是 new类名或接口名(){};,大括号内部重写其方法
}
}
abstract class MyClass{
public abstract void aa();
}
2.参数传递
public class DEMO {
public static void main(String[] args) {
}
}
class Outer{
int num=30;
class Inner{
int num=20;
public void show(){
int num=10;
System.out.println(num);//这是局部变量,访问的是本方法的
System.out.println(this.num);//这个访问的是本内部类的成员变量
// 内部也可以这样写
System.out.println(Inner.this.num);
System.out.println(new Outer().num);//内部类也可以new外部类
// 但是对第三句最简洁的方法是这么写的
System.out.println(Outer.this.num);//记住这个语法就行,从内部类里面访问外部的成员
}
}
}
3.返回值类型
public class Test {
public static void main(String[] args) {
Son son=new Son();
Father f=sss(son);
System.out.println(son.num);
Son s=(Son) f;//这里向下转型,因为之前f里面new了一个Son了,这个Son返回给了f,所以这里的向下转型就是f里面的那个son
System.out.println(s.num);
}
public static Father sss(Father f){//这里是接口形参,所以实参应为子类的引用变量
Son son = new Son();
son.num=6;
return son; //接口这里跟抽象类一样,返回值要返回其子类,但是不论在方法内或者方法外,一定要把其子类new出来
}
}
interface Father{
int num=30;
void hehe();
}
class Son implements Father{
int num=300;
@Override
public void hehe() {
this.num=8000;
System.out.println("ddsadas");
}
}
public class Demo {
public static void main(String[] args) {
Myclass s = sss(20);//这的返回类型就是子类 sss代表的是子类(因为返回的是子类型)这里就用多态
MySon ms= (MySon) s;//向下转型
}
//返回值类型如果是抽象类或者接口的话,返回这个类型的子类型即可
public static Myclass sss(int num){//这里的返回类型只能是多态
MySon mySon = new MySon();//必须要有new,不然没有地址了
int a=10;
return mySon;//返回其子类变量型即可
}
}
abstract class Myclass{
public abstract void send();
}
class MySon extends Myclass{
@Override
public void send() {
System.out.println("dasdsa");
}
}
4.修饰符权限
修饰符分为四个:public,protacted,缺省,private,四个的等级依次降低
private是只能在本类里面用,出了类就不行
private可以用在内部类的修饰上,static 也可以修饰内部类,且俩可以同时一起用
缺省是只能在本包里面用,出了包就不行
protacted是出了本包之外,也可以在外包使用,但是外包使用的话,外包的类必须与本包的类是继承关系(外包类是子类),不是继承关系也不能用
public 本包外包继承非继承都可以用
public protacted 缺省 private 是一个领域
abstrat final default 修饰方法的时候是一个领域