匿名类、包、权限修饰符_DAY10

1:内部类(理解)

      (1)把类定义在一个类的内部。

      (2)特点:

           A:内部类可以直接使用外部类的成员,包括私有。

           B:外部类要使用内部类成员,必须创建对象使用。

           例子:

public class InnerClassTest {
    public static void main(String[] args) {
        OuterClass.InnerClass inner=new OuterClass().new InnerClass();//创建内部类对象
        inner.innerMethod(); //外部类要使用内部类成员,必须创建对象使用
    }
}

class OuterClass{
    //成员变量
    private int age=10;
    //构造方法
    public OuterClass(){}

    //成员内部类
    class InnerClass{
       public void innerMethod(){
           System.out.println("我是成员内部类,访问外部类的私有属性age:"+age);
           //内部类可以直接使用外部类的成员,包括私有。
       }
    }
}
View Code

      (3)内部类的分类:

           局部内部类:定义在方法中的内部类

           成员内部类:定义在类中方法外的内部类

      (4)成员内部类

           class Outer {

               class Inner {  //成员内部类

               }

           }

 

         普通的修饰的时候:

             外部类名.内部类名 变量 = 外部类对象.内部类对象;

             Outer.Inner oi = new Outer().new Inner();

 

          class Outer {

               static class Inner {

                    void method(){}

             }

         }

         用静态修饰内部类时:

               外部类名.内部类名 变量 = 外部类名.内部类对象

               Outer.Inner oi = new Outer.Inner();

               Outer.Inner oi = Outer.new Inner(); //错误

 

         用静态修饰内部类和方法时:

               Outer.Inner.method()

         成员内部类:

             private:为了数据的安全。可以加数据校验

             static:为了方便调用。

         例子:

/*
    成员内部类:
        内部类定义在成员位置
    内部类对象创建:
        Outer.Inner x = new Outer().new Inner();
*/
class Demo8 
{
    public static void main(String[] args) 
    {
        //Inner inner = new Inner();   //内部类对象不可以直接这样创建
        //System.out.println(new Outer().age); //调用错误

    
                Outer out = new Outer();
        Outer.Inner inner = out.new Inner(); //创建内部类对象的方式1
        Outer.Inner inner2 = new Outer().new Inner();//创建内部类的对象的方式2
        
                inner.innerMethod();
                inner2.innerMethod();
   
    }
}

class Outer
{
        //成员属性
    private int age;
        
        //成员内部类
    class Inner
    {
        public void innerMethod(){
            System.out.println("我是内部类的方法,外部类age的值为"+age); //可以直接访问外部私有属性
        }
    }
        
        //成员方法
    public void outerMethod(){
        Inner inner = new Inner(); //创建成员内部类对象,调用成员内部类方法
        inner.innerMethod();
    }
}
View Code
/*
    private与static修饰符的成员内部类
    private:外界无法直接创建内部类对象,外部类可以创建内部类对象,在此之前可以加入校验。
    static: 修饰内部类,不需要使用外部类对象,外部类名直接调用,修饰内部类成员,不需要内部类对象,使用内部类名直接调用。
*/
class Demo9 
{
    public static void main(String[] args) 
    {
        /*private-----------------------------------------------------------------------

        //当使用private修饰成员内部类,则不能使用以下两种方法创建对象
                //Outer out = new Outer();
        //Outer.Inner2 inner = out.new Inner2(); //方式1
        //Outer.Inner2 inner = new Outer().new Inner2();//方式2
        
        //可以在外部类的方法中创建内部类对象,可以增加数据校验,保证安全性
        out.outerMethod();
        */


                //static---------------------------------------------------------------------
        //当使用static修饰成员内部类,可以直接使用外部类名new Outer.innerMethod()的形式创建内部类对象
        Outer.Inner inner= new Outer.Inner();
        inner.innerMethod();

                //当使用static修饰成员内部类,同时成员内部类的方法也用static修饰时,可以直接使用外部类.内部类.方法的形式,调用内部类的方法!
        Outer.Inner.innerStaticMethod();
    }
}

