文章目录
- 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();}@Overridepublic 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{@Overridepublic 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倍扩容。
如果要限制数据的类型,则可以加上泛型,如果不加,则什么类型的数据都可以加入集合中。