zoukankan      html  css  js  c++  java
  • java基础笔记-类与对象(特殊类)

    内部类:

    •   仅仅为外部类服务
    •   可以隐藏该类的实现细节
    •   可以方便的访问外部类的私有成员而不需要提供公有的get ,set方法

    内部类分类:  

      普通内部类: 直接将类定义在另一个类的类体内

      静态内部类: 使用static 修饰的内部类,属于类层级别

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

      匿名内部类:没有名字的内部类(用的最多)

    普通内部类:

      又称成员内部类。

     普通内部类的定义和使用例子:

    package com.lagou.task10;
    
    /**
     * 编程实现普通内部类的定义和使用       -  文档注释
     */
    public class NormalOuter {
        private int cnt = 1;
    
        // 定义普通内部类,隶属于外部类的成员,并且是对象层级
        /*private*/public /*final*/ class NormalInner {
            private int ia = 2;
            private int cnt = 3;
            public NormalInner() {
                System.out.println("普通内部类的构造方法体执行到了!");
            }
    
            public void show() {
                System.out.println("外部类中变量cnt的数值为:" + cnt); // 1
                System.out.println("ia = " + ia); // 2
            }
    
            public void show2(int cnt) {
                System.out.println("形参变量cnt = " + cnt);  // 局部优先原则  4
                System.out.println("内部类中cnt = " + this.cnt); // 3
                System.out.println("外部类中cnt = " + NormalOuter.this.cnt); // 1
            }
        }
    }
    package com.lagou.task10;
    
    public class NormalOuterTest {
    
        public static void main(String[] args) {
    
            // 1.声明NormalOuter类型的引用指向该类型的对象
            NormalOuter no = new NormalOuter();
            // 2.声明NormalOuter类中内部类的引用指向内部类的对象
            NormalOuter.NormalInner ni = no.new NormalInner();
            // 调用内部类中的show方法
            ni.show();
    
            System.out.println("---------------------------------------------");
            ni.show2(4);
        }
    }

    内部类 方法形参cnt ,内部类成员变量cnt,外部类成员变量cnt的区分:

      内部类 方法形参cnt  -> cnt

      内部类成员变量cnt  -> this.cnt

      外部类成员变量cnt  ->  NormalOuter.this.cnt

    静态内部类:

    语法格式:

      

    静态内部类定义例子:

    package com.lagou.task10;
    
    /**
     * 实现静态内部类的定义和使用
     */
    public class StaticOuter {
        private int cnt = 1;        // 隶属于对象层级
        private static int snt = 2; // 隶属于类层级
    
        public /*static*/ void show() {
            System.out.println("外部类的show方法就是这里!");
        }
    
        /**
         * 定义静态内部类   有static关键字修饰隶属于类层级
         */
        public static class StaticInner {
            private int ia = 3;
            private static int snt = 4;
    
            public StaticInner() {
                System.out.println("静态内部类的构造方法哦!");
            }
    
            public void show() {
                System.out.println("ia = " + ia); // 3
                System.out.println("外部类中的snt = " + snt); // 2
                //System.out.println("外部类的cnt = " + cnt); // Error:静态上下文中不能访问非静态的成员,因此此时可能还没有创建对象
            }
    
            public void show2(int snt) {  // 就近原则
                System.out.println("snt = " + snt); // 5
                System.out.println("内部类中的成员snt = " + StaticInner.snt); // 4
                System.out.println("外部类中的成员snt = " + StaticOuter.snt); // 2
                //StaticOuter.show();
                new StaticOuter().show();
            }
        }
    }
    package com.lagou.task10;
    
    public class StaticOuterTest {
    
        public static void main(String[] args) {
    
            // 1.声明StaticInner类型的引用指向该类型的对象
            StaticOuter.StaticInner si = new StaticOuter.StaticInner();
            // 2.调用show方法进行测试
            si.show();
    
            System.out.println("---------------------------------------------");
            si.show2(5);
        }
    }

    静态内部类 方法形参snt ,静态内部类成员变量snt,静态外部类成员变量snt的区分:

      静态内部类 方法形参snt  -> snt

      静态内部类成员变量snt  ->StaticInner.snt

      静态外部类成员变量snt  -> StaticOuter.snt

    静态 context 中 不能访问this,this 指当前类的对象

    局部内部类:

      

      局部内部类不能使用访问修饰符 和 static 关键字

       局部内部类只在当前方法内部有效

      局部内部类可以在方法体内部创建对象

      局部内部类可以使用外部方法的局部变量,但是必须是理解为 final,这是因为局部内部类 和局部变量的声明周期不同所致

        局部内部类使用的局部变量必须理解为final,虽然final 关键字可以省略,但是建议加上,提高可读性。

        默认会拷贝一份局部变量到局部内部类使用,因此该局部变量不能改变。

    局部内部类例子:

    package com.lagou.task10;
    
    /**
     * 编程实现局部内部类的定义和使用
     */
    public class AreaOuter {
        private int cnt = 1;
    
        public void show() {
    
            // 定义一个局部变量进行测试,从Java8开始默认理解为final关键字修饰的变量
            // 虽然可以省略final关键字,但建议还是加上
            final int ic = 4;
    
            // 定义局部内部类,只在当前方法体的内部好使    拷贝一份
            class AreaInner {
                private int ia = 2;
    
                public AreaInner() {
                    System.out.println("局部内部类的构造方法!");
                }
    
                public void test() {
                    int ib = 3;
                    System.out.println("ia = " + ia); // 2
                    System.out.println("cnt = " + cnt); // 1
                    //ic = 5;  Error
                    System.out.println("ic = " + ic); // 4
                }
            }
    
            // 声明局部内部类的引用指向局部内部类的对象
            AreaInner ai = new AreaInner();
            ai.test();
        }
    
    }
    package com.lagou.task10;
    
    public class AreaOuterTest {
    
        public static void main(String[] args) {
    
            // 1.声明外部类类型的引用指向外部类的对象
            AreaOuter ao = new AreaOuter();
            // 2.通过show方法的调用实现局部内容类的定义和使用
            ao.show();
        }
    }

     回调模式:

      回调模式是指——如果一个方法的参数是接口类型,则在调用该方法时, 需要创建并传递一个实现此接口类型的对象;

    而该方法在运行时会调用 到参数对象中所实现的方法(接口中定义的)。

    匿名内部类:

      语法格式:• 接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 }

    例子:

    package com.lagou.task10;
    
    public interface AnonymousInterface {
        // 自定义抽象方法
        public abstract void show();
    }
    package com.lagou.task10;
    
    public class AnonymousInterfaceTest {
    
        // 假设已有下面的方法,请问如何调用下面的方法?
        // AnonymousInterface ai = new AnonymousInterfaceImpl();
        // 接口类型的引用指向实现类型的对象,形成了多态
        public static void test(AnonymousInterface ai) {
            // 编译阶段调用父类版本,运行调用实现类重写的版本
            ai.show();
        }
    
        public static void main(String[] args) {
    
            //AnonymousInterfaceTest.test(new AnonymousInterface()); // Error:接口不能实例化
            AnonymousInterfaceTest.test(new AnonymousInterfaceImpl());
    
            System.out.println("---------------------------------------------------------------");
            // 使用匿名内部类的语法格式来得到接口类型的引用,格式为:接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 };
            AnonymousInterface ait = new AnonymousInterface() {
                @Override
                public void show() {
                    System.out.println("匿名内部类就是这么玩的,虽然你很抽象!");
                }
            };
    
            // 从Java8开始提出新特性lamda表达式可以简化上述代码,格式为:(参数列表) -> {方法体}
            AnonymousInterface ait2 = () -> System.out.println("lamda表达式原来是如此简单!");
            AnonymousInterfaceTest.test(ait2);
        }
    }

    lambda 表达式:

    格式为:(参数列表) -> {方法体} //需要重写的方法参数列表 ,需要重写的方法体


    枚举类:

    package com.lagou.task10;
    
    public interface DirectionInterface {
        // 自定义抽象方法
        public abstract void show();
    }
    package com.lagou.task10;
    
    /**
     * 编程实现所有方向的枚举,所有的方向:向上、向下、向左、向右   枚举类型要求所有枚举值必须放在枚举类型的最前面
     */
    public enum DirectionEnum implements DirectionInterface {
        // 2.声明本类类型的引用指向本类类型的对象
        // 匿名内部类的语法格式:接口/父类类型 引用变量名 = new 接口/父类类型() { 方法的重写 };
        // public static final Direction UP = new Direction("向上") { 方法的重写 };
        UP("向上") {
            @Override
            public void show() {
                System.out.println("贪吃蛇向上移动了一下!");
            }
        }, DOWN("向下") {
            @Override
            public void show() {
                System.out.println("贪吃蛇向下移动了一下!");
            }
        }, LEFT("向左") {
            @Override
            public void show() {
                System.out.println("左移了一下!");
            }
        }, RIGHT("向右") {
            @Override
            public void show() {
                System.out.println("右移了一下!");
            }
        };
    
        private final String desc; // 用于描述方向字符串的成员变量
    
        // 通过构造方法实现成员变量的初始化,更加灵活
        // 1.私有化构造方法,此时该构造方法只能在本类的内部使用
        private DirectionEnum(String desc) { this.desc = desc; }
    
        // 通过公有的get方法可以在本类的外部访问该类成员变量的数值
        public String getDesc() {
            return desc;
        }
    
        // 整个枚举类型只重写一次,所有对象调用同一个
        /*@Override
        public void show() {
            System.out.println("现在可以实现接口中抽象方法的重写了!");
        }*/
    }
    package com.lagou.task10;
    
    /**
     * 编程实现方向枚举类的测试,调用从Enum类中继承下来的方法
     */
    public class DirectionEnumTest {
    
        public static void main(String[] args) {
    
            // 1.获取DirectionEnum类型中所有的枚举对象
            DirectionEnum[] arr = DirectionEnum.values();
            // 2.打印每个枚举对象在枚举类型中的名称和索引位置
            for (int i = 0; i < arr.length; i++) {
                System.out.println("获取到的枚举对象名称是:" + arr[i].toString());
                System.out.println("获取到的枚举对象对应的索引位置是:" + arr[i].ordinal()); // 和数组一样下标从0开始
            }
    
            System.out.println("---------------------------------------------------------------");
            // 3.根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象
            //DirectionEnum de = DirectionEnum.valueOf("向下"); // 编译ok,运行发生IllegalArgumentException非法参数异常
            DirectionEnum de = DirectionEnum.valueOf("DOWN");
            //DirectionEnum de = DirectionEnum.valueOf("UP LEFT"); // 要求字符串名称必须在枚举对象中存在
            //System.out.println("转换出来的枚举对象名称是:" + de.toString());
            System.out.println("转换出来的枚举对象名称是:" + de); // 当打印引用变量时,会自动调用toString方法
    
            System.out.println("---------------------------------------------------------------");
            // 4.使用获取到的枚举对象与枚举类中已有的对象比较先后顺序
            for(int i = 0; i < arr.length; i++) {
                // 当调用对象在参数对象之后时,获取到的比较结果为 正数
                // 当调用对象在参数对象相同位置时,则获取到的比较结果为 零
                // 当调用对象在参数对象之前时,则获取到的比较结果为 负数
                System.out.println("调用对象与数组中对象比较的先后顺序结果是:" + de.compareTo(arr[i]));
            }
    
            System.out.println("---------------------------------------------------------------");
            // 5.使用数组中每个DirectionEnum对象都去调用show方法测试
            for (int i = 0; i < arr.length; i++) {
                arr[i].show();
            }
        }
    }

     注解:

       Annotation ,引用数据类型,可以看作特殊接口

      是一种标记,通过这些标记可以在编译、类加载、运行时做指定的处理。

      注解继承 java.lang.annotation.Annotation 接口

      没有成员的注解,叫标记或标识注解

      注解成员变量: public String value();// 声明一个String类型的成员变量

      注解只有成员变量,没有成员方法

      注解的成员变量用无形参的方式来声明,方法名是成员变量的名字,返回值是成员变量的类型

      注解只有一个成员的时候,一般使用value命名

      注解的类型 可以是String ,8种基本数据类型,class,enum,Annotation类型

      注解名称后,使用小括号 value = "hello"

      注解成员变量给默认值: public String value() default “123”;

    元注解:

      可以对注解进行注解

      @Retention     保持,生命周期,有效范围

      @Documented  是否在文档注释中体现

      @Target        表示注解可以修饰哪些内容

      @Inherited     是否可继承

      @Repeatable   可重复

    @Retention :

    取值:

      RetentionPolicy.SOURCE //只在源码阶段保留,在编译时丢弃

      RetentionPolicy.CLASS  // 保留到class文件中,不被加载到JVM

           RetentionPolicy.RUNTIME // 可以保留到运行时

    使用示例:@Retention(RetentionPolicy.SOURCE)

    @Documented:

       javadoc 工具可以抽取类,方法,成员的注释,默认不包括注解内容

      idea: Tools -》Generate JavaDoc   命令行参数指定编码 -encoding utf-8

      @Documented 要求 @Retention(RetentionPolicy.RUNTIME)

      用来表示注解能否被 javadoc工具提取

    使用示例:

      @Retention(RetentionPolicy.RUNTIME)

      @Documented

    @Target:

      指定被修饰的注解可以修饰哪些元素

      取值:枚举类型

    使用示例:

     @Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})

    @Inherited :

      表示注解所修饰的类中的注解 可以被子类继承

    package com.lagou.task10;
    
    import java.lang.annotation.*;
    
    //@Retention(RetentionPolicy.SOURCE)     // 表示下面的注解在源代码中有效
    //@Retention(RetentionPolicy.CLASS)      // 表示下面的注解在字节码文件中有效,默认方式
    @Retention(RetentionPolicy.RUNTIME)      // 表示下面的注解在运行时有效
    @Documented                              // 表示下面的注解信息可以被javadoc工具提取到API文档中,很少使用
    // 表示下面的注解可以用于类型、构造方法、成员变量、成员方法、参数 的修饰
    @Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
    @Inherited  // 表示下面的注解所修饰的类中的注解使用可以被子类继承
    // 若一个注解中没有任何的成员,则这样的注解叫做标记注解/标识注解
    public @interface MyAnnotation {
        //public Direction value(); // 声明一个String类型的成员变量,名字为value   类型有要求
        public String value() default "123"; // 声明一个String类型的成员变量,名字为value
        public String value2();
    }
    package com.lagou.task10;
    
    // 表示将标签MyAnnotation贴在Person类的代码中,使用注解时采用 成员参数名 = 成员参数值, ...
    //@MyAnnotation(value = "hello", value2 = "world")
    @MyAnnotation(value2 = "world")
    public class Person {
        /**
         * name是用于描述姓名的成员变量
         */
        @MyAnnotation(value2 = "1")
        private String name;
        /**
         * age是用于描述年龄的成员变量
         */
        private int age;
    
        /**
         * 编程实现无参构造方法
         */
        @MyAnnotation(value2 = "2")
        public Person() {
        }
    
        /**
         * 编程实现有参构造方法
         * @param name
         * @param age
         */
        public Person(@MyAnnotation(value2 = "4") String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        /**
         * 自定义成员方法实现特征的获取和修改
         * @return
         */
        @MyAnnotation(value2 = "3")
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }

    @Repeatable:

      表示注解可以被重复使用

      需要声明 成员变量是数组的注解

      

    package com.lagou.task10;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Target;
    
    /**
     * 自定义注解里面可以描述多种角色
     */
    @Target(ElementType.TYPE_USE)
    public @interface ManTypes {
        ManType[] value();
    }
    package com.lagou.task10;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Repeatable;
    import java.lang.annotation.Target;
    
    /**
     * 自定义注解用于描述任务的角色
     */
    @Repeatable(value = ManTypes.class)
    @Target(ElementType.TYPE_USE)
    public @interface ManType {
        String value() default "";
    }
    package com.lagou.task10;
    
    @ManType(value = "职工")
    @ManType(value = "超人")
    //@ManTypes({@ManType(value = "职工"), @ManType(value = "超人")})  // 在Java8以前处理多个注解的方式
    public class Man {
    
        @Deprecated // 表示该方法已经过时,不建议使用
        public void show() {
            System.out.println("这个方法马上过时了!");
        }
    
        public static void main(String[] args) {
            int ia = 97;
            char c1 = (@ManType char) ia;
        }
    }

     预制注解:

      @Override 重写

      @Deprecated 过时

      @SuppressWarings 抑制编译器警告

    文章来自拉勾教育 大数据开发

      

      

     

      

      

  • 相关阅读:
    C# 高级编程语言
    unity ForceMode
    UnityError 切换场景灯光变黑问题解决
    Unity Time.timeScale
    Unity 打开网页 Application.OpenURL(字符串);
    Unity www动态加载网上图片
    Unity GameObject.Find 和 transform.Find
    Unity UGUI按钮添加点击事件
    事务
    git和redis
  • 原文地址:https://www.cnblogs.com/wanghzh/p/14579315.html
Copyright © 2011-2022 走看看