0
点赞
收藏
分享

微信扫一扫

面向对象代码练习

Star英 2022-05-01 阅读 91

文章目录


前言

代码练习
详细的解释都在代码中给出


成员变量和局部变量的区别?

package 面向对象;

/*
    成员变量和局部变量的区别?
        A:在类中的位置不同
            成员变量:在类中方法外
            局部变量:在方法定义中或者方法声明上
        B:在内存中的位置不同
            成员变量:在堆内存
            局部变量:在栈内存
        C:生命周期不同
            成员变量:随着对象的创建而存在,随着对象的消失而消失
            局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
        D:初始化值不同
            成员变量:有默认初始化值
            局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

        注意事项:
            局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
*/
class Varialbe {
    //成员变量
    //int num = 10;
    int num; //0

    public void show() {
        //int num2 = 20; //局部变量
        //可能尚未初始化变量num2
        //int num2; //没有默认值
         int num2 = 20;
        System.out.println(num2);//这里报错,num2没有默认值

        int num = 100;
        System.out.println(num);
    }
}


class VariableDemo {
    public static void main(String[] args) {
        Varialbe v = new Varialbe();

        System.out.println(v.num); //访问成员变量 0

        v.show();// 20 100

    }
}

匿名对象

package 面向对象;

/*
    匿名对象:就是没有名字的对象。

    匿名对象的应用场景:
        A:调用方法,仅仅只调用一次的时候。
            注意:调用多次的时候,不适合。因为会重新生成对象
            那么,这种匿名调用有什么好处吗?
                有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
        B:匿名对象可以作为实际参数传递
*/
class NiMing {
    public void show() {
        System.out.println("我爱学习");
    }
}

class NiMingDemo {
    public void method(NiMing s) {
        s.show();
    }
}

class NoNameDemo {
    public static void main(String[] args) {
        //带名字的调用
        NiMing s = new NiMing();
        s.show();
        s.show();
        System.out.println("--------------");

        //匿名对象
        //new NiMing();
        //匿名对象调用方法
        new NiMing().show();
        new NiMing().show(); //这里其实是重新创建了一个新的对象
        System.out.println("--------------");


        //匿名对象作为实际参数传递
        NiMingDemo sd = new NiMingDemo();
        //NiMing ss = new NiMing();
        //sd.method(ss); //这里的s是一个实际参数
        //匿名对象
        sd.method(new NiMing());

        //在来一个
        new NiMingDemo().method(new NiMing());
    }
}

内部类

  • 匿名内部类
  • 成员内部类
  • 局部内部类
package 面向对象;
/**
 * 匿名内部类
 *         就是内部类的简化写法。
 *
 *     前提:存在一个类或者接口
 *         这里的类可以是具体类也可以是抽象类。
 *
 *     格式:
 *         new 类名或者接口名(){
 *             重写方法;
 *         }
 *
 *     本质是什么呢?
 *         是一个继承了该类或者实现了该接口的子类的匿名对象。
 */
interface Inter4 {
    public abstract void show();
    public abstract void show2();
}
/**
    内部类概述:
        把类定义在其他类的内部,这个类就被称为内部类。
        举例:在类A中定义了一个类B,类B就是内部类。

    内部的访问特点:
        A:内部类可以直接访问外部类的成员,包括私有。
        B:外部类要访问内部类的成员,必须创建对象。

*/
class Outer1 {
    private int num = 10;
    class Inner1 {
        public void show() {
            //内部类可以直接访问外部类的成员,包括私有。
            System.out.println(num);
        }
    }
    public void method() {
        //找不到符号
        //show();

        //外部类要访问内部类的成员,必须创建对象。
        Inner1 i = new Inner1();
        i.show();
    }
    /**
     * 成员内部类的修饰符:
     *         private 为了保证数据的安全性
     *         static 为了方便访问数据
     *             注意:静态内部类访问的外部类数据必须用静态修饰。
     */
    private static int num2 = 100;
    public static class Inner2{
        public void show(){
            //System.out.println(num);
            System.out.println(num2);
        }
        public static void show2() {
            //System.out.println(num);//报错。静态内部类访问的外部类数据必须用静态修饰。

            System.out.println(num2);
        }
    }

