面向对象案例

面向对象(上)

1、类和对象

定义类

什么是对象?

具体的实体,比如我是一个对象,我的宠物狗二哈也是一个对象

什么是类?

类就是对象的抽象,比如我是人类,二哈是狗类

java中定义对象的语法

[修饰符] class类名
{
零到多个构造器定义...
零到多个成员方法...
零到多个方法...
}

注意,修饰符static

//定义一个Person类

public class Person(){
private  int  age;
private  String name;

//空值构造器
public Person(){
}

//有参构造器
public Person(int age , String name){
  this.age = age;
  this.name=name;
}

publci void  say(){
System.out.println("说话..")
}

}
//创建对象
Person p = new Person();
//给对象赋值
p.name = "张三";
p.age = 13;
//调用方法
p.say();

this的调用

public class Dog(){
//先设定一个run的方法
public void run(){
System.out.println("小狗在奔跑");
}
//在设定一个跳的方法,假定要调用run方法
/*
        public void jump(){
        Dog d = new Dog;
        d.run;
        System.out.println("小狗在跳");

        }

*/

//但是上面创建类的过程可以用this来代替
        public void jump(){
         this.run;
         System.out.println("小狗在跳");

        }

}

2、方法详解

方法不能独立执行,一定是"对象.方法"或者是"类.方法"执行,如果单独存在方法,是因为省略了this

参数的传递

public class transforTest{

           public static void swap(int a , int b){

            int temp =   a ;

            a = b;

             b = temp;
             
            System.out.println("a的值为"+a+"; b的值为"+b);

        }
        public static void main(String args[]){
        
        int a = 6;
        int b = 9;
        swap(a , b);
        
        System.out.println("a的值为"+a+"; b的值为"+b);
        }

}
/**
第一个输出显示:a值为9,b值为6
第二个输出显示:a值为6,b值为9
因为在方法中的参数不与main中的参数相同,虽然它们都叫a,并且swap方法没有返回a与b,所以在swap方法里交换后,不影响a,b的输出值
*/

方法的重载

public class Overload(){
    public void test(){
    System.out.println("这是一个测试方法");
    }
    public void test(String content){
    System.out.println("传入的内容为"+ content);
    }
    public static void main(String args[]){
    Overload o = new Overload();
    
    o.test();
    o.test("重载的方法");
    
    }

}
/**
传入的参数不一致,导致使用的方法也不一致,这就是方法的重载
*/

3、成员变量和局部变量

成员变量与类变量的例子

class Person{
    //Person类的实例变量
    public String name;
    //Person类的类变量
    public static int eyeNum;

}


public class PersonTest{

    public static void main(String[] args) {
        //首先输出Person类的eyeNum,类对象进行过初始化,因此输出0
        System.out.println("Person类的类变量eyeNum的初始值为" + Person.eyeNum);
        //建立一个Person对象,对Person的实例变量和类变量进行赋值
        Person p1 = new Person();
        System.out.println("没有复制之前的类变量eyeNum的值为" + p1.eyeNum  + ";  实例变量值为"+p1.name);
        p1.name = "孙悟空";
        p1.eyeNum = 2;
        System.out.println("p1的类变量eyeNum的值为" + p1.eyeNum  + ";  p1的实例变量值为"+p1.name);
        System.out.println("Person类的类变量eyeNum的值为" + Person.eyeNum);
        //建立另外一个对象p2,因为前面对类变量进行赋值,所以直接输出值为2
        Person p2 = new Person();
        //eyeNum属于类的,因此输出为2,但name属于实例的,因此输出为null
        System.out.println("p2的类变量eyeNum的值为" + p2.eyeNum +"p2的name的值为:"+p2.name);


    }

注意:实例变量是随之对象的建立而建立的 ,两个实例对象的变量之间并没有什么关系

建议:因为类变量任何对象都可以访问,因此使用时最好以类为主调,而不是对象,这样可以避免产生歧义

局部变量

public class VariableTest {
    //定义一个实例变量
    public String name="李芳";
    //定义一个类变量
    public static double price = 98.0;

