今日学习-20200924
1. IEDA使用
1.1 创建模板
Settings->File and Code Templates->includes->(填写模板)->OK
设置成功后:
1.2 修改快捷键
多次使用发现,IDEA一键格式化的快捷键和QQ的自动锁定的快捷键重复了,导致每次格式化没完成,QQ先给我锁了。
解决:File->Settings->Keymap->搜索Reformat Code->改为Ctrl+Alt+R
2. 知识点
2.1 包
装类的。在src文件夹下新建包,本质上就是文件夹,分类用的,因为以后写的项目会越来越大,类不能一股脑全部放在src下,既不好寻找,也容易重名,所以需要建文件夹把这些类分开。
命名方式为com.baidu.XXX(行业规定,公司的域名倒过来写,确保不会重复),包名全部小写。因为我们后期还会引入各种各样的架构,如果不这么命名,很容易重复,而且同名文件也不好拷进来。
这样命名的好处,一眼就能看出来我们使用的架构是哪个公司编写的。
新建包的两种方式:
-
直接右击src新建package
-
右击src新建java class,建class是带上包名,此时会将该package和class一起建好
注意命名格式,包名群不小写,类名首字母大写
2.2 权限修饰符
作用域 | 当前类 | 同package | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | × | |
friendly(default) | √ | √ | × | |
private | √ | × | × | × |
测试public权限修饰符:
package com.seu.java;
/**
* @author SJ
* @date 2020/9/24
*/
public class Java {
public void java(){
System.out.println("我来自com.seu.java包的Java类的java方法");
}
}
package com.seu.test;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test2 {
public void print3() {
System.out.println("我来自test包的Test2类的print3方法");
}
}
package com.seu.test;
import com.seu.java.Java;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test {
public static void main(String[] args) {
System.out.println("接下来要测试public的适用范围:我当前处在com.seu.test包的Test类");
System.out.println("测试当前类:");
Test test = new Test();
test.print();
System.out.println("测试同package:");
Test2 test2 = new Test2();
test2.print3();
System.out.println("测试其他package:");
Java java = new Java();
java.java();
}
public void print(){
System.out.println("我来自com.seu.test包的Test类的print方法");
}
public void print2(){
System.out.println("我来自com.seu.test包的Test类的print2方法");
}
}
运行结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
接下来要测试public的适用范围:
测试当前类:
我来自com.seu.test包的Test类的print方法
测试同package:
我来自test包的Test2类的print3方法
测试其他package:
我来自com.seu.java包的Java类的java方法
Process finished with exit code 0
测试protected权限修饰符:
将上述所有方法改成protected后,调用其他包方法时报错,其余均可成功执行。
测试private权限修饰符:
将上述所有方法改成private后,除了当前类调用方法不报错,其余全部报错。
为什么要用权限修饰符
-
对自己而言,保护代码不被污染
-
对别人而言,给别人一个干净的接口
2.3 类new对象、构造方法、get和set
万物皆对象。对象1.有特点(属性)2.能做一些事(方法)
我们写的class是描述这类对象有什么属性和方法。
属性:一般使用基础类型或引用类型描述,在Java里属性一般会私有化,使用private关键字,使用setter和getter方法进行取值和赋值。
方法:封装了一些代码逻辑,方法的目的就是做好一件事情,我们在定义类里面,一个方法就是这类事物的一个功能。
构造方法:名字和类名相同,不能有返回值,可以有参数。一旦自己定义了构造方法,系统不会赠送空的构造方法
get和set方法
//每个方法,定义的时候,都会默认传入两个变量
//this:this代表new出来的哪个对象
//super 当前类的父类的对象
package com.seu.test;
/**
* @author SJ
* @date 2020/9/24
*/
public class TestAttribute {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
我们虽然将name私有化了,但是我们可以通过公有化的方法get和set给私有化的name赋值。
测试:
package com.seu.test;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test2 {
protected void print3() {
System.out.println("我来自test包的Test2类的print3方法");
}
public static void main(String[] args) {
TestAttribute testAttribute = new TestAttribute();
testAttribute.setName("宝宝");
System.out.println(testAttribute.getName());
}
}
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
宝宝
Process finished with exit code 0
如果我们直接使用name,并把它定义为public,那么别的地方想怎么用就怎么用。
如果定义为private,别的地方根本没法用。
我们使用get和set方法有什么用呢?我们可以在get和set函数里设置一些条件,控制权限。别人像操纵我们的数据的时候得问问能不能这么操作,使数据更加安全。
所以在java里,所有的属性都是private。所有的属性都有get和set,get和set可以一键生成。
2.4 封装、继承
测试继承
package com.seu.myextends;
/**
* @author SJ
* @date 2020/9/24
*/
public class Parent {
private String name;
private Boolean isRich;
public void distributeMoney(){
System.out.println("父亲分财产!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getRich() {
return isRich;
}
public void setRich(Boolean rich) {
isRich = rich;
}
}
package com.seu.myextends;
/**
* @author SJ
* @date 2020/9/24
*/
public class Son extends Parent {
private String name;
public void say(){
//super指向了parent的一个对象
if (super.getRich())
System.out.println("我是富二代");
else
System.out.println("我没法拼爹");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.seu.myextends;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test {
public static void main(String[] args) {
Son son = new Son();
son.setRich(true);
son.setName("小明");
son.say();
}
}
测试结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
我是富二代
Process finished with exit code 0
总结:继承的实质,儿子没有的方法,可以从父亲里面找,儿子没有的变量,也可以从父亲里面找。
顺序是,先在自己这里找,如果找不到,就去父亲那里找
你可以继承你爹所有的东西,但是你爹私有化的东西(不想给你),你就继承不了。
java里的顶级父类:Object。所有的对象都有Object类的所有方法。
son的下面这些方法,都继承自顶级父类Object。
覆盖:若儿子有跟父亲同名的方法,先用儿子的。儿子没有才去父亲那里找。
叫儿子重写父亲的方法。
跟之前学习的环境变量一样,现在当前的文件夹里找,找不到再去系统环境变量里找。
注意:java里是单继承。儿子只能有一个爹。但是一个爹可以有多个儿子。(这里跟C++不一样,C++是多继承)
2.5 内存的使用,静态过程和动态过程
画图工具:processon https://www.processon.com/diagraming/5f6c9622e401fd64b5d92ca9
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JPhmI0zG-1603001299243)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200924215050157.png)]
第一次主动使用类,类就会被加载到内存。加载的过程是一个静态的过程,加载就是把class放在内存里面,同时初始化了一些static变量和方法,运行的时候是在main方法里运行,真正创建对象是在main方法里创建,一创建就会在内存里开辟一块空间放这些方法和变量,所以普通的方法和变量都是属于对象的。而static方法和变量是属于类对象的。类对象在内存里只有一份,在类加载的过程中就被初始化。
2.6 String
字符串是引用类型,但是为什么不用new?-因为太常用了,就简化了。
package com.seu.mystring;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test {
public static void main(String[] args) {
String myString = "myString";
//判断"myString"里是否包含"my"
//实际应用:判断一段话里有没有这个关键字
boolean my = myString.contains("my");
System.out.println(my);
//找子串,从第二个截到第四个,不包含第四个
//实际应用:身份证判断省份、城市、生日等
String substring = myString.substring(2, 4);
System.out.println(substring);
//分割字符串
//实际应用:剥离一些东西
String tobeSplit = "张三、李四、王五";
//用“、”分割字符串,分割完是个数组
String[] s = tobeSplit.split("、");
for (String s1 :
s) {
System.out.println(s1);
}
//判断字符串相等
String a = "woshizhu";
boolean m = a.equals("woshizhu");
System.out.println(m);
}
}
运行结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
true
St
张三
李四
王五
true
Process finished with exit code 0
java String类下方法常用总结:https://blog.csdn.net/w464960660/article/details/105233704?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight
2.7 基础类型的包装类
(这篇文章写得很好)https://alexyyek.github.io/2014/12/29/wrapperClass/
例:int i=3;
i是基本数据类型,是没有方法的,是 . 不出来的。
所以java给我们提供了包装类,将所有的基础类型进行了包装。
Integer i = 3; 也不用new,这叫自动装箱。
使用时会自动将包装类转为基本数据类型,sout时也可以直接sout(i),不足要i.get(),这叫自动拆箱。此时 i 就有了方法:
因此可以用一句话总结装箱和拆箱的实现过程:
装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的xxxValue方法实现的。(xxx代表对应的基本数据类型)。
Integer 就是int的包装类,封装了int类型和一些方法。
基本类型 | 大小 | 包装类 |
---|---|---|
boolean | / | Boolean |
char | 16bit | Character |
byte | 8bit | Byte |
short | 16bit | Short |
int | 32bit | Int |
long | 64bit | Long |
float | 32bit | Float |
double | 64bit | Double |
void | / | Void |
包装类一些很难被注意到的问题:
package com.seu.baozhuanglei;
/**
* @author SJ
* @date 2020/9/24
*/
public class TestBaoZhuang {
public static void main(String[] args) {
Integer integer1=100;
Integer integer2=100;
Integer integer3=200;
Integer integer4=200;
System.out.println(integer1==integer2);
System.out.println(integer3==integer4);
}
}
这段代码的执行结果是什么?
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
true
false
Process finished with exit code 0
为什么是这个结果?
首先我们要区分"==“和"equals()”
基本类型 | == | equals |
---|---|---|
字符串变量 | 对象在内存中的首地址 | 字符串内容 |
非字符串变量 | 对象在内存中的首地址 | 对象在内存中的首地址 |
基本类型 | 值 | 不可用 |
包装类 | 地址 | 内容 |
现在我们可以明确。"=="比较的是两个包装类对象的地址。
说明 integer1 和 integer2 指向同一对象;integer3 和 integer4 指向不同对象。
我们来看一下源码:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJgCemXv-1603001299248)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200924184758220.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ligi644-1603001299252)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200924185329610.png)]
源码说明:首先他们搞了一个cache,装 -128~127(包含)之间的数,如果传进来的 int 在这里面,就直接返回已经存在于cache中的对象的引用,如果不在这中间,就重新new一个Interger对象。
100在这个范围内,所以地址是相同的。200不在这个范围内,所以 integer3 和 integer4 都是重新new出来的,地址就肯定不一样。
这样的话,我们再来看看其他的包装类:
package com.seu.baozhuanglei;
/**
* @author SJ
* @date 2020/9/24
*/
public class Test {
public static void main(String[] args) {
Double d1=10.0;
Double d2=10.0;
System.out.println(d1==d2);
Boolean b1=true;
Boolean b2=true;
System.out.println(b1==b2);
}
}
结果:
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe" ...
false
true
Process finished with exit code 0
Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是,所以浮点类型肯定是要新建对象的。
注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的,Double、Float的valueOf方法的实现是类似的。
- 谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。
1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;
2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。
再来最后理解亿遍:
package com.seu.baozhuanglei;
/**
* @author SJ
* @date 2020/9/24
*/
public class LastTest {
public static void main(String[] args) {
Integer i0=1;
Integer i1=2;
Integer i2=3;
Integer i3=3;
Integer i4=231;
Integer i5=231;
Double d1=1.0;
Double d2=1.0;
Float f1=1.0f;
Long l1=3L;
Long l2=2L;
//cache等值对象比较
System.out.println(i2==i3);//true
//cache外等值对象比较
System.out.println(i4==i5);//false
//先算术运算再比较(理论上在cache内)
System.out.println(i3==(i0+i1));//true.触发自动拆箱
//Double等值的比较
System.out.println(d1==d2);//false
//Double类型和Float类型的等值比较
System.out.println(d1.equals(f1));//false类型不同
//含有算数计算的equals
System.out.println(i3.equals(i0+i1));//true 先触发自动拆箱过程,再触发自动装箱过程,也就是说i0+i1,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较
//含有算数计算的等值 但==两边类型不同
System.out.println(l1==(i0+i1));//true
//含有算数计算,equals两边类型不同
System.out.println(l1.equals(i0+i1));//false 类型不同
//含有算数计算,但是计算符号两边类型不同
System.out.println(l1.equals(i0+l2));//true i0转换为long
//如果()内数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法
}
}
结果
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"
true
false
true
false
false
true
true
false
true
Process finished with exit code 0
这里面需要注意的是:当 “==” 运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然。
2.8 API
一个工具,帮助我们看一看,java给我们写了哪些类,有什么方法。
/含有算数计算,equals两边类型不同
System.out.println(l1.equals(i0+i1));//false 类型不同
//含有算数计算,但是计算符号两边类型不同
System.out.println(l1.equals(i0+l2));//true i0转换为long
//如果()内数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法
}
}
结果
```java
"C:\Program Files\Java\jdk1.8.0_131\bin\java.exe"
true
false
true
false
false
true
true
false
true
Process finished with exit code 0
这里面需要注意的是:当 “==” 运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然。
2.8 API
一个工具,帮助我们看一看,java给我们写了哪些类,有什么方法。