    /**
     * 注意:
     *         1:内部类和外部类没有继承关系。
     *         2:通过外部类名限定this对象
     *             Outer.this
     */
    public int num3 = 10;
    class Inner3{
        public int num3 = 20;
        public void show(){
            int num3 = 30;
            System.out.println(num3);//30
            System.out.println(this.num3);//20
            System.out.println(Outer1.this.num3);//10
            System.out.println(num);//10
        }
    }

    /**
     * 局部内部类
     *         A:可以直接访问外部类的成员
     *         B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
     *
     *     注意事项:
     *         局部内部类访问局部变量的注意事项?
     *         A:局部内部类访问局部变量必须用final修饰
     *         B:为什么呢?
     *             局部变量是随着方法的调用而调用,随着调用完毕而消失。
     *             而堆内存Inner的内容并不会立即消失。所以,我们加final修饰。
     *             加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
     *             我在内存中存储的是数据20,所以,我还是有数据在使用。
     */
    private int num4 = 40;
    public void method2(){
        final int num5 = 50;//局部内部类访问局部变量必须用final修饰
        class Inner{
            public void show(){
                System.out.println(num4);
                System.out.println(num5);
            }
        }
        Inner i = new Inner();
        i.show();
    }

    public void method3() {

        Inter4 i = new Inter4() { //多态
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        };

        i.show();//是一个继承了该类或者实现了该接口的子类的匿名对象。所以可以调用方法
        i.show2();
    }

}

class InnerClassDemo {
    public static void main(String[] args) {
        //需求:我要访问Inner类的show()方法

        //格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
        Outer1.Inner1 oi1 = new Outer1().new Inner1();
        oi1.show();//10
        System.out.println("--------------------------");
        //成员内部类被静态修饰后的访问方式是:
        //格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
        Outer1.Inner2 oi2 = new Outer1.Inner2();
        oi2.show();
        oi2.show2();

        //show2()的另一种调用方式。因为静态方法,可以通过类名调用。
        Outer1.Inner2.show2();
        System.out.println("--------------------------");
        Outer1.Inner3 oi3 = new Outer1().new Inner3();
                oi3.show();
        System.out.println("--------------------------");
                Outer1 o = new Outer1();
                o.method2();
        System.out.println("--------------------------");
        Outer1 o2 = new Outer1();
        o.method3();
    }
}

基本类型与引用类型

package 面向对象;

/*
    形式参数的问题:
        基本类型:形式参数的改变不影响实际参数
        引用类型:形式参数的改变直接影响实际参数
*/
//形式参数是基本类型
class Demo_ji {
    public int sum(int a,int b) {
        a=b;
        b=a+b;
        System.out.println("a:"+a+",b:"+b);
        return a + b;
    }
}

//形式参数是引用类型
class Demo_yin {
    public void show() {
        System.out.println("我爱学习");
    }

    public void reverse(int[] arr){
        int t;
        for (int i = 0; i < (arr.length/2); i++) {
            t=arr[i];
            arr[i]=arr[arr.length - i -1];
            arr[arr.length - i -1]=t;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);
        }
    }
}

class Demo {
    //如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
    public void method(Demo_yin s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
        s.show();
    }
}

class ArgsTest {
    public static void main(String[] args) {
        //形式参数是基本类型的调用
        //基本类型:形式参数的改变对实际参数没有影响。基本类型传递的是数据值
        Demo_ji d = new Demo_ji();
        int a=10;int b=20;
        int result = d.sum(a,b);
        System.out.println("result:"+result);//a:20,b:40 result:60
        System.out.println("a:"+a+",b:"+b);//a:10,b:20
        System.out.println("--------------");

        //形式参数是引用类型的调用
        //需求:我要调用Demo类中的method()方法
        Demo sd = new Demo();
        //创建引用对象
        Demo_yin s = new Demo_yin();
        sd.method(s); //把s的地址给到了这里
        System.out.println("--------------");
        //引用类型:形式参数的改变直接影响实际参数。引用类型传递的是地址值
        int[] arr = {1,2,3,4,5};
        s.reverse(arr);//54321
        System.out.println("--------------");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]);//54321
        }

    }
}

标准类

  • 封装
  • static
  • this
  • hashcode
  • tostring
  • equals 与 ==
  • 静态代码块,构造代码块,构造方法的执行顺序?
  • 代码:Student s = new Student();做了哪些事情?
package 面向对象;

