重踏学习Java路上_Day10(形参与返回值,包,修饰符,内部类)

1:形式参数和返回值的问题(理解)
    (1)形式参数:
         类名:需要该类的对象,总之需要类变量的都是需要其实例化的对象      特别例子://匿名对象用法 new StudentDemo().method(new Student());//
        

   抽象类名:需要该类的子类对象,抽象类本身不能实例化,抽象类有构造方法,但不能用作实例化调用,仅仅用于子类访问父类数据的初始化,继承父类的子类方式有两种(1.抽象类继承抽象类,此时不能实例化,但也不用重写抽象方法;2.具体类继承抽象类,重写抽象方法,使其能进行实例化,使其在堆内存区有一份对象数据,把引用地址赋值给抽象类的引用类型变量完成实例化)
        

    接口名:需要该接口的实现类对象,接口本身不能实例化,因为没有构造方法,实现接口的子类方式有两种(1.抽象类实现接口,此时不能实例化,但也不用重写抽象方法;2.具体类实现对象,重写接口抽象方法,使其能进行实例化,使其在堆内存区有一份对象数据,把引用地址赋值给接口的引用类型变量完成实例化)

例子:

类作为形式参数:

class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public void method(Student s) { //ss; ss = new Student();  Student s = new Student();
        s.study();
    }
}

class StudentTest {
    public static void main(String[] args) {
        //需求:我要测试Student类的study()方法
        Student s = new Student();
        s.study();
        System.out.println("----------------");
        
        //需求2:我要测试StudentDemo类中的method()方法
        StudentDemo sd = new StudentDemo();
        Student ss = new Student();
        sd.method(ss);
        System.out.println("----------------");
        
        //匿名对象用法
        new StudentDemo().method(new Student());
    }
}

抽象类作为形式参数:

abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public void method(Person p) {//p; p = new Student();  Person p = new Student(); //多态
        p.study();
    }
}

//定义一个具体的学生类
class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest {
    public static void main(String[] args) {
        //目前是没有办法的使用的
        //因为抽象类没有对应的具体类
        //那么,我们就应该先定义一个具体类
        //需求:我要使用PersonDemo类中的method()方法
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
    }
}

接口作为形式参数:

interface Love {
    public abstract void love();
}

class LoveDemo {
    public void method(Love l) { //l; l = new Teacher();  Love l = new Teacher(); 多态
        l.love();
    }
}

//定义具体类实现接口
class Teacher implements Love {
    public void love() {
        System.out.println("老师爱学生,爱Java,爱林青霞");
    }
}

class TeacherTest {
    public static void main(String[] args) {
        //需求:我要测试LoveDemo类中的love()方法
        LoveDemo ld = new LoveDemo();
        Love l = new Teacher();
        ld.method(l);
    }
}


    (2)返回值类型:
        类名:返回的是该类的对象
        抽象类名:返回的是该类的子类对象
        接口名:返回的是该接口的实现类的对象

类,抽象类,接口作为返回值的例子:

类做返回:

class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        //Student s = new Student();
        //Student ss = s;
        
        //Student s = new Student();
        //return s;
        return new Student();
    }
}

class StudentTest2 {
    public static void main(String[] args) {
        //需求:我要使用Student类中的study()方法
        //但是,这一次我的要求是,不要直接创建Student的对象
        //让你使用StudentDemo帮你创建对象
        StudentDemo sd = new StudentDemo();
        Student s = sd.getStudent(); //new Student(); Student s = new Student();
        s.study();
    }
}

抽象类做返回:

abstract class Person {
    public abstract void study();
}

class PersonDemo {
    public Person getPerson() {
        //Person p = new Student();
        //return p;
        
        return new Student();
    }
}

class Student extends Person {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class PersonTest2 {
    public static void main(String[] args) {
        //需求:我要测试Person类中的study()方法
        PersonDemo pd = new PersonDemo();
        Person p = pd.getPerson(); //new Student();  Person p = new Student(); 多态
        p.study();
    }
}

接口做返回:

interface Love {
    public abstract void love();
}

class LoveDemo {
    public Love getLove() {
        //Love l = new Teacher();
        //return l;
        
        return new Teacher();
    }
}

//定义具体类实现接口
class Teacher implements Love {
    public void love() {
        System.out.println("老师爱学生,爱Java,爱林青霞");
    }
}

class TeacherTest2 {
    public static void main(String[] args) {
        //如何测试呢?
        LoveDemo ld = new LoveDemo();
        Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
        l.love();
    }
}


    (3)链式编程
        对象.方法1().方法2().......方法n();
        