class Outer
{
    private static int age;

    static class Inner
    {
        public void innerMethod(){
            System.out.println("我是内部类的方法,外部类age的值为"+age);
        }

        public static void innerStaticMethod(){
            System.out.println("我是内部类的方法,外部类age的值为"+age);
        }
    }

    public void outerMethod(){
        //数据校验
        Inner inner = new Inner();
        inner.innerMethod();
    }
}


class Outer2
{
    private int age2;

    private class Inner2
    {
        public void innerMethod2(){
            System.out.println("我是内部类的方法,外部类age的值为"+age2);
        }
    }

    public void outerMethod2(){
        //数据校验
        Inner inner2 = new Inner2();
        inner2.innerMethod2();
    }
}
View Code

 

      (5)局部内部类

           A:带名字的局部内部类

                 class Outer {          //外部类

                        public void method() { //成员方法

                              final int a = 10;

                              class Inner {  //成员内部类

                                    public void show() {   //成员内部类的方法

                                           System.out.println("show");

                                           System.out.println(a);

                                       }

                                   }

                              Inner i = new Inner(); //在成员内部类里面创建对象并使用!

                              i.show();

                        }

                   }

         B:匿名内部类(掌握)

               a:没有名字的内部类。其本质是一个对象。是通过多态来实现的。

               b:前提:存在一个抽象类或者接口。

               c:格式:

                  new 抽象类或者接口() {

                      重写父类方法;

                  };

 

               本质:是一个继承了类或者实现了接口的子类匿名对象。

           例子:

/*
    匿名内部类:
        在通过简写形式定义一个没有类名的类。
        匿名内部类即将匿名定义类与创建对象的动作一起完成。    

        必须要有实现或者继承关系。

        格式:
        new 类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)};  //注意使用的是父类或者接口

*/
class Demo11 
{

    public static void main(String[] args) 
    {
        Demo12 demo12 = new Demo12();
        demo12.outerMethod();
    }
    
}

abstract class Animal
{
    public abstract void eat();
}

interface MyInterface
{
    public abstract void method();
    public abstract void method2();
}

class Demo12
{
    public void outerMethod(){
    
        class Cat extends Animal  //内部类
        {
            public void eat(){
                System.out.println("舔着吃!");
            }
        }
        Animal cat = new Cat();
        cat.eat();

        System.out.println("============================");

        Animal anyAnimal = new Animal(){ //没有类名,有对象名
            public void eat(){
                System.out.println("舔着吃!");
            }

            public void method(){
                System.out.println("我是匿名内部类对象的方法");
            }
        };
        
        anyAnimal.eat();
        //anyAnimal.method();

        new Animal(){
            public void eat(){
                System.out.println("舔着吃!");
            }
        }.eat();

        //===============================以上为抽象类的内部类,以下为接口的内部类
        System.out.println("============================");

        class MyClass implements MyInterface
        {
                public void method() {
                    System.out.println("我是内部类方法1");
                }
                public void method2() {
                    System.out.println("我是内部类方法2");
                }
        }

        MyInterface mi = new MyClass();//有类名MyClass,有对象名mi
        mi.method();
        mi.method2();

        MyInterface mi2 = new MyInterface(){//没有类名,有对象名mi2
                public void method() {
                    System.out.println("我是匿名内部类方法1");
                }
                public void method2() {
                    System.out.println("我是匿名内部类方法2");
                }
        };

        mi2.method();
        mi2.method2();

        new MyInterface(){    //没有类名,没有对象名,即匿名对象
                public void method() {
                    System.out.println("我是匿名内部类方法1");
                }
                public void method2() {
                    System.out.println("我是匿名内部类方法2");
                }
        }.method();

        
        new MyInterface(){ //没有类名,没有对象名,即匿名对象
                public void method() {
                    System.out.println("我是匿名内部类方法1");
                }
                public void method2() {
                    System.out.println("我是匿名内部类方法2");
                }
        }.method2();
    }
}
View Code

 

               d.匿名内部类的使用场景 :

          :内部类效率更高。

          :通常在使用接口类型参数的方法上,并该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。

          :增强阅读性。

                        例子:

