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