    public void info(){
        //局部方法的变量会覆盖重名的类变量和实例变量,且在方法结束后会被销毁
        String name = "老王";
        System.out.println(name);
        //使用this为变量做限定则可以输出实例变量的值
        System.out.println(this.name);

    }

    public static void main(String[] args) {
        //同样的,局部变量会覆盖类变量
        int price = 65;
        System.out.println(price);
        //使用类名做限定
        System.out.println(VariableTest.price);
        //运行info方法
        new VariableTest().info();
    }
}

4、隐藏和封装

封装举例

使用get和set封装

public class Person {
    
    //使用private修饰,让这些变量都隐藏起来
    private String name;
    private int age;
    
    //提供方法来操作变量
    
    public void setName(String name){
        //执行校验程序
        if (name.length() > 6 || name.length() < 2){
            System.out.println("您的命名不符合规范");
            return;
        }else{
            this.name = name;
        }
    }

    public String getName() {
        return this.name;
    }


    public void setAge(int age){
        //执行校验程序
        if (age > 150|| age < 0){
            System.out.println("您的输入不符合规范");
            return;
        }else{
            this.age = age;
        }
    }

    public int getAge() {
        return this.age;
    }
}

操作对象的age和name

public class PersonTest {
    public static void main(String[] args) {
        Person p = new Person();
        p.setName("王小二");
        p.setAge(7);
        System.out.println("输出set后的名字:"+p.getName() + "; 输出set后的年龄:"+ p.getAge());
    
    }
}

Java的常用包

java.lang:这个包下包含的Java语言的核心类,如Stirng、Math、System和Thread,这个包无需import导入,系统会自动导入
java.util:这个包下包含了Java的大量工具类和集合框架类/接口,如Arraylist\List\Set等
java.net:这个包下包含了网络编程相关的类\接口
java.io:这个包下包含了输入\输出相关的类\接口
java.text:这个包下包含了一些Java格式化相关的类
java.sql:这个包下包含了JDBC数据库相关的类\接口

5、构造器

将所有的实例变量实行初始化

public class ConstructorTest {
    public String name;
    public int count;
    //自定义构造器
    public  ConstructorTest(String name , int count){
        this.count=count;
        this.name = name;
    }

    public static void main(String[] args) {
        ConstructorTest c = new ConstructorTest("狼王",12);
        System.out.println(c.count);
        System.out.println(c.name);
    }

}

构造器的重载

public class ConstructorTest {
    public String name;
    public int count;
    public int age;
    //自定义构造器
    public  ConstructorTest(String name , int count){
        this.count=count;
        this.name = name;
    }
    public  ConstructorTest(String name , int count,int age){
        this(name,count);
        this.age = age;
    }

    public static void main(String[] args) {
        ConstructorTest c = new ConstructorTest("狼王",12,43);
        System.out.println(c.count);
        System.out.println(c.name);
        System.out.println(c.age);
    }

}

6、类的继承

子承父类,子类拥有父类的全部成员变量和方法

例子

public class Fruit {
    public double weight;
    public String name="水果";
    
    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public void info(){
        System.out.println("我是一个水果,重"+weight+"g");
    }
}
public class Apple  extends  Fruit{
    public static void main(String[] args) {
        Apple a = new Apple();
        a.setWeight(91.0);
        a.info();
    }
    
}

父类不变,子类重写方法

public class Apple  extends  Fruit{

    public void info(){
        System.out.println("重写父类的方法");
    }
    public static void main(String[] args) {
        Apple a = new Apple();
        a.info();

        }

    }

super关键字的作用

public class Apple  extends  Fruit{

    public void info(){
        System.out.println("重写父类的方法");
    }

