文章目录
- 1. 方法
- 2. OOP
- 2.1 static
- 2.2 单例模式
- 2.3 继承
- 2.4 多态
 
- 3. 常用API
- 3.1 包
- 3.2 String
- 3.3 ArrayList
 
1. 方法
方法定义时要使用public static修饰,这是和C++最不同的地方,因为java都是基于类执行的。
Java的参数传递机制是值传递,即传递的是一个副本;而如果参数是数组,则是引用传递,可以理解为传递的是数组的指针,这是唯一不同的地方。
package basic;
import java.util.Scanner;
public class Method {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt(), b = sc.nextInt();
        System.out.println(sum(a, b));
    }
    public static int sum(int a, int b) {
        return a + b;
    }
}
2. OOP
Java受欢迎的一个主要原因就是有垃圾回收机制,比如当你把一个对象置为null的时候,就自动回收了。
java的OOP和C++不同的是,java默认权限都是default,即只能在本package中访问,而且我们需要对每一个参数或者函数写上访问权限;C++的话就是在前面写一个public或者private,这一点来说,java要麻烦一点。
2.1 static
java有实例代码块,即加{},里面的代码可以在构造前执行,同时还可以加static,这样就只执行一次。
2.2 单例模式
懒汉式
public class SingletonB {
    private static SingletonB b;
    private SingletonB() {}
    // 加同步锁线程安全,但是效率低
//    public static synchronized SingletonB getInstance() {
    public static SingletonB getInstance() {
        if(b == null) {
            synchronized (SingletonB.class) {
                if(b == null)
                    b = new SingletonB();
            }
        }
        return b;
    }
}
饿汉式
public class SingletonA {
    private static final SingletonA a = new SingletonA();
    private SingletonA() {}
    public static SingletonA getInstance() {
        return a;
    }
}
2.3 继承
java的继承用的是extends关键字,可以让一个类和另一个类建立起父子关系。子类可以继承父类的非私有成员(成员变量、成员方法)。
权限修饰符
 public和private是最常用的,protected和缺省也有,不过很少。
| 修饰符 | 在本类中 | 同一个包下的其他类里 | 任意包下的子类里 | 任意包下的任意类里 | 
|---|---|---|---|---|
| private | √ | |||
| 缺省 | √ | √ | ||
| protected | √ | √ | √ | |
| public | √ | √ | √ | √ | 
单继承
 和C++不同的是,Java只支持单继承,这也就不能存在菱形继承的问题了;不过也是支持多层继承的。(据我的了解,似乎只有C++支持多继承)
Object类
- Object类是java所有类的祖宗类(默认)。这一点就像是python的类一样,全部都继承自Object。
方法重写
- 使用@Override注解,他可以指定编译器,检查我们重写的方法格式是否正确,代码可读性也更好。
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小
- 私有方法、静态方法不能被重写
- 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限
public class Son extends Father{
    public void print2() {
        System.out.println("I'm Son");
        print1();
    }
    @Override
    public void print3(int a, int b) {
        super.print3(3, 4);
        System.out.println("I'm Son " + a + " " + b);
    }
}
声明不变,重新实现
2.4 多态
在进行强转时,java建议使用instanceof关键字,判断当前对象的真实类型,再进行强转。
final
- 修饰类:该类被称为最终类,特点是不能被继承了
- 修饰方法:该方法被称为最终方法,特点是不能被重写了
- 修饰变量:该变量只能被赋值一次(java没有const常量,用final来代替)
常量
- 使用了static final修饰的成员变量就被成为常量
- 作用:通常用于记录系统的配置信息。
- 命名规范:使用大写字母,多个单词之间使用下划线连接起来。
抽象类
 Java中的抽象类用abstract关键字修饰,相当于C++的 = 0。被抽象的类不能有实例,必须被子类重写所有抽象方法。
public abstract class People {
    public People() {
        System.out.println("人被构造出来了");
    }
    public void run() {}
    public abstract void eat();
}
public class Student extends People{
    @Override
    public void run() {
        System.out.println("学生跑得快");
    }
    public void eat() {
        System.out.println("学生在吃东西");
    }
}
public class Main {
    public static void main(String[] args) {
        People p1 = new Teacher();
        People p2 = new Student();
        p1.run();
        p2.run();
        // 强制转换
        if(p1 instanceof Student) {
            Student s = (Student) p1;
        } else {
            Teacher s = (Teacher) p1;
        }
        p1.eat();
        p2.eat();
    }
}
接口
 Java接口的关键字是interface,Java接口是一种特殊的抽象类型,主要用于定义对象之间的交互方式。它定义了一组方法的规范,这些方法没有具体的实现。
 
 在这里可以选择Interface。在接口类中,不需要加public abstract、public static这些。
