Java拾遗初步
1、public和private、protected不能组合;return语句后面不能再写代码,因为执行不到,所以编译报错
public class Test{
public static void main(String[] args) {
System.out.println(Hello());
}
//错误: 非法的修饰符组合: public和private
/*public private void Hello(){
//错误: 找不到符号
System.out.println(hello);
}*/
//错误: 非法的修饰符组合: public和protected
/*public protected void Hello(){
System.out.println("hello");
}*/
public static String Hello(){
String s = "hello";
return s;
//错误: 无法访问的语句
//除非把上面的return语句移到这行代码后面
System.out.println("hello");
}
}
2、方法重载不看变量名的顺序,变量名可变,应看数据类型的顺序
public class Test{
public static int sum(int i,int j){
return i + j;
}
//方法重载不看变量名的顺序,而看数据类型的顺序
public static int sum(int j,int i){
return i + j;
}
}
3、拼接运算符'+'在遇到字符串前如果数据可以运算,那么作为加号运算符;但如果不能运算如一个数字+布尔类型,则编译出错
public class Test{
public static void main(String[] args) {
System.out.println(1 + 2 + "x" + 3);//3x3
//错误: 二元运算符 '+' 的操作数类型错误.布尔类型不能进行字符串拼接?可
//System.out.println(1 + true + "x" + 1 + 2);
System.out.println(true + "a");//truea
System.out.println(1 + "x" + 1 + 2 + false);//1x12false
System.out.println(1 + 'a' + "x" + 1 + 2);//98x12
}
}
4、左移测试,当左移的位数超过该数值类型的最大位数时,会用左移的位数去模类型的最大位数,然后按余数进行移位
public class Test{
public static void main(String[] args) {
//第一行代码的结果没问题,因为是32位一起移动的,不是8位移动,因此不存在溢出的问题
//60的二进制位为00111100,左移3位结果为480,二进制为111100000
System.out.println(60 <3);
//-2147483648=-2^31(最高位变成符号位)
System.out.println(0x40000000 <1);
//0 100000...000再左移,java会丢弃溢出位
System.out.println(0x40000000 <2);
//-2147483648
System.out.println(0x44000000 <5);
int i = 1,j = 0x80000000;
/*注意,这两个不是语句哦
i < j <//当左移的位数超过该数值类型的最大位数时,//会用左移的位数去模类型的最大位数,然后按余数进行移位
System.out.println(i <33);//2
System.out.println(j <33);//0 丢弃最高位
}
}
5、Java余数计算的一点小规律,异号取余数遵循尽量使商小的原则
public class Test{
public static void main(String[] args) {
//Java中同号取余数没有异议,但是异号取余数遵循尽量使商小的原则,
//即5 = -2*(-3)+ 1;-5 = 2 * 2 + (-1),故余数分别为1、-1
System.out.println(-7 % -2);//-1
System.out.println(5 % -2);//1
System.out.println(-5 % 2);//-1
}
}
6、Java中二、八、十六进制赋值,二进制以0b开头,八进制以0开头,十六进制以0x开头.数字字面量可以加下划线
public class Test{
public static void main(String[] args) {
int i = 0b1001;//java7之后,可以用0b或0B前缀表示二进制
int j = 0B100;
System.out.println(i);//9
System.out.println(j);//4
//还可以为数字字面量加下划线,这些下划线只是为了让人更易读,
//编辑器编译时会去除这些下划线
i = 1_000_000;
j = 0b1_000;
System.out.println(i);//1000000
System.out.println(j);//8
//java中没有任何无符号形式的int、long、byte、short类型
byte k = (byte)0b10000000;
System.out.println(k);//-128
//1e4是double类型,不用赋值给int类型哦
double h = 1e4;
System.out.println(h);//10000.0
}
}
7、写注释尽量不用转义序列\u,会在解析代码之前得到处理,可能会出现奇奇怪怪的错误。
public class Test{
public static void main(String[] args) {
System.out.println('\u03C0');//π
System.out.println('\u000a');//\n
/*
注释\u000a is a newline 也要注意这种错误,
\u000a是换行符,会把is a newline换到下一行,出现一系列问题
Look inside c:\users 注意这里有个错误: 非法的 Unicode 转义
因为\u后面要求有4位十进制数
*/
System.out.println('\u03C0');//π
//错误: 字符文字的行结尾不合法
//因为转义字符会在解析代码之前得到处理,所以下面这行代码变成:
//System.out.println(
//);
System.out.println('\u000a');
//但是下面这行代码可以,因为这个\n是运行时执行
System.out.println('\n');
}
}
8、转义字符的魔力,慎用
\u000a
public class Test {
public static void main(String[] args) {
/*输出:hello*/
// \u000a System.out.println("hello");
}
}
\u007d及\u007b
public class Test {
public static void main(String[] args) {
/*输出:假亦真!*/
if(false == true){// \u000a \u007d \u007b
System.out.println("假亦真!");
}
}
}
\u0022
public class Test {
public static void main(String[] args) {
//输出:1
//常见字符串长度混淆题,\u0022是双引号右半边
System.out.println("a\u0022.length() + \u0022".length());
}
}
9、开辟数组时如果没有初始化,会默认初始化
public class Test {
public static void main(String[] args) {
int[] arr=new int[5];
System.out.println(arr[0]);//0
}
}
10、静态导入:导入静态方法和静态域,这样可以不必加类名前缀
import static java.lang.System.*;//静态导入
public class test {
public static void main(String[] args) {
out.println("hello");
}
}
11、格式化输出,System.out.printf(…)
System.out有提供一个printf方法:
b转换符输出布尔值,B输出大写布尔值
s输出字符串,f表示浮点数,d表示十进制整数,
o输出八进制,x输出十六进制,\n换行
标志分别为:
, 添加分组分隔符,好像对小数点后不起作用
0 数字前面补0(指定宽度有余时)
空格 在正数之前添加空格(默认右对齐,所以看起来跟没加空格标志的没有区别)
- 左对齐
( 将负数括在括号里,取出负号
# 对于f格式是包含小数点;对于x或o格式,是添加前缀0x或0
$ 给定被格式化的参数索引。如 %1$d 将以10进制打印第1个参数
< 格式化前面说明的数值(同一个语句内,该标志前面的转换符对应的参数)
可以同时使用多个标志
printf方法中日期与时间的格式化选项,应使用java.time包的方法,以下格式是Date类和相关的格式化选项
不知道为什么月份显示中文了,用cmd输出也是这样,跟时区有关吗?注意格式中必须有t
c 完整的日期和时间 按星期 月 日 时间 时区 月份依次打印
F ISO 8601 日期
D 美国格式的日期(月/日/年)月、日都是两位数,不够补零
T 24小时时间
r 12小时时间 后面带pm或am,这里是下午或上午
R 24小时没有秒
Y 四位数字的年
y 年的后两位数字(前面补0)
C 年的前两位数字(前面补0)
B 月的完整拼写
b/h 月的缩写
m 两位数字的月,前面补0
d 两位数字的日 前面补0
e 两位数字的日,前面不补0
A 星期几的完整拼写
a 星期几的缩写
j 三位数的年中的日子,前面补0,在001~336之间
H 两位数字的小时,前面补零,在0~23之间
k 两位数字的小时,前面不补0,在0~23之间
I 两位数字的小时,前面补0,在0~12之间
l 两位数字的小时,前面不补0,在0~12之间
M 两位数字的分钟,前面补0
S 两位数字的秒,前面补0
L 三位数字的毫秒
N 九尾数字的毫微秒
p 上午或下午的标志
z 从GMT起,RFC822数字位移(啥玩意)
Z 时区
s 从格林威治时间1970-01-01 00:00:00起的秒数
Q 从格林威治时间1970-01-01 00:00:00起的毫秒数
import java.util.Date;
/**
* @author uthor 默夜
* @version 1.0
*/
public class test {
public static void main(String[] args) {
/**
* System.out有提供一个printf方法:
* b转换符输出布尔值,B输出大写布尔值
* s输出字符串,f表示浮点数,d表示十进制整数,
* o输出八进制,x输出十六进制,\n换行
*/
System.out.printf("%b\n",true);//true
boolean flag = true;
System.out.printf("%b\n",flag);//true
System.out.printf("%B\n",flag);//TRUE
flag = false;
System.out.printf("%b\n",flag);//false
System.out.printf("%B\n",flag);//FALSE
/**
* 标志分别为:
* , 添加分组分隔符,好像对小数点后不起作用
* 0 数字前面补0(指定宽度有余时)
* 空格 在正数之前添加空格(默认右对齐,所以看起来跟没加空格标志的没有区别)
* - 左对齐
* ( 将负数括在括号里,取出负号
* # 对于f格式是包含小数点;对于x或o格式,是添加前缀0x或0
* $ 给定被格式化的参数索引。如 %1$d 将以10进制打印第1个参数
* * 可以同时使用多个标志
*/
System.out.printf("%,.4f\n",10000/3.0);//3,333.3333
System.out.printf("%08.2f\n",10000/3.0);//03333.33
System.out.printf("% 9.2f\n",-10000/3.0);// -3333.33
System.out.printf("%-8.2f\n",10000/3.0);//3333.33
System.out.printf("% 8.2f\n",10000/3.0);// 3333.33
System.out.printf("%8.2f\n",10000/3.0);// 3333.33
System.out.printf("% 8.2f\n",-123.5);// -123.50
System.out.printf("%(8.2f\n",-123.5);//(123.50)
System.out.printf("%,(.2f\n",-1236.5);//(1,236.50)
System.out.printf("%.0f\n",100.0);//100
System.out.printf("%#.0f\n",100.0);//100.
System.out.printf("%o\n",8);//10
System.out.printf("%#o\n",8);//010
System.out.printf("%x\n",10);//a
System.out.printf("%#x\n",10);//0xa
System.out.printf("%1$d %1$x\n",159);//159 9f
System.out.printf("%1$d %,159);//159 9f//可以用静态的String.format方法创建一个格式化的字符串
String message = String.format("hello,I am %s.Next year,I will be %d","张三",21);
System.out.println(message);//hello,I am 张三.Next year,I will be 21/**
* printf方法中日期与时间的格式化选项,应使用java.time包的方法,以下格式是Date类和相关的格式化选项
* 不知道为什么月份显示中文了,用cmd输出也是这样,跟时区有关吗?注意格式中必须有t
* c 完整的日期和时间 按星期 月 日 时间 时区 月份依次打印
* F ISO 8601 日期
* D 美国格式的日期(月/日/年)月、日都是两位数,不够补零
* T 24小时时间
* r 12小时时间 后面带pm或am,这里是下午或上午
* R 24小时没有秒
* Y 四位数字的年
* y 年的后两位数字(前面补0)
* C 年的前两位数字(前面补0)
* B 月的完整拼写
* b/h 月的缩写
* m 两位数字的月,前面补0
* d 两位数字的日 前面补0
* e 两位数字的日,前面不补0
* A 星期几的完整拼写
* a 星期几的缩写
* j 三位数的年中的日子,前面补0,在001~336之间
* H 两位数字的小时,前面补零,在0~23之间
* k 两位数字的小时,前面不补0,在0~23之间
* I 两位数字的小时,前面补0,在0~12之间
* l 两位数字的小时,前面不补0,在0~12之间
* M 两位数字的分钟,前面补0
* S 两位数字的秒,前面补0
* L 三位数字的毫秒
* N 九尾数字的毫微秒
* p 上午或下午的标志
* z 从GMT起,RFC822数字位移(啥玩意)
* Z 时区
* s 从格林威治时间1970-01-01 00:00:00起的秒数
* Q 从格林威治时间1970-01-01 00:00:00起的毫秒数
*/
Date today = new Date();//第一个参数是实际的年减去1900的差
Date past = new Date(-1802,2,2);
System.out.printf("%tc\n",today);//星期日 十月 11 21:32:32 CST 2020
System.out.printf("%tF ; %,today);//2020-10-11 ; 10/11/20
System.out.printf("%tT ; %,today);//21:39:51 ; 09:39:51 下午 ; 21:39
System.out.printf("%tY ; %,today);//2020 ; 20 ; 20
System.out.printf("%tY ; %,past);//0098 ; 98 ; 00
System.out.printf("%tB ; %,today);//十月 ; 十月 ; 十月 ; 10
System.out.printf("%td ; %,today);//11 ; 11
System.out.printf("%td ; %,past);//02 ; 2
System.out.printf("%tA ; %,today);//星期日 ; 星期日
System.out.printf("%tj\n",today);//285
System.out.printf("%tH ; %,today);//21 ; 21 ; 09 ; 9
System.out.printf("%tM ; %,today);//39 ; 51 ; 146 ; 146000000
System.out.printf("%tp ; %,today);//下午 ; +0800 ; CST
System.out.printf("%ts ; %,today);//1602423591 ; 1602423591146
System.out.printf("%1$s %2$tB %2$te, %,"today:",today);//today: 十月 11, 2020
}
}
12、大数值初用:测试从490个可能数值中抽取60个的概率
public class Test {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("抽取多少个数值?");
int k = s.nextInt();
System.out.println("最大的数值为多少?");
int n = s.nextInt();
//使用静态的valueOf方法将普通的数值转化为大数值
BigInteger lotteryOdds = BigInteger.valueOf(1);
for(int i = 1;i <= k;i ++){
lotteryOdds = lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i));
}
//1 / 716395843461995557415116222540092933411717612789263493493351013459481104668848
System.out.println("你的概论为:1 / " + lotteryOdds.toString());
}
}
13、int自动转换为float有可能出现精度损失,long确实会默认转换为float
public class Test{
public static void main(String args[]){
int n = 123456789;
float f = n;
System.out.println(n);//123456789
System.out.println(f);//1.23456792E8
long l = 10L;
float f = l / 1F;
System.out.println(f);//10.0
}
}
14、浮点型被0除会得到无穷大或者NaN结果,整数被0除产生运行时异常
public class Test{
public static void main(String args[]){
int n = 1;
//java.lang.ArithmeticException: / by zero
System.out.println(n/0);
float f = 1F;
System.out.println(f/0);//Infinity
//如果强转希望进行舍入运算,可调用java.lang.Math的round方法
double x = 9.997;
//返回最接近参数的long类型
int nx = (int)Math.round(x);
System.out.println(nx);//10
}
}
15、静态变量在类加载时执行,而实例变量在创建对象时执行
public class Test{
static T t1 = new T(1);
T t2 = new T(2);
static T t3 = new T(3);
public static void main(String args[]){
Test t = new Test();//如果没有这行,那么Test:2不出现
}
}
class T{
public T(int i){
System.out.println("Test:"+i);
}
}