    public void replay(){
        System.out.println(super.name);
        super.info();
    }
    public static void main(String[] args) {
        Apple a = new Apple();
        a.weight  = 98.0;
        a.info();
        //调用方法输出“水果”和执行父类info()方法
        a.replay();
        //输出“水果”
        System.out.println(((Fruit)a).name);
        System.out.println("=========replay方法结束以后重新赋值===============");
        a.name = "苹果";
        System.out.println(a.name);
        }

    }


super可以访问被子类隐藏的父类实例变量和方法,不仅如此,super还可以继承父类构造器

class Base{
    public double size;
    public String name;
    public Base(double size , String name){
        this.size = size;
        this.name = name;
    }
}

public class Sub extends Base{

    public String color;
    public Sub(double size, String name , String color) {
        super(size, name);
        this.color = color;
    }

    public static void main(String[] args) {
        Sub s = new Sub(5.6 , "测试对象","红色");
        System.out.println(s.size + "--"+s.color+"--"+s.name);
    }
}

7、多态

运行时的状态和编译时的不一致

class BaseClass {

    public String  name = "父类的名字";
    public void info(){
        System.out.println("父类的的方法");
    }
    public void test(){
        System.out.println("父类即将被覆盖的方法");
    }

}


public class SubClass extends BaseClass {
    public String name = "子类的名字";
    public void test(){
        System.out.println("子类覆盖父类的方法");
    }
    public void sub(){
        System.out.println("子类的普通方法");
    }

    public static void main(String[] args){
        System.out.println("=====================父类===================");
        BaseClass baseClass = new BaseClass();
        System.out.println(baseClass.name);
        baseClass.info();
        baseClass.test();
        System.out.println("=====================子类===================");
        SubClass subClass = new SubClass();
        System.out.println(subClass.name);
        subClass.sub();
        subClass.test();
        System.out.println("=====================多态===================");
        BaseClass p  = new SubClass();
        //将输出的是父类的实例变量
        System.out.println(p.name);
        //执行的是当前类的test方法
        p.test();
        //下面的方法失效,因为编译时是BaseClass类,没有提供sub()方法
        //p.sub();
        //因此可以强行转换
        SubClass s = (SubClass) p;
        s.sub();


    }
}

例子中的p编译时的类型是BaseClass,运行时类型是SubClass

强行转换

public class Test {
    public static void main(String[] args) {
        double d = 13.4;
        long l = (long)d;
        System.out.println(l);
        int in = 5;
        //试图把一个数值类型的变量转换为boolean类型,下面代码编译出错
        //编译时会提示:不可转类型
        //boolean  b =  (boolean)in;
        Object obj = "hello";
        //obj变量编译时类型为Object,Object与String类型存在继承关系,可以强制类型转换
        //而且obj变量的实际类型是String,所以运行时也能通过
        String objstr = (String)obj;
        System.out.println(objstr);

        //定义一个ObjPri变量,编译时类型为Object,实际类型为Integer
        Object objPri = new Integer(5);
        //objPri变量的编译类型为Object,实际运行类型为Integer
        //Object与Integer存在继承关系
        //可以强制类型转换,而objPri变量的实际类型是Integer
        //所以下面代码引发ClassCastException异常
        //String str = (String)objPri;

        //但是可以用instanceof进行判断是否可以成功转换
        if (objPri instanceof String){
            String str = (String)objPri;
        }else {
            System.out.println("不可以强制转换");
        }
    }
}

8、组合

组合案例

import org.w3c.dom.ls.LSOutput;

class  Animal{
    private  void beat(){
        System.out.println("心脏在跳动");
    }
    public void breath(){
        beat();
        System.out.println("呼吸~~~~");
    }
}

class Bird {
    private Animal a;

    public Bird(Animal a){
        this.a = a;
    }
    public void breath(){
        a.breath();
    }
    public void fly(){
        System.out.println("鸟会飞");
    }
}

class fish{
    private Animal a;
    public fish(Animal a){
        this.a = a;
    }
    public void breath(){
        a.breath();
    }
    public void swim(){
        System.out.println("鱼会游");
    }
}

public class CompileTest {

