Java 入门 (九)

权限修饰符

是java中的一些关键字,用来限定变量、方法、类等的适用范围。这些权限修饰符都是封装的一种表现。

public:公开的,权限是最大的
    可以被访问的范围:
        1.本类
        2.同包下的其它类
        3.不同包下的其他类(需要导包)
protected:受保护的
    可以被访问的范围:
        1.本类
        2.同包下的其他类
        3.不同包下的子类
默认的(啥也不写):默认的
    可以被访问的范围:
        1.本类
        2.同包下的其它类
private:私有的
    可以被访问的范围:
        1.本类

多态

多态就是一个事物多种的形态

在Java中就是对一个命令(方法)有不同的反应(方法的重写)

前提

  1. 有子父类的关系(继承)
  2. 有方法的重写
  3. 父类的引用指向子类的对象

注意:数据类型 对象名 = new 数据类型();

​ 对象名实际上就是引用,真正的对象是new 数据类型();

package top.zunmx.u1;
// ALC-Master
class Fu{

}
class Zi extends Fu{

}
public class Demo1 {
    public static void main(String[] args) {
        Fu f = new Zi(); ///!!!
    }
}

多态中成员访问的关系

Fu f = new Zi();

等号左边为父类的引用f,等号的右边为子类的对象 new Zi();

成员变量

编译看左边(左边有就编译通过,没有就报错),运行看左边(执行父类的成员变量内容)

成员方法

编译看左边(左边有就编译通过,没有就报错),运行看右边(执行子类中重写的内容)

优先访问子类中的方法,但是父类中必须也要有这个方法

如果子类中没有这个方法,就执行父类中的这个方法。

如果父类中有这个方法,而子类中没有,那么就执行父类中的这个方法。

静态方法(附加)

都看左

多态的好处

  1. 增强了代码的可维护性(由继承保证)
  2. 增加了代码的可扩展性(由多态保证)
package top.zunmx.u1;

// ALC-Master
class Animal {
    String name;
    int age;

    public void eat() {

    }

    public void sleep() {

    }
}

class Cat extends Animal {
    public Cat() {

    }

    public void eat() {
        System.out.println("猫吃饭");
    }

    public void sleep() {
        System.out.println("猫睡觉");
    }

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

class Dog extends Animal {
    public Dog() {

    }

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

    public void eat() {
        System.out.println("狗吃饭");
    }

    public void sleep() {
        System.out.println("狗睡觉");
    }
}

class Tiger extends Animal {
    public Tiger() {

    }

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

    public void eat() {
        System.out.println("老虎吃饭");
    }

    public void sleep() {
        System.out.println("老虎睡觉");
    }
}

class Snake extends Animal {
    public Snake() {

    }

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

    public void eat() {
        System.out.println("蛇吃饭");
    }

    public void sleep() {
        System.out.println("蛇睡觉");
    }
}

public class Demo3 {
    public static void main(String[] args) {
        Cat c = new Cat("小黑", 3);
        life(c);
        Cat c1 = new Cat("小黑黑", 3);
//      c1.eat();
//      c1.sleep();
        life(c1);
        Cat c2 = new Cat("小黑黑黑", 3);
        c2.eat();
        c2.sleep();
        System.out.println("----------");

        Dog d = new Dog("小花", 3);
        life(d);
        Dog d1 = new Dog("小花花", 3);
//      c1.eat();
//      c1.sleep();
        life(d1);
        Dog d2 = new Dog("小花花花", 3);
        d2.eat();
        d2.sleep();
        System.out.println("----------");

        Tiger t = new Tiger("小黄", 3);
        life(t);
        Tiger t1 = new Tiger("小黄黄", 3);
//      c1.eat();
//      c1.sleep();
        life(t1);
        Tiger t2 = new Tiger("小黄黄黄", 3);
        t2.eat();
        t2.sleep();
        System.out.println("----------");

        Animal s = new Snake("小青", 400);
        life(s);
        Snake s1 = new Snake("小青青", 400);
        life(s1);
    }


    public static void life(Animal a) {
        a.eat();
        a.sleep();
        System.out.println("######");
    }

    public static void life(Cat c) {
        c.eat();
        c.sleep();
    }

    public static void life(Dog d) {
        d.eat();
        d.sleep();
    }

    public static void life(Tiger t) {
        t.eat();
        t.sleep();
    }
}

多态的弊端

  1. 不能访问子类特有的功能(因为多态中编译要看左边父类中有没有,父类没有就直接编译报错了)
  2. 如何解决这个问题呢?

    1. 直接创建一个子类对象
    2. 将父类的引用强制转换为子类对象

向上/向下转型

向上转型:是从较小的类型到较大的类型 Fu f = new Zi();

向下转型:是从较大的类型到较小的类型 Zi z = (Zi)f;

为什么可以向下转型:因为父类的引用本来就是子类的对象,这个向下转型只不过是再将子类对象转变为原来的样子。

package top.zunmx.d2;

// ALC-Master
class 孔子爹 {
    public void teachPython() {
        System.out.println("讲Python");

    }
}

class 孔子 extends 孔子爹 {
    public void teachLunYu() {
        System.out.println("讲论语");
    }