public class Student {
    /**
     *  private:私有的。可以修饰成员变量和成员方法。
     *  注意:被private修饰的成员只能在本类中访问。
     *  封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
     */
    //姓名
    private String name;
    //年龄
    private int age;
    /**
     * 针对多个对象有共同的这样的成员变量值的时候,
     *         Java就提高了一个关键字来修饰:static。
     * static关键字注意事项
     *         A:在静态方法中是没有this关键字的
     *             如何理解呢?
     *                 静态是随着类的加载而加载,this是随着对象的创建而存在。
     *                 静态比对象先存在。先存在的,不能访问后面进来的。
     *         B:静态方法只能访问静态的成员变量和静态的成员方法
     *                 静态方法:
     *                     成员变量:只能访问静态变量
     *                     成员方法:只能访问静态成员方法
     *                 非静态方法:
     *                     成员变量:可以是静态的,也可以是非静态的
     *                     成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
     *             简单记:
     *                 静态只能访问静态。
     */
    static String country;

    //非静态变量
    int num = 10;

    //静态变量
    static int num2 = 20;


    //构造方法
    //public Student() {
    //}

    /**
     * 代码块:在Java中,使用{}括起来的代码被称为代码块。
     *     根据其位置和声明的不同,可以分为
     *         局部代码块:局部位置,用于限定变量的生命周期。
     *         构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
     *             作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。
     *         静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
     *             作用:一般是对类进行初始化。
     *
     *     面试题?
     *         静态代码块,构造代码块,构造方法的执行顺序?
     *         静态代码块 -- 构造代码块 -- 构造方法
     *         静态代码块:只执行一次
     *         构造代码块:每次调用构造方法都执行
     */
    static {
        System.out.println("Student 静态代码块");
    }

    public Student() {
        System.out.println("Student 构造方法");
    }

    {
        System.out.println("Student 构造代码块");
    }

    /**
     * this
     * (1)代表当前类的引用对象
     *         记住:哪个对象调用方法,该方法内部的this就代表那个对象
     * (2)this的应用场景:
     *         A:解决了局部变量隐藏成员变量的问题
     *
     * 构造方法:
     *         给对象的数据进行初始化
     *
     *     格式:
     *         A:方法名与类名相同
     *         B:没有返回值类型,连void都没有
     *         C:没有具体的返回值
     */
    //构造方法
    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public Student(String name,int age,String country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }


    public static String getCountry() {
        return country;
    }

    public static void setCountry(String country) {
        Student.country = country;
    }
    //带返回值的成员方法
    public String getName() {
        //this:哪个对象调用那个方法,this就代表那个对象
        return name;
    }

    //不带返回值的成员
    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    //带参数的成员方法
    public void setAge(int age) {
        this.age = age;
    }