    public static void main(String[] args) {
        //需要显示创建被组合的对象
        Animal a1 = new Animal();
        Bird b = new Bird(a1);
        b.breath();
        b.fly();
        //需要显示创建被组合的对象
        Animal a2 = new Animal();
        fish f = new fish(a2);
        f.breath();
        f.swim();
    }

}

9、初始化块

初始化块代码无需输入参数,可以更好地提高代码的复用性

实际上,初始化块代码是一个假象,经过Javac编译后,会还原到没有构造器中

class  Root{
    static {
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root(){
        System.out.println("Root的无参构造器");
    }
}
class Mid extends Root{
    static {
        System.out.println("Mid的静态的初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid(){
        System.out.println("Mid的无参数构造器");
    }
    public Mid(String msg){
        //通过this调用同一类中重载的构造器
        this();
        System.out.println("Mid的带参数构造器,其参数值为"+msg);
    }
}

class Leaf extends Mid{
    static {
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }
    public Leaf(){
    //通过super调用父类中一个带有参数的构造器
        super("Java");
        System.out.println("执行Leaf的构造器");
    }
}

public class  Test{
    public static void main(String[] args) {
        new Leaf();
        new Leaf();
    }
}

面向对象(下)

1、Java8的增强包装类

自动装箱,自动拆箱

public class AutoBoxingUnboxing {
    public static void main(String[] args) {
        //直接把一个基本类型变量赋给Integer对象
        Integer inObj  =5 ;
        //直接把一个boolean类型变量赋给一个Object类型
        Object boolObj = true;
        //直接把一个Integer对象赋给int类型的变量
        int it = inObj;
        if (boolObj instanceof Boolean) {
         //先把Object对象 对象强制类型转换为Boolean类型,再赋给boolean变量
            boolean b = (Boolean)boolObj;
            System.out.println(b);
        }
    }
}

类型转换

public class Primitive2String {
    public static void main(String[] args){
        //把一个String类型转换为Int类型
        String instr  =  "123";
        int in = Integer.parseInt(instr);
        System.out.println(in);

        System.out.println("==========================");
        //把String类型转换为float类型
        String floatstr = "123.432";
        float fs = Float.parseFloat(floatstr);
        System.out.println(fs);

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

        //把float类型转换为String类型
        float f1 = 124.65f;
        String f2 = String.valueOf(f1);
        System.out.println(f2);

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

        //把一个double变量转换为Sting变量
        double d = 132.4;
        String s = String.valueOf(d);
        System.out.println(d);
        System.out.println("==========================");

        //把一个boolean转换为String变量
        boolean b = true;
        String bl = String.valueOf(b);
        System.out.println(bl);

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

    }
}

注意Integer的范围

Integer ina = 2;
Integer inb = 2;
System.out.println(ina == inb)//输出true
Integer inc = 128;
Integer ind = 128;
System.out.println(inc == ind)//输出false

//因为系统把-128~127之间的整数自动装箱成Integer实例,并放入了一个数组缓存起来,在[-128,127]自动装箱实际上指的是同一个数组元素,所以相等。但是在范围外,系统总是重新创建一个实例,两个实例不相等。

Java8的无符号运算

public class UnsignedTest {
    public static void main(String[] args) {
        byte b  = -3;
        //将byte类型的-3转换为无符号整数
        System.out.println("byte类型的-3对应的无符号整数"+Byte.toUnsignedInt(b));
        //指定使用16进制解析无符号整数
        int val = Integer.parseUnsignedInt("ab",16);
        System.out.println(val);//输出171
        //将-12转换为无符号int性,然后转换为16进制的字符串
        System.out.println(Integer.toUnsignedString(-12,16));
        //将两个数转换为无符号整数后相除
        System.out.println(Integer.divideUnsigned(-2,3));
        //将两个数转换为无法呼号整数后求余
        System.out.println(Integer.remainderUnsigned(-2,7));
    }
}

2、处理对象

toString

toString是一个“自我描述”的方法,当程序员打印该对象时,系统将会输出该对象的“自我描述”信息,用以告诉外界该对象具有的状态信息

import org.w3c.dom.ls.LSOutput;

class Apple{
    private String color;
    private double weight;
    public Apple(){

    }
    public Apple(String color , double weight){
        this.weight = weight;
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }
}

public class ToStringTest {
    public static void main(String[] args) {
        Apple a = new Apple("红色",5.7);
        System.out.println(a);
    }
}

== 和equals

== : 如何两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),只要两个变量的值相等,就将返回true。对于应用比那辆,只有他们指向同一个对象时,才会返回true。

equals:提供自定义相等的标准

当使用new String("hello")时,JVM会先使用常量池来管理"hello"常量,再调用String类的构造器来创建一个新的String对象。新建的String对象被保存在堆内存中。也就是说new String("hello")实际上产生了两个字符串对象

3、类成员

类成员有:成员变量、成员方法、构造器、初始化块、内部类(接口、枚举)

当使用实例来访问类成员是,实际上依然是委托该类来访问类成员,因此即使某个实例为null,它也可以访问它所属的类的类成员,例如下面代码:

public class NullAccessStatic {
    private  static void test(){
        System.out.println("static修饰的方法");
    }