package package3;

/*
    使用匿名内部类的场景:
        1:提高效率
        2:当参数类型,返回值类型,成员变量类型为抽象类或者接口时,可以使用匿名内部类。
        3:增强阅读性

*/
class Demo13
{
    public static void main(String[] args)
    {
        //-----------------普通方式调用  ---------------------
        Demo13 demo13 = new Demo13();
        MyClass mc = new MyClass();
        demo13.method(mc);

       //-----------------创建匿名内部类---------------------
        demo13.method(new MyInerface(){
            public void method() {
                System.out.println("匿名对象匿名内部类方法一");
            }
            public void method2() {
                System.out.println("匿名对象匿名内部类方法二");
            }
        });


        MyAbsClass mac = demo13.method2();
        mac.eat();
        mac.sleep();
        mac.hitBeanBean();
    }

    //参数类型为接口的方法
    public void method(MyInerface mi) {
        mi.method();
        mi.method2();
    }
    //返回值类型为抽象类的方法
    public MyAbsClass method2() {
        // 方式1:有类名MyClass2、有对象名mac
         /* 
        MyAbsClass mac = new MyClass2();
        return mac;
        */
       
        //方式2:没有类名,有对象名mac
        /*
        MyAbsClass mac = new MyAbsClass(){
                public void eat() {
                    System.out.println("匿名内部类中:学完匿名内部类,就吃不下去了!");
                }
                public void sleep(){
                    System.out.println("匿名内部类中:学完匿名内部类,就睡不着了!");
                }
        };

        return mac;
        */

        //方式3:没有类名,没有对象名
        return new MyAbsClass(){      //匿名内部类
            public void eat() {
                System.out.println("匿名内部类中:学完匿名内部类,就吃不下去了!");
            }
            public void sleep(){
                System.out.println("匿名内部类中:学完匿名内部类,就睡不着了!");
            }
        };
    }
}

//---------------------------接口--------------------------------------
interface MyInerface
{
    public abstract void method();
    public abstract void method2();
}

class MyClass implements MyInerface
{
    public void method() {
        System.out.println("方法一");
    }
    public void method2() {
        System.out.println("方法二");
    }
}

//---------------------------抽象类--------------------------------------

abstract class MyAbsClass
{
    public abstract void eat();
    public abstract void sleep();

    public void hitBeanBean(){
        System.out.println("学完匿名内部类,就开始打豆豆!");
    }
}

//---------------------------非抽象类--------------------------------------
class MyClass2 extends MyAbsClass
{
    public void eat() {
        System.out.println("学完匿名内部类,就吃不下去了!");
    }
    public void sleep(){
        System.out.println("学完匿名内部类,就睡不着了!");
    }
}
View Code

            (6)例子:定义并使用内部类。要求包含局部内部类,成员内部类,匿名内部类。

/**
 * 定义并使用内部类。要求包含局部内部类,成员内部类,匿名内部类。
 */
public class Main {
    public static void main(String[] args) {

        //调用成员内部类
        Fu.Zi zi= new Fu().new Zi();
        zi.sleep();


        //调用局部内部类
        Fu fu=new Fu();
        fu.eat();

        //调用匿名内部类
        fu.method().eatType();

    }
}
View Code
/**
 * 定义并使用内部类。要求包含局部内部类,成员内部类,匿名内部类。
 */
public class Fu {
    //成员变量
    String string = "巴马";

    //成员内部类
    public class Zi {
        public void sleep() {
            System.out.println("睡觉");
        }
    }

    //局部内部类
    public void eat() {
        class EatMeat extends EatType {      //局部内部类,必须要继承抽像类或者继承接口
            public void eatType() {
                System.out.println("吃肉");

            }
        }
        EatMeat eatMeat = new EatMeat();
        eatMeat.eatType();
    }