    public void playLOL() {
        System.out.println("孔子玩弱鸡联盟");

    }
}

public class Demo {
    public static void main(String[] args) {
        // 向上转型 从小到大
        孔子爹 kzd = new 孔子();
        kzd.teachPython(); // 孔子乔装打扮伪装爹去讲Python
        // 摘下领带 变成自己的样子 从大到小
        孔子 kz = (孔子)kzd;
        kz.playLOL();
    }
}

抽象类

回想之前写的动物类,我说某一个物体是一个动物,那肯定是不行的。只有是具体的猫、狗才是一个具体的动物。那么我们之前所谓的动物类就是将符合某一类特征的物体给他们放在一块组成了一个类,这是要给抽象类。再回想猫和狗都会吃饭和睡觉,但是因为习惯的不同,吃的东西和睡觉的方式应该也是不同的,所以我们再去定义一个动物类的吃饭和睡觉这些共有方法的时候,就不应该在方法中协商具体的内容,而只需要声明这个吃和睡得方法就可以了,写这种只有方法的声明而没有方法体的方法称为抽象方法。

格式

/*
*关键字:abstract
*/
权限修饰符 abstract 类名 {

}
修饰符 abstract 返回值类型 方法名(参数列表);

特点

  1. 抽象类中可以放抽象方法
  2. 抽象方法一定要放在抽象类中
  3. 抽象类不能进行实例化(也就是抽象类不能创建对象)

抽象类中的成员

变量:成员变量、静态变量、常量

成员方法:成员方法、具体方法、抽象方法

构造方法:有构造方法,但是不能进行实例化。

为什么抽象类中有构造方法?

要进行初始化

抽象类如何进行初始化?

抽象类可以被继承,所以抽象类可以通过子类进行实例化(多态的一种体现)

接口

回想之前写的猫狗案例,我们写的都是废猫、废狗,因为他们只会吃饭、睡觉。现在已经有狗会开车了,猫会下棋了。这些功能一般的猫做不到,这是经过训练之后才得到的,所以这些功能不能统一的定义在一个抽象类中,应该把这些后天学习的功能,放到一个单独的容器中装起来,以后谁训练了,就让谁使用这个容器。这个容器就是所谓的接口。

接口:定义一组规范,扩展一些功能。

格式:

权限修饰符 interface 接口名 {}

注意:接口也会生成了一个字节码文件

特点:

​ 接口中没有构造方法

接口如何进行实例化

关键字:implements

class 实现类 implements 接口{

}

我们可以通过接口的实现类进行简介的实例化(多态的一种体现)

接口中的成员

变量:只能是常量,并且默认被public static final 修饰

方法:只能是抽象方法(这句话再jdk8之前是正确的,但是之后有瑕疵了,在jdk8之后可以有被static、default修饰的方法)

构造方法:没有构造方法。

​ 因为接口中只有常量和抽象方法,常量默认是被public static final 修饰,可以通过接口名.常量名进行访问。抽象方法必须要被重写,所以接口不需要进行初始化,所以也就没有构造方法了。

实现多态的三种方式

  1. 普通类 [不常用]
  2. 抽象类 [不太常用]
  3. 接口 [常用]

对比

类与类:

可以进行单继承、多层继承

类与接口:

单实现操作

多实现

​ class AImpl implements A, B

​ 因为接口中的方法默认都是抽象的,如果多实现的这些接口中有相同的方法名,这些方法都会被重写的。到最后执行的也是重写之后的方法。

接口与接口:

接口可以单继承

接口可以多继承

注意:

​ 一个类可以单继承一个类,同时再多实现接口

匿名内部类

没有名字的类

前提