    public static void main(String[] args) {
        NullAccessStatic S = null;
        S.test();
    }
}

4、final修饰符

final成员变量

final修饰的成员变量必须有程序员显示地指定初始值,没有final修饰的成员变量系统会赋默认值

public class FinalVariableTest {
    //定义成员变量时指定默认值,合法
    final int a = 6;
    //下面变量将在构造器或初始化块中分配初始值
    final String str;
    final int c ;
    final static double d;
    
    
    //不能打印没有初始化的值
    //final int age;
    //下面代码将出错:
    // public static void main(String[] args){System.out.println(age)}


    //既没有指定默认值,有没有在初始化块,构造器中指定初始值
    //下面定义的ch实例变量时不合法的
    //final char ch;
    //初始化块,可对没有指定默认值的实例变量指定初始值
    {
        //在初始化块中为实例变量指定初始值
        str = "hello";
        //定义a实例变量时已经指定了默认值
        //不能为a重新赋值,因此下面赋值语句非法
        //a = 9;

    }

    //静态初始化块,可对没有指定默认值的类变量指定初始值
    static {
        //在静态初始化块中位类变量指定初始值,合法
        d = 5.6;
    }

    //构造器,可对即没有指定默认值,有没有在初始化块中指定初始值的实例变量指定初始值
    public FinalVariableTest(){
        //如果在初始化块中已经对str指定了初始值
        //那么在构造器中不能对final变量重新赋值
        //str="java";
        c = 5;
    }

    public void changeFinal(){
        //普通方法不能为final修饰的成员变量赋值
        //d =1.2;
        //不能再普通方法中位final成员变量指定初始值
        //ch = 'a';
    }

    public static void main(String[] args) {
        FinalVariableTest f = new FinalVariableTest();
        System.out.println(f.a);
        System.out.println(f.d);
        System.out.println(f.c);

    }
}

局部变量

public class FinalLoalVariableTest {
    public void test(final  int a ){

        //不能对形参赋值,下面语句非法
        // a = 7;
        System.out.println("这个衬衫的价格是"+ a + "元");
    }

    public static void main(String[] args) {
        final  int  b ;
        b  = 8 ;
        //下面语句非法
        // b = 10;
         FinalLoalVariableTest s =  new FinalLoalVariableTest();
         s.test(2);
    }
}

final修饰基本类型变量和引用类型变量的区别

class Person{
   private int age;