    //输出所有的成员变量值
    public void show() {
        System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", num=" + num +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

package 面向对象;

public class StudentTest {
    /**
     * public:权限最大
     * static:不用创建对象调用
     * void:返回值给jvm没有意义
     * main:就是一个常见的名称。
     * String[] args:可以接收数据,提供程序的灵活性
     * 格式:java MainDemo hello world java
     *      java MainDemo 10 20 30
     * @param args
     */
    static {
        System.out.println("主函数中静态代码块");
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        /** 代码:Student s = new Student();做了哪些事情?
         *     (1)把Student.class文件加载到内存
         *     (2)在栈内存为s开辟空间
         *     (3)在堆内存为学生对象申请空间
         *     (4)给学生的成员变量进行默认初始化。null,0
         *     (5)给学生的成员变量进行显示初始化。林青霞,27
         *     (6)通过构造方法给成员变量进行初始化。刘意,30
         *     (7)对象构造完毕,把地址赋值给s变量
         */
        //方式1给成员变量赋值
        //无参构造+setXxx()
        Student s1 = new Student();
        s1.setName("林青霞");
        s1.setAge(27);
        //输出值
        System.out.println(s1.getName()+"---"+s1.getAge());
        s1.show();


        //方式2给成员变量赋值
        Student s2 = new Student("刘意",30);
        System.out.println(s2.getName()+"---"+s2.getAge());
        s2.show();

        Student s3 = new Student("邓丽君",16,"中国");
        s3.show();

        Student s4 = new Student();
        System.out.println(s4.num);//10

        System.out.println(Student.num2);//推荐类名调用
        System.out.println(s4.num2);//20

        Student s5 = new Student();
        /*
        *   主函数中静态代码块
            Student 静态代码块
            Student 构造代码块
            Student 构造方法
            林青霞---27
            姓名:林青霞,年龄:27,国籍:null
            Student 构造代码块
            刘意---30
            姓名:刘意,年龄:30,国籍:null
            Student 构造代码块
            姓名:邓丽君,年龄:16,国籍:中国
            Student 构造代码块
            Student 构造方法
            10
            20
            20
            Student 构造代码块
            Student 构造方法
        * */
        System.out.println("----------------------------");
        Student s6 = new Student();
        /*
             Student 构造代码块
             Student 构造方法
         */

        /**
         * Object:类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
         * 每个类都直接或者间接的继承自Object类。
         *
         * Object类的方法:
         *         public int hashCode():返回该对象的哈希码值。
         *             注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值。
         *                        你可以理解为地址值。
         *
         *        public final Class getClass():返回此 Object 的运行时类
         *            Class类的方法:
         *                public String getName():以 String 的形式返回此 Class 对象所表示的实体
         */
        System.out.println("----------------------------");
        Student o1 = new Student();
        System.out.println(o1.hashCode());//1163157884
        Student o2 = new Student();
        System.out.println(o2.hashCode());//1956725890
        Student o3 = o1;
        System.out.println(o3.hashCode());//1163157884
        System.out.println("------------------------------");

        Student o4 = new Student();
        Class c = o4.getClass();
        System.out.println(c);//class 面向对象.Student
        String str = c.getName();
        System.out.println(str); // 面向对象.Student

        //链式编程
        String str2  = o4.getClass().getName();
        System.out.println(str2);//面向对象.Student
        System.out.println("-----------------------------");
        /**
         * public String toString():返回该对象的字符串表示。
         * 直接输出一个对象的名称,其实就是调用该对象的toString()方法。
         *
         * Integer类下的一个静态方法:
         *          public static String toHexString(int i):把一个整数转成一个十六进制表示的字符串
         *
         * toString()方法的值等价于
         *      getClass().getName() + '@' + Integer.toHexString(hashCode())
         *      this.getClass().getName()+'@'+Integer.toHexString(this.hashCode())
         */
        System.out.println(o4.toString());// 面向对象.Student@1540e19d
        System.out.println(o4.getClass().getName() + '@'
                + Integer.toHexString(o4.hashCode()));//面向对象.Student@1540e19d
        System.out.println(o4);//面向对象.Student@1540e19d
        System.out.println("--------------------");

        /**
         * public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。
         * 这个方法,默认情况下比较的是地址值。比较地址值一般来说意义不大,所以我们要重写该方法。
         * 怎么重写呢?
         *         一般都是用来比较对象的成员变量值是否相同。
         * 重写的代码优化:提高效率,提高程序的健壮性。
         * 最终版:
         *         其实还是自动生成。
         *
         * 看源码:
         *         public boolean equals(Object obj) {
         *             //this - s1
         *             //obj - s2
         *           return (this == obj);
         *       }
         *
         * ==:
         *         基本类型:比较的就是值是否相同
         *         引用类型:比较的就是地址值是否相同
         * equals:
         *         引用类型:默认情况下,比较的是地址值。
         *         不过,我们可以根据情况自己重写该方法。一般重写都是自动生成,比较对象的成员变量值是否相同
         */
        Student e1 = new Student("e1",1);
        Student e2 = new Student("e1",1);
        System.out.println(e1==e2);//false
        Student e3 = e1;
        System.out.println(e1==e3);//true

        System.out.println(e1.equals(e2));//false
        System.out.println(e1.equals(e1));//true
        System.out.println(e1.equals(e3));//true

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

        /**
         *    protected void finalize():当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。用于垃圾回收,但是什么时候回收不确定。
         *    protected Object clone():创建并返回此对象的一个副本。
         *        A:重写该方法
         *
         *  Cloneable:此类实现了 Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。
         *      这个接口是标记接口,告诉我们实现该接口的类就可以实现对象的复制了。
         *      让被克隆的类实现该接口,才可以克隆
         */
    //    Student c1 = new Student();
    //    c1.setName("克隆");
    //    c1.setAge(22);
        克隆
    //    Object obj = c1.clone();
    //    Student c2= (Student) obj;
    }
}

举报

相关推荐

0 条评论