    //匿名内部类
    public EatType method() {  //返回值类型或者参数类型为抽象类或者接口
      /*EatType type= new EatType(){
            public void eatType(){
                System.out.println("吃鱼");
            }
        };
      return type;*/

      return new EatType(){
            public void eatType(){
                System.out.println("吃鱼");
            }
        };

    }

}
View Code
public abstract class EatType {
    public abstract void eatType();
}
View Code

         (7)匿名内部类面试题

        

/*
    匿名内部类练习:
        Outer.method.show();    意思为Outer类的静态成员变量method可以调用一个show方法,可以调用show方法的一定是Inter接口的子类实例
        Outer.method().show();  意思为Outer类的静态成员方法method()的返回值可以调用一个show方法,可以调用show方法的一定是Inter接口的子类实例
*/

interface Inter{
    void show();
}

//题目1:
class Outer{
    //补齐代码
    public static Inter method() {
                //方式1
        /* 
        Inter inter = new Inter(){
            public void show(){
                System.out.println("hello world");
            }
        };
        return inter;
        */

                //方式2
        return new Inter(){
            public void show(){
                System.out.println("hello world");
            }
        };
    }
}

class innerClassTest{
    public static void main(String[] args){
        Outer.method().show();
    }
}


//题目2:
/*
class Outer{
    //补齐代码
    public static Inter method = new Inter(){
        public void show(){
            System.out.println("hello world");
        }
    }; 
}
class innerClassTest{
    public static void main(String[] args){
        Outer.method.show();
        
    }
} 
*/
View Code

 

2:包(掌握)

      (1)包就是永远区分相同类在不同文件夹下。其本质就是一个文件夹。

      (2)包的作用:让相同类名的类可以存在。为了组织代码。cn.itcast.action   cn.itcast.service  cn.itcast.db

      (3)定义包:

           package 包名.包名...;

      (4)带包的编译和运行(理解)

           A:方式一

               手动式

                 a:javac编译代码

                 b:手动建立包,把class扔进去

                 c:java执行,带全路径

           B:方式二

               自动式

                 a:通过javac编译自动生成包

                      javac -d . 文件名

                 b:通过java运行class文件

                   java 包名.包名.class文件名不带扩展名

      (5)不同包下的类之间的访问。

           权限够大才行。

 

         以后,我们所有定义的类都用public修饰。

      (6)面试题:

           在同一个java文件中,可不可以有多个类?可以。

           而我们知道类是可以用public修饰的,那么,可不可以多个类都用public修饰?不可以。

           并且,一般的时候,如果有main方法也存在的时候,都是public修饰带main那个类。

           文件名必须和该public修饰的类名一致。

      (7)实际运行的时候,是要求Class文件在一个文件加下,可以直接调用,如果不在一个文件夹下,导包也是为了导入Class文件。

 

3:导包(掌握)

      (1)如果多次使用一个多级包的类,每次带全路径太麻烦,我们就考虑使用导包。

      (2)导包的格式:

           import 包名.包名...;

 

         注意:

             在同一个包下如果有多个类被使用,可以使用通配符*来导入,但是不建议。

             推荐:使用谁导入谁。

    (3)面试题:

       package,import,class出现的位置?

           package > import > class

 

4:权限修饰符(掌握)

      (1)用于保证在不同的情况下可以使用

      (2)使用如下

                  本类     同一个包下   不同包下的子类   不同包下的无关类

         private    Y

         默认       Y       Y

         protected  Y      Y             Y

         public     Y       Y              Y              Y

 

 

    常见的组合规则:

       权限修饰符+abstract/final/static+...

 

    我们到底怎么用(开发的时候一般都这么做):

        类:

           public class Demo {       }

 

      成员变量:

           变量:private String name;  加上相应的getter和setter

           常量:public static final int X = 10;

 

      构造方法:

           不让外界创建:private Demo(){}

           大部分:public Demo(){}

 

      成员方法:

           不让外界用:private void show(){}

           大部分:public void method(){}

           抽象方法:public abstract void function();

 

posted @ 2017-09-11 12:59  AI菌  阅读(225)  评论(0编辑  收藏  举报