    public Person(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                '}';
    }
}

public class FinalTest {
    public static void main(String[] args) {
        final  int[] Arri = {1 , 2, 3 ,4, 5, 6};
        //可以对Arri内的值进行赋值
        Arri[2] = 4;
        System.out.println(Arri[2]);
        //但是不能对Arri进行赋值
        //Arri = 1;
        final Person p = new Person(24);
        //可以对age重新赋值
        p.setAge(54);
        System.out.println(p.getAge());
        //但时对p重新赋值是非法的
        //p = null;

    }
}

宏替换

public class FinalLocalTest {
    public static void main(String[] args) {
     //定义一个局部变量
     final int a = 5;
        System.out.println(a);
    }
}
/**
 * 程序定义了一个局部final变量,并在定义时赋予初始值为5,对这个程序来说,a根本不存在,当执行System.out.println(a);时,
 * 实际执行System.out.println(a);
 */

fianl修饰符的一个重要用途就是定义"宏变量",编一个群会把程序中用到宏变量的值直接替换成该变量的值

public class FinalReplaceTest {
    public static void main(String[] args) {
        final int a = 9;
        int a1 = 9;
        //如果被富于的表达式只是基本的算是表达式或者字符串连接运算,没有访问普通变量,或者调用方法
        //那么Java编译器同样会将这种final变量当成“宏变量”
        final String c1 = "java";
        String test = c1 + a;
        String test2 = c1+a1;
        
   
        final String c2 = "java" + 9;
        //因为c3调用了方法,所以不会再编译时就确定下来
        final String c3 = "java" + String.valueOf(9);
       
        System.out.println(c1 == "java");
        
        System.out.println(test == "java9");
        System.out.println(test2 == "java9");
        

        System.out.println(c2 == "java9");
        System.out.println(c3 == "java9");
    }
}

final方法

public class FinalMethodTest {
    public final  void test(){
    }
}

class sub extends  FinalMethodTest{
   //将引发编译错误,因为不能重写final方法
    public void test(){};
}

虽然不能重写fianl方法,但是当final方法用private修饰时,子类可以创建和父类同名的方法,以达到"重写"的效果

private class FinalMethodTest {
    public final  void test(){
    }
}

class sub extends  FinalMethodTest{
   //将引发编译错误,因为不能重写final方法
    public void test(){};
}

实例访问类成员时,实际上依然是委托给该类来访问类成员,因此即使某个实例为null,它也可以访问它所属的类的类成员,

final类

java.lang.Math就是一个final类,可以用final修饰后变得不可继承

不可变类

创建一个不可变类

public class Address {
    private final  String detail;
    private final String postCode;
    //在构造器里初始化两个实例变量
    public Address(){
        this.detail = "";
        this.postCode = "";
    }
    public Address(String detail , String postCode){
        this.detail =detail;
        this.postCode = postCode;
    }

    public String getDetail() {
        return detail;
    }

    public String getPostCode() {
        return postCode;
    }

    //重写equals()方法,判断链各个对象是否相等
    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        
        if (obj != null && obj.getClass() == Address.class){
            Address ad = (Address)obj;
            //当detail和postCode相等时,可认为两个Address对象相等
            if (this.getDetail().equals(ad.getDetail())
             && this.getPostCode().equals(ad.getPostCode())){
                return true;
            }
        }
        return false;
    }
    public int hashCode(){
        return detail.hashCode() + postCode.hashCode()*31;
    }
}

5、抽象类

public abstract class SpeedMeter {
    //转速
    private  double turnRate;
    public SpeedMeter(){}
    //把返回这轮半径的方法定义成抽象方法
    public abstract double getRadius();
    public void setTurnRate(double turnRate){
        this.turnRate = turnRate;
    }
    //定义计算速度的通用算法
    public double getSpeed(){
        return Math.PI*2*getRadius()*turnRate;
    }       
}
public class CarSpeedMeter extends  SpeedMeter {
    public double getRadius(){
        return 0.28;
    }

    public static void main(String[] args) {
        CarSpeedMeter csm = new CarSpeedMeter();
        csm.setTurnRate(15);
        System.out.println(csm.getSpeed());
    }
}

6、接口

接口和抽象类的区别

接口类似于整个系统的总纲,指定了系统各个模块应该遵循的标准

抽象类作为多个子类的共同父类,它所体现的是一种模板式设计