public interface 接口名 {
	// 成员变量(常量)
	// 成员方法(抽象方法)
}
对应的还有实现类,他的关键字是implements,所以综上可以把接口类认为是父类,实现类认为是子类。一个类可以实现多个接口,实现类实现多个接口,必须重写完接口的全部抽象方法。
修饰符 class 实现类 implements 接口1, 接口2, 接口3, ... {
}
接口的优点
- 弥补了单继承的不足,一个类可以同时实现多个接口
- 让程序可以面向接口编程,程序员可以灵活方便的切换各种业务实现
JDK8新特性
 在接口类中,允许实现方法,默认是public,主要是方便项目中后续开发增加新功能时,可以直接在接口类实现,不必对所有的实现类重写增加新功能,更便于项目的扩展和维护。(感觉加了这个功能后,就和C++的virtual很像了,自己本身也可以有自己的实现,然后也能让子类进行重写)
三者都默认被public修饰。
public interface A {
    /**
    * 1. 默认方法:必须使用default修饰,默认会被public修饰
    * 实例方法:对象的方法,必须使用实现类的对象来访问
    */
    default void test1() { // 默认用public修饰,所以不用写
        System.out.println("默认方法");
        test2();
    }
    /**
     * 2. 私有方法:必须使用private修饰(JDK9开始支持),只能在接口内部被调用
     * 实例方法:对象的方法
     */
    private void test2() {
        System.out.println("私有方法");
    }
    /**
     * 3. 静态方法:必须使用static修饰,必须用当前接口名调用
     */
    static void test3() {   // 默认用public修饰,所以不用写
        System.out.println("静态方法");
    }
} 
3. 常用API
3.1 包
- 如果当前程序中,要调用自己所在包下的其他程序,可以直接调用。(同一个包下的类,互相可以直接调用)
- 如果当前程序中,要调用其他包下的程序,则必须在当前程序中导包,才可以访问!import 包名.类名
- 如果当前程序中,要调用Java提供的程序,也需要先导包才能使用;但是Java.lang包下的程序不需要导入,可以直接使用
- 如果当前程序中,要调用多个不同包下的程序,而这些程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问。
Java万物皆对象,就是这个道理。
3.2 String
String的几种创建方式,官方推荐的是第一种方法。
 
一些常用的API:
 
public static void main(String[] args) {
        String s = "jehanrio";
        // 1. 获取字符串长度
        System.out.println("s的长度:" + s.length());
        // 2. 提取某个索引的字符
        char c = s.charAt(2);
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            System.out.print(ch);
        }
        System.out.println();
        System.out.println("_____________________________");
        // 3. 字符串转换为字符数组,再进行遍历
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            System.out.print(chars[i]);
        }
        System.out.println();
        // 4. 判断字符串内容是否一样
        String s1 = "JehanRio";
        String s2 = "jehanrio";
        System.out.println("s1和s2是否一样:" + s1.equals(s2));
        // 5. 忽略大小写比较字符串内容
        System.out.println("忽略大小写比较内容是否一样:" + s1.equalsIgnoreCase(s2));
        // 6. 截取字符串内容,这点和C++不一样,第二个参数是结尾的下标(不包含),而不是长度
        System.out.println(s1.substring(1, 5));
        // 7. 内容替换,并返回新的字符串对象
        String info = "你是个垃圾";
        String s3 = info.replace("垃圾", "***");
        System.out.println(s3);
        // 8. 判断是否包含关键字(C++的find)
        System.out.println(info.contains("垃圾"));
        // 9. 判断字符串是否以**开头
        System.out.println(s2.startsWith("jehan"));
        // 10. 把字符串按照某个指定内容,分割成多个字符串,放到一个字符串数组中(python的.join)
        String s5 = "张三,李四,王五";
        String[] rs = s5.split(",");
        for (String r : rs) {
            System.out.print(r+" ");
        }
    }
一些注意事项
- String的内容是不可变的,只要是以"..."写出的字符串对象,会在堆内存中的字符串常量池中存储。(每次试图修改字符串对象,都是指向了新的字符串对象)
- 只要是以“...”方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份(和python一样);但是通过new方式创建字符串对象,每new一次都会产生一个新的对象存在堆内存中。这也是为什么官方推荐我们用"...",为了节约内存。
  
  
String s1 = new String("abs");创建了2个对象
String s2 = "abc";// 创建了0个对象
s1和s2的地址不同。
3.3 ArrayList
ArrayList是Java中的集合容器,对应着类似C++的vector,底层是一种动态数组,扩容也是2倍扩容。
 
 如果要限制数据的类型,则可以加上泛型,如果不加,则什么类型的数据都可以加入集合中。




















