java基础
java的基本程序设计结构
第一个程序
Main.java
public class Main {
public static void main(String[] args) {
System.out.println("hello,world");
}
}
java的源代码的文件名必须和公共类的名字相同,必须以.java
结尾。
- 编译:
javac Main.java
得到二进制文件Main.class
- 执行:
java Main
打印hello world
或者直接java Main.java
执行。
数据类型
基本和C++相同,不同的之处: java中的布尔类型boolean
是不支持数值转换的,即x
为数值,if(x)
这样的代码是不能通过编译的。
变量和常量
变量
java中并不区分变量的声明和定义,且变量声明后必须显式赋值,使用未赋值的语句是错误的,如:
double x;
System.out.println(x);
java 10开始,可根据变量初始化值推断它的类型,只需借助关键字var
: var x = 1.2;
常量
final
关键字指示常量,表示变量只能被赋值一次,之后不能被更改,常量习惯上大写。
public static final double PI = 3.14;
枚举类型
enum Color{RED,BLUE,GREEN};
Color cr = Color.BLUE;
运算符
数学函数
Math
类包含很多数学函数,使用方法Math.funcion()
,其中常用的函数有:
sqrt()
: 开方pow()
:幂运算- 三角函数:
sin, cos, tan, atan...
- 指数函数:
exp, log
,log10
非常接近$\pi$和$e$的常量,分别为Math.PI
和Math.E
。
位运算
算术移位:用符号位填充高位,<<,>>
逻辑移位:用0填充高位,<<<, >>>
字符串
基础
- 子串:
str.substring(i,j)
,str
索引[i, j
)的字符组成的子串 - 拼接:
+
适用于短小且频率不高的字符串拼接,因为效率低,String.join(str1,str2,str3)
效率很高,或者转为StringBuilder
,用对应的append
方法
String s1 = "abcedfg";
String substr = s1.substring(1,3); //bc
String s2 = "a".repeat(3); // aaa java11 支持repeat
String s3 = "a" + "b" + "c"; // aaa
String s4 = String.join("aa","bc","cd"); // aaa
java中字符串的一个重要特点:不可变性,即不能修改字符串中的某个字符,如果非要修改呢?只能让其指向一个新的字符串。不可变性使得字符串间可以共享。JAVA(1)【基础类型】String类型的字符串池 - 小拙 - 博客园 (cnblogs.com)
-
判断是否相等:
s1.equals(s2)
, java中字符串如果用==
判断,实际比较的是地址 -
空串与
null
串: 长度为0的串为空串,null串表示没有任何对象和自己关联,判断一个字符串既不是空串也不是null串:if(s != null && s.length() != 0)
常用api
除了上面的,其他常用的api:
char charAt(int index):
返回给定位置的代码单元empty()
:是否为空startsWith(String prefix)
:是否以prefix作为前缀endsWith(String suffix)
:是否以suffix作为后缀length()
:长度toLowerCase()
/toUpperCase:转小/大写
StringBuilder类
拼接字符串append
的效率高,对应的一些api:
length()
:长度append()
:可添加单个字符或者字符串- setCharAt(int i, char c):将第i个代码单元设置为字符c
insert(int offset, String str/ char c):
在索引offset后插入字符串str或者单个字符cdelete(index1, index2)
:删除索引[index1,index2)之间的字符串,并返回残余的字符串toString():
返回String类型的对象
输入输出
读取输入
Scanner in = new Scanner(System.in);
String s1 = in.nextLine();
String s2 = in.next(); //以空格为分界
int num = in.nextInt(); //in.nextDouble
检查是否还有输入:boolean hasNext()
/ hasNextInt()
/hasNextDouble()
格式化输出
double a = 1 / 3.0;
System.out.printf("%8.2f",a); //总字符长度为8,精确至小数点后2位,即前面留了5个空格
文件输入
String path = "D:/Files/桌面文件/1.txt";
Scanner in = new Scanner(Path.of(path), StandardCharsets.UTF_8);
String s = in.nextLine();
System.out.println(s);
循环
和C++的break
功能更强的是,java中break
语句可以带标签,如多重循环中,break
加上标签可直接跳转到最外层。标签放在循环最外层的前面,并加上冒号。
public static void main(String[] args) {
label:
for(int i=0;i<5;i++) {
for(int j=0;j<5;j++) {
if(j==3) {
break label;
}
System.out.print("i= "+i +" j= " +j + "\n");
}
}
System.out.println("This is end");
}
//输出
i= 0 j= 0
i= 0 j= 1
i= 0 j= 2
This is end
大数
BigDecimal a = BigDecimal.valueOf(100);
BigInteger b = new BigInteger("12466456663875366527162366515632664357");
BigInteger c = new BigInteger("12466456663875366527162366515632664357");
System.out.println(b.add(c));
System.out.println(b.subtract(c)); //减法
System.out.println(b.multiply(c));
System.out.println(b.divide(c));
System.out.println(b.mod(c));
BigDecimal 中除法除不尽会报错,所以除不尽的情况要指定舍去方式:
public class Main {
public static void main(String[] args) {
BigDecimal a = BigDecimal.valueOf(1);
BigDecimal b = BigDecimal.valueOf(3);
System.out.println(a.divide(b, 2, RoundingMode.HALF_UP)); //保留两位小数,并四舍五入,0.33
System.out.println(a.divide(b, 2, RoundingMode.CEILING)); //天花板除法 0.34
System.out.println(a.divide(b, 2, RoundingMode.FLOOR)); //地板除 0.33
}
}
数组
声明数组
public class Main {
public static void main(String[] args) {
int[] a = new int[10];
int [] b = new int[]{1,2,3};
int [] c = {1,4,6};
}
}
数组拷贝
java的数组声明:int[] a = new int[100]
等价于C++里面的int* a = new int[100]
,因此=
赋值实际上只是引用同一个数组,如果想拷贝一份,则应该用Arrays.copyOf()
public class Main {
public static void main(String[] args) {
int [] c = {1,4,6};
int [] d = c;
c[1] = 9;
System.out.println(c);
System.out.println(d);
for(int x:d){
System.out.print(x +"\t");
}
}
}
//
[I@5fd0d5ae
[I@5fd0d5ae
1 9 6
public class Main {
public static void main(String[] args) {
int [] a = {1,4,6};
int [] b = Arrays.copyOf(a,5); //从数组a的起始复制,第二个参数为新数组的总长度,不够补0
a[1] = 9;
System.out.println(a);
System.out.println(b);
for(int x:b){
System.out.print(x +"\t");
}
}
}
//
[I@5fd0d5ae
[I@2d98a335
1 4 6 0 0
用于数组的api
用法:Arrays.
加上下面的api:
-
sort(arr);
采用的是快速排序 -
static String toString(arr):[1, 7, 5, 3, 6, 2, 0]
-
copyOfRange(arr, from, to):
复制arr的区间[from, to)的数据 -
binarySearch(arr, value)
:在有序数组中寻找value,并返回对应的下标r
,如果找不到,则-r-1
为应该插入的位置 -
fill(arr,value)
:将数组全部用value
填充 -
equals(arr1,arr2)
:判断两个数组是否相等(长度,对应的元素都是相等的才返回true)
多维数组
java多维数组可以是不规则的,
public class Main {
public static void main(String[] args) {
int[][] a = {{1,2,3},{2,3}};
int[][] b = new int[2][3];
System.out.println(a[1][1]);
System.out.println(Arrays.deepToString(a)); //toString无法处理多维数组
}
}
对象和类
本章只记录和C++的差别,类似的不记录。
构造器
默认字段初始化
如果没有显式地为字段设置处置,那么会被赋为默认值,数值为0,布尔为false
, 对象引用为null
无参构造器
如果类没有构造器,则会提供一个无参构造器,但如果提供了有参构造器,而没有提供无参构造器,则构造对象时不提供参数是错误的。
类的导入
自定义类的导入
和使用完全限定名相比,简单的方式是采用import 导入
静态导入
import static java.lang.Math.sqrt;
public class Main {
public static void main(String[] args) {
int a = 9;
int b = (int) sqrt(a);
System.out.println(b);
}
}
包访问权限
public:
可以被任意类使用private:
只能由定义它们的类使用- 没有指定
private
或者public
: 可以被同包的所有方法使用 protected
: 对本包和所有子类可见
和C++相比,protected
的保护的安全性变差了
继承
类,父类,子类
定义子类
java中用关键字extends
表示继承,且java中只有公有继承,同样可以重写父类的方法,如下面的run
方法,但如果还是想调用父类的,子类的run
方法中用关键字super
实现:super.run();
public class Student extends Person {
@Override
public void run() {
System.out.println("a student is running!");
}
public void eat(){
System.out.println("eating...");
}
}
子类的构造器
相同的字段,可以借助父类的构造器,依旧是利用super
调用构造器,这一句必须是子类构造器中的第一句。
int score;
public Student(String name,int age,int score){
super(name,age);
this.score = score;
}
java中动态绑定是默认的,在运行时自动选择恰当的方法,若不想一个方法是虚拟的,则用final
修饰它。
阻止继承:final类和方法
如Person
类加上了final
关键字,则Student
无法继承它。
public final class Person
同样给Person
类中的方法run
加上final
修饰,在子类中同样不能重写覆盖
public final void run(){
System.out.println("running!");
}
强制类型转换
java中子类强制转为父类是合法的,但反过来一般会报错,因此转换前用instanceof
检查。
if(p instanceof Student)
抽象类
抽象类不能实例化,将一个类声明为abstract
,这个类就成为了抽象类。用abstract
修饰的方法不用实现,类似C++的虚基类。
public abstract class Person {
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public abstract void run();
}
Object:所有类的父类
Object类型的变量
Object
类是所有类的超类(父类),但定义的时候不需要加上extends
。可用Object类引用任意类型的对象,当然要进行具体操作,还需要墙砖为对应的类型。对象数组和基本的数组都拓展了Object
类
Object obj = new Student("Alice", 23,89); //ok
Student st = (Student)obj;
Animal a = new Aninal[5];
obj = a; //0k
obj = new int[10]; //ok
equals方法
用于检测两个对象是否相等。
- 若引用同一个对象,则想等
- 另一个对象为
null
或者不是同一个类型,不相等 - 接下来判断各种字段,由于自己的
name
字段可能也是null
,故name.equals(o.name)
是有问题的,而应该用Objects.equals
方法 - 比较。
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
访问权限
接口,lambda表达式与内部类
接口
使用
概念:不是类,而是对符合这个接口的类的一组规范(听了想打人
标签:Java,String,基础,System,println,new,public,out From: https://www.cnblogs.com/shmilyt/p/16931106.html