  • 接口只能包含抽象方法和默认方法,不能为普通方法提供方法实现;抽象类则完全可以包含普通方法
  • 接口里不能定义静态方法;抽象类可以定义静态方法
  • 接口里不包含构造器抽象类里可以包含构造器,抽象类的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作
  • 接口里不能包含初始化块;但抽象类则完全可以包含初始化块
  • 一个类最多只能有一个父类,包括抽象类;但一个类可以直接实现过个接口,通过实现多个接口可以弥补Java单继承的不出

接口的继承

interface interfaceA
{
    int PROP_A = 5;
    void testA();
}
 interface interfaceB{
    int PROP_B = 6;
    void testB();
 }
 interface interfaceC extends interfaceA ,interfaceB{
    int PROP_C = 7;
    void test();
 }

public class InterfaceExtendsTest {
    public static void main(String[] args) {
        System.out.println(interfaceC.PROP_A);
        System.out.println(interfaceC.PROP_B);
        System.out.println(interfaceC.PROP_C);
    }
}

7、内部类

非静态内部类

public class Cow {

    private double weight;
    //外部类的两个重载的构造器
    public Cow(){}
    public Cow(double weight ){
        this.weight = weight;
    }
    //定义一个非静态内部类
    private class CowLeg{
        //非静态内部类的两个实例变量
        private double length;
        private String color;
        //非静态内部类的两个重载构造器
        public CowLeg(){}
        public CowLeg(double length , String color){
            this.color = color;
            this.length = length;
        }

        public double getLength() {
            return length;
        }

        public void setLength(double length) {
            this.length = length;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }
        //非静态内部类的实例方法
        public void info(){
            System.out.println("当前牛腿的颜色是:" +
                    color + ",高"+ length);
            //直接访问外部类的private修饰的成员变量
            System.out.println("本牛腿所在奶牛重"+ weight);
        }
    }
    public void test(){
        CowLeg c1 = new CowLeg(1.12, "黑白相间");
        c1.info();
    }

    public static void main(String[] args) {
        Cow cow = new Cow(322.1);
        cow.test();
    }
}

如果外部类成员变量与内部类成员变量同名,可以用this、外部类类名.this作为鉴定来区分

内部类与外部类的关系

public class Outer {
    private int outProp =  9 ;
    class  Inner{
        private int inProP = 5;
        public void acessOutProp(){
            //非静态内部类可以访问外部类的成员变量
            System.out.println(outProp);
        }
    }
    //外部类不能访问内部类的成员变量
    public void test(){
        //System.out.println(inProp);
        //如果要访问内部类的实例比那辆,必须显示创建内部对象
        System.out.println("内部类的inProp值"+ new Inner().inProP);
    }

    public static void main(String[] args) {
        //这样只是创建了外部类对象,没有创建内部类对象
        Outer out = new Outer();
        out.test();
    }
}

注意事项:

  1. 不允许在外部类的静态成员中直接使用费静态内部类
  2. 不能在非静态内部类定义静态成员

静态内部类

public class StaticInnerClassTest {
    private int prop1 = 5;
    private static int prop2 = 9;
    static class StaticInnerClass{
        //静态内部类可以包含静态成员
        private static int age;
        public void accessOutProp(){
            //下面代码出现错误
            //静态内部类无法访问外部类的实例变量
            //System.out.println(prop1);
            //下面代码正常
            System.out.println(prop2);
        }
    }
}

静态内类的调用

public class AccessStaticInnerClass {
    static class StaticInnerClass{
        private static  int prop1 = 5;
        private  int prop2= 9;
    }

    public void accessInnerProp(){

        System.out.println(StaticInnerClass.prop1);
        System.out.println(new StaticInnerClass().prop2);
    }