  1. 可以被一个类继承的类
  2. 可以被一个类实现的接口

格式

new 类名或者接口名(){
    方法的实现或者重写;
}
// 注意:匿名内部类的本质就是一个对象

实例

package top.zunmx.u1;

// ALC-Master
interface A {
    public abstract void show();

}

class C {
    public void test(A a) {
        a.show(); // ?
    }
}

// function one
class Aimpl implements A {
    public void show() {
        System.out.println("function1");
    }
}

public class Demo2 {
    public static void main(String[] args) {
        C c = new C();
        A aim = new Aimpl();
        c.test(aim);

        // function two
        C c1 = new C();
        A a = new A() {

            @Override
            public void show() {
                System.out.println("function2");

            }

        };
        c1.test(a);

        // function three
        C c2 = new C();
        c.test(new A() {
            @Override
            public void show() {
                System.out.println("function3");

            }
        });

    }
}

API

API: Application Programming Interface

此API是Java官方提供了很多功能强大的类,这些类中有很多可以目前再开发中遇到问题的解决方法,我们无需知道方法的源码以及他们实现细节,只需要通过调用来使用即可。API会随着JDK以jar包下发给开发者。

JAR 包:就是装了很多类的字节码文件(.class),但是只有这些jar包是不行的,这个时候还需要搭配官方给这些类的解释说明书才可以使用。

如何生成jar

File-Export-JAR file- 选择要生成jar包的Java文件-选择生成目录-

如何导入JAR

Eclipse : 复制到工作目录-右键-Build Path - Add to Build Path

Object类

java.lang 包下的,所以不用进行导入包就能使用

累Object 是类层次结构的跟类。每个类都是用Object作为超类

构造方法

public Object(); //只有一个无参构造方法

所有的类都会直接或者间接的继承Object类,又因为Object只有一个无参构造方法,所有所有的类都默认访问的父类的无参构造方法。

instanceof

格式: 对象 instanceof 类型

作用:判断一个对象是否属于一个类型,如果属于那么就返回true,否则false

常见方法

  • toString
  public String toString() ; //返回字符串默认形式
  /*实际上是getclass().getName()+'@'+Integer.toHexString(hashCode()); 拼接而得,但是这个数据对我们没有意义。重写
  */

  @Override
  public String toString() {
      return "重写toString";
  }
  ```
- equals

```java
  public boolean equals(Object obj)
  ```

  Object 中的equals方法是用来比较对象是否相同,这个目前对我们来说也没有太大的意义,我们相比较的是属性是否相同,如果属性是完全一致的话,我们就认为是相同的对象。但是目前原来的是解决不了的,所以我们需要重写。

```java
  package top.zunmx.u3;

  // ALC-Master
  class Car extends Object {
    String name;
    int price;

    public Car(String name, int price) {
        super();
        this.name = name;
        this.price = price;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + price;
        return result;
    }

  // 第一版
  //    public boolean equals(Object obj) {
  //        Car cc = (Car) obj;
  //        obj=cc;
  //        return ((this.name.equals(cc.name) && (this.price == (cc.price))));
  //
  //    }
  // 第二版
  //    public boolean equals(Object obj) {
  //        if(this == obj) {
  //            return true;
  //        }
  //        if (!(obj instanceof Car)) {
  //            return false;
  //        }
  //        Car cc = (Car) obj;
  //        obj=cc;
  //        return ((this.name.equals(cc.name) && (this.price == (cc.price))));
  //
  //    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Car other = (Car) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (price != other.price)
            return false;
        return true;
    } // 自动生成

  }

  class D {

  }

  public class Demo1 {
    public static void main(String[] args) {
        Car c = new Car("五菱宏光", 3000);
        Car c2 = new Car("东风神车", 100000);
        Car c3 = c;
        Car c4 = new Car("东风神车", 100000);
        boolean b1 = c.equals(c2); // equals 是object方法,多态的体现
        boolean b2 = c.equals(c3);
        boolean b3 = c2.equals(c4);
        System.out.println(b1 + " " + b2 + " " + b3);

        D d = new D();
        boolean b4 = c.equals(d); // java.lang.ClassCastException: 其中你把D强转成了汽车类,equals
        System.out.println(b4);
    }
  }
  ```

## ‘==’ 和 equals 区别

> == 比较基本数据类型和引用数据类型
> 
> ​     基本数据类型比较的是值
> 
> ​     引用数据类型比较多是地址值
> 
> equals:只能比较引用数据类型
> 
> ​     1.重写之前比较的是地址的值
> 
> ​     2.重写之后比较的是类的属性值是否相同

# String类

> java.lang 下的,所以不需要导入包
> 
> String 类代表字符串。字符串是常量,所以他们的值在创建之后不能更改

```java
String();
String(byte[] bytes);
String(byte[] bytes, it offset, int length);
String(char[] value);
String(char[] value, it offset, int length);
String(String original);

注意:

  1. 如果是两个常量直接进行相加,那么会先进行相加得到结果之后在和常量池中的内容比较。

如果有,那么就使用常量池的内容

如果没有,那么就再开辟一个空间存储结果
2. 如果两个变量进行相加,那么会先开辟空间,然后再进行相加(实际上两个变量进行相加的时候会转为StringBuilder)

常见功能

  1. 判断功能

java boolean equals(Object anObject); boolean equalsIgnoreCase(String anotherString); boolean startWith(String prefix); boolean endwith(String suffix); boolean contains(CharSequence s); boolean isEmpty();
2. 获取功能

```java
char charAt(int index);
int length();
String substring(int beginIndex);
String substring(int beginIndex, int endIndex);

int indexOf(int ch);
int indexOf(int ch,int fromIndex);
int indexOf(String str);
int indexOf(String str,int fromIndex);

int lastIndexOf(int ch);
```

评论 0

还没有评论,来说点什么吧。

提交后需要审核才会公开。