        这种用法:其实在方法1()调用完毕后,应该一个对象;
                  方法2()调用完毕后,应该返回一个对象。
                  方法n()调用完毕后,可能是对象,也可以不是对象。

例子:

/*
    链式编程。
        每次调用完毕方法后,返回的是一个对象。
*/
class Student {
    public void study() {
        System.out.println("Good Good Study,Day Day Up");
    }
}

class StudentDemo {
    public Student getStudent() {
        return new Student();
    }
}

class StudentTest3 {
    public static void main(String[] args) {
        //如何调用的呢?
        StudentDemo sd = new StudentDemo();
        //Student s = sd.getStudent();
        //s.study();
        
        //大家注意了
        sd.getStudent().study();
    }
}

2:包(理解)
    (1)其实就是文件夹
    (2)作用:
        A:区分同名的类
        B:对类进行分类管理
            a:按照功能分 (CRUD四个功能,四个包,各自底下有学生添加,学生删除老师添加,老师删除等)
            b:按照模块分(老师包,学生包,每个包各自含自己的CRUD功能)
    (3)包的定义(掌握)
        package 包名;
        多级包用"."分开即可。
    (4)注意事项:(掌握)
        A:package语句必须在文件中的第一条有效语句
        B:在一个java文件中,只能有一个package
        C:如果没有package,默认就是无包名
    (5)带包的编译和运行
        A:手动式

             a.编写一个带包的java文件

             b.通过javac命令编译该java文件

             c.手动创建包名

             d.把b步骤的class文件放到C步骤的最底层包

             e:回到和包根目录在同一目录的地方,然后运行,记住带包运行。java cn.itcast.HelloWorld
        B:自动式(掌握)
            javac -d . HelloWorld.java (-d:创建目录,"."表示在本路径下创建)

            1.编写一个带包的java文件

            2.javac编译的时候带上-d即可

                    javac -d . HelloWorld.java
            3.回到和包根目录在同一目录的地方,然后运行,记住带包运行java cn.itcast.HelloWorld

          

            不同包下类之间的访问:先编译引入包的java文件,再编译执行包下的java文件,再带包运行

          
3:导包(掌握)
    (1)我们多次使用一个带包的类,非常的麻烦,这个时候,Java就提供了一个关键字import。
    (2)格式:
        import 包名...类名; //这种方式导入是到类的级别
        另一种:
            import 包名...*;(不建议)
    (3)package,import,class的顺序
        package > import > class

        package:只能有一个

        import:可以有多个

        class:可以有多个,以后建议是一个
    
4:权限修饰符(掌握)
    (1)权限修饰符
                        本类    同一个包下(包含子类与无关类)    不同包下的子类    不同包下的无关类
        private           Y
        默认               Y            Y
        protected       Y            Y                            Y
        public             Y            Y                            Y                       Y
    (2)这四种权限修饰符在任意时刻只能出现一种
        public class Demo {}        

5:常见的修饰符(理解)
    (1)分类:
        权限修饰符:private,默认,protected,public
        状态修饰符:static,final
        抽象修饰符:abstract
    (2)常见的类及其组成的修饰
       修饰符:
        权限修饰符:private,默认的,protected,public
        状态修饰符:static,final
        抽象修饰符:abstract
        
    类:
        权限修饰符:默认修饰符,public
        状态修饰符:final
        抽象修饰符:abstract
        
        用的最多的就是:public

       //此处不允许使用修饰符private
  //此处不允许使用修饰符protected
  //此处不允许使用修饰符static

       
    成员变量:
        权限修饰符:private,默认的,protected,public
        状态修饰符:static,final
        
        用的最多的就是:private
        
    构造方法:
        权限修饰符:private,默认的,protected,public
        
        用的最多的就是:public
        
    成员方法:
        权限修饰符:private,默认的,protected,public
        状态修饰符:static,final
        抽象修饰符:abstract
        
        用的最多的就是:public
        
    除此以外的组合规则:
        成员变量:public static final
        成员方法:public static
                  public abstract
                  public final
       
    (3)另外比较常见的:
        public static final int X = 10;
        public static void show() {}
        public final void show() {}
        public abstract void show();

6:内部类(理解)
    (1)把类定义在另一个类的内部,该类就被称为内部类。
        举例:把类B定义在类A中,类B就被称为内部类。
    (2)内部类的访问规则
        A:可以直接访问外部类的成员,包括私有
        B:外部类要想访问内部类成员,必须创建对象
    (3)内部类的分类 (注意:类与类是平级关系)
        A:成员内部类:在成员位置定义的类,被称为成员内部类
        B:局部内部类:在局部位置定义的类,被称为局部内部类
    (4)成员内部类  (外部类没有static作为修饰,而内部类则可以用static修饰,因为内部类把他看做外部类的成员来看待,成员是可以用静态修饰的)
         A:private 为了保证数据的安全性  身体类(包含心脏类,肝脏类,肺类等,这些都用私有内部类)
        B:static 为了让数据访问的方便性  ,内部类用静态修饰是因为内部类可以看出是外部类的成员,一般使用static修饰内部类的话,会用public作为访问修饰符,因为已经在类加载是加载了,算是顶层类,一般这样用不用构造方法,直接类名加方法就好了,所以,一般公用的才使用public

               被静态修饰的成员内部类只能访问外部类的静态成员

              内部类方法被静态修饰后的方法:1.静态方法2.非静态方法
        
        成员内部类不是静态的:
            外部类名.内部类名 对象名 = new 外部类名().new 内部类名();  例子:Outer.Inner oi = new Outer().new Inner();
        成员内部类是静态的:
            外部类名.内部类名 对象名 = new 外部类名.内部类名();  例子:Outer.Inner oi = new Outer.Inner();   

  (5)成员内部类的面试题(填空) 

/*
      面试题:
            要求请填空分别输出30,20,10。
        
      注意:
            1:内部类和外部类没有继承关系。
            2:通过外部类名限定this对象
                  Outer.this
*/
class Outer {
    public int num = 10;
    class Inner {
        public int num = 20;
        public void show() {
            int num = 30;
            System.out.println(num);  //就近原则下的num
            System.out.println(this.num);  //本类下的成员变量num
            //System.out.println(new Outer().num);   //这句是可以的,创建一个匿名对象调用变量,但不是最简单,最简单在下面
            System.out.println(Outer.this.num);  //利用Outer.this,限制this的范围,来访问Outer下的num
        }
    }
}
class InnerClassTest {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }    
}


    (6)局部内部类(这个点很容易被忽视)

        可以直接访问外部类的成员
        可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
        局部内部类访问局部变量的注意事项:
        A:局部内部类访问局部变量必须加final修饰。
        B:为什么呢?
            因为局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的数据并不会立即消失。
            所以,堆内存还是用该变量,而该变量已经没有了。
            为了让该值还存在,就加final修饰。
            通过反编译工具我们看到了,加入final后,这个变量就成了常量,堆内存直接存储的是值,而不是变量名。
局部内部类例子,面试题:

/*
    局部内部类
        A:可以直接访问外部类的成员
        B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
    
    面试题:
        局部内部类访问局部变量的注意事项?
        A:局部内部类访问局部变量必须用final修饰
        B:为什么呢?
            局部变量是随着方法的调用而调用,随着调用完毕而消失。
            而堆内存的内容并不会立即消失。所以,我们加final修饰。
            加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
            我在内存中存储的是数据20,所以,我还是有数据在使用。
*/
class Outer {
    private int num  = 10;
    
    public void method() {
        //int num2 = 20;  //jdk报错,说明一定要final作为局部变量的修饰
        final int num2 = 20;//对的
        class Inner {
            public void show() {
                System.out.println(num);
                //从内部类中访问本地变量num2; 需要被声明为最终类型,可以利用反编译穿软件看看,是否直接变为20,连变量名都消失了
                System.out.println(num2);//20
            }
        }
        
        //System.out.println(num2);
        
        Inner i = new Inner();
        i.show();
    }
}

class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
  

  (7)匿名内部类(掌握)
        A:其实是局部内部类的简化形式
        B:前提
            存在一个类或者接口,这里的类可以是具体类也可以是抽象类
        C:格式:
            new 类名或者接口名() {
                重写方法;
            }
        D:本质:
            其实是继承该类(具体类对象)或者实现接口的子类(实现类)匿名对象

        E:好处:在使用匿名对象或匿名内部类时,都是一次定义,一次使用就不会用了,所以不用创建引用变量指向对象引用地址,匿名的使用能让jvm的垃圾回收机制快点收回内存,因为它没有被栈的变量所指向,所以回收速度最快。

          弊端:只能使用一次
  

    (8)匿名内部类在开发中的使用
        我们在开发的时候,会看到抽象类,或者接口作为参数。
        而这个时候,我们知道实际需要的是一个子类对象。
        如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
       例子:

/*
    匿名内部类在开发中的使用
*/
interface Person {
    public abstract void study();
}

class PersonDemo {
    //接口名作为形式参数
    //其实这里需要的不是接口,而是该接口的实现类的对象
    public void method(Person p) {
        p.study();
    }
}

//实现类
class Student implements Person {
    public void study() {
        System.out.println("好好学习,天天向上");
    }
}

class InnerClassTest2 {
    public static void main(String[] args) {
        //测试
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
        System.out.println("--------------------");
        
        //匿名内部类在开发中的使用
        //匿名内部类的本质是继承类或者实现了接口的子类匿名对象
        pd.method(new Person(){
            public void study() {
                System.out.println("好好学习,天天向上");
            }
        });
    }
}


    (9)匿名内部类的面试题(补齐代码)
/*
    匿名内部类面试题:
        按照要求,补齐代码
            interface Inter { void show(); }
            class Outer { //补齐代码 }
            class OuterDemo {
                public static void main(String[] args) {
                      Outer.method().show();
                  }
            }
            要求在控制台输出”HelloWorld”
*/
interface Inter {
    void show();
    //public abstract
}

class Outer {
    //补齐代码
    public static Inter method() {
        //子类对象 -- 子类匿名对象
        return new Inter() {
            public void show() {
                System.out.println("HelloWorld");
            }
        };
    }
}

class OuterDemo {
    public static void main(String[] args) {
        Outer.method().show();
        /*
            1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
            2:Outer.method().show()可以看出method()方法的返回值是一个对象。
                又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
        */
    }
}

原文地址:https://www.cnblogs.com/canceler/p/4602952.html