    public static void main(String[] args) {
        AccessStaticInnerClass a = new AccessStaticInnerClass();
        a.accessInnerProp();
    }
}

使用内部类

out为外部类,in为内部列

out.in i = new out().new in();

匿名内部类

abstract class Device{
    private String name;
    public abstract double getPrice();
    public Device(){}
    public Device(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}


public class AnonymousInner {
    public void test(Device d){
        System.out.println(d.getName() +"-------"+ d.getPrice());
    }

    public static void main(String[] args) {
        AnonymousInner a = new AnonymousInner();
        //调用有参数的构造器创建Device匿名实现类的对象
        a.test(new Device("电子示波器")
        {
            public double getPrice() {
                return 78.2;
            }
        });
        //调用无参数的构造器创建Device匿名实现类对象
        Device d = new Device() {
            //初始化块
            {
                System.out.println("匿名类的初始化块");
            }
            public double getPrice() {
                return 76.4;
            }
            //重写父类的实例方法
            public String getName(){
                return "键盘";
            }
        };
        a.test(d);
    }
}

9、枚举类

enum SeasonEnum{
    //在第一行列出4个枚举实例
    SPRING,SUMMER,FALL,WINTER;
}

public class EnumTest{
    public void judge(SeasonEnum s){
        //switch 语句里的表达式可以使枚举值
        switch (s){
            case SPRING:
                System.out.println("春暖花开");
                break;

            case SUMMER:
                System.out.println("夏天");
                break;
            case FALL:
                System.out.println("秋天");
                break;
            case WINTER:
                System.out.println("冬天");
                break;

        }
    }

    public static void main(String[] args) {
        //枚举类默认有一个values()方法,返回枚举类的所有实例
        for (SeasonEnum s : SeasonEnum.values()){
            System.out.println(s);
        }
        //使用枚举实例时,可通过EnumClass.variable形式类访问
        new EnumTest().judge(SeasonEnum.SPRING);
    }
}

使用枚举类创建构造器

enum Gender{
    //此处的枚举值必须调用对应的构造器来创建
    MALE("男"),FEMALE("女");
    private final String name;

    private     Gender(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class GenderTest {
    public static void main(String[] args) {
        Gender g1 = Gender.valueOf("MALE");

        System.out.println(g1 + "代表:" + g1.getName());

        Gender g2 =  Gender.valueOf("FEMALE");
        System.out.println(g2 + "代表:" + g2.getName());

    }
}

实现枚举类的接口

interface GenderDesc{
    void info();
}


enum Gender implements  GenderDesc{
    //此处的枚举值必须调用对应的构造器来创建
    MALE("男"),FEMALE("女");
    private final String name;

    private     Gender(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void info() {
        System.out.println("这是用于定义性别的接口");
    }
}

public class GenderTest {
    public static void main(String[] args) {
        Gender g1 = Gender.valueOf("MALE");

        System.out.println(g1 + "代表:" + g1.getName());

        Gender g2 =  Gender.valueOf("FEMALE");
        System.out.println(g2 + "代表:" + g2.getName());

    }
}

枚举类与抽象方法

public enum  Operation {
    PLUS{
        public double eval(double x ,double y){
            return x + y;
        }
    },
    MINUS{
        public double eval(double x ,double y) {
            return x - y;
        }
    },
    TIMES {
        public double eval(double x, double y) {
            return x * y;
        }
    },
    DIVIDE{
        public double eval(double x ,double y) {
            return x / y;
        }
    };
  //为枚举类定义一个抽象方法
  //这个抽象方法由不同的枚举类提供不同的实现
    abstract   double eval(double x , double y);
  public static void main(String[] args) {
      System.out.println(Operation.PLUS.eval(3,4));
      System.out.println(Operation.MINUS.eval(5,4));
      System.out.println(Operation.TIMES.eval(3,4));
      System.out.println(Operation.DIVIDE.eval(3,4));

  }
}
posted @ 2020-10-09 23:08  白杨木  阅读(164)  评论(0)    收藏  举报