15天学Java-Day02
引言
作为一名Linux运维程序员,这是我学习Java的第二天,也是接受新的挑战的一天,和我一样的程序员很多,但是做出改变,踏出那关键的一步的人很少。我相信,我们只有在不断的改变,不断地提升自己,才能一步一步走向更高的舞台,让我们一起开始今天新的学习吧。
Demo01
扫描器与switch…case联合应用:在scanner扫描器收集到我们所输入的数据之后,在switch…case中进行运行,输出我们设定的结果。
注意:在switch…case中一定要注意语句穿透,没有break进行switch语句的跳出,会导致case语句穿透。
public class Demo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取一行数据
// 注意:同一个scanner不要混用nextLine与nextInt
String inputStr = scanner.nextLine();
switch(inputStr){// byte short int char String 枚举
case "篮球":
System.out.println("爱好是篮球");
// 跳出switch语句,没有break,会发生case语句穿透
break;
case "足球":
System.out.println("爱好是足球");
break;
case "网球":
System.out.println("爱好是网球");
break;
default:
System.out.println("输入的内容暂时无法判断");
break;
}
}
}
Demo02
JVM中的存储空间:
栈: 固定大小的数据
堆: 存储区域的称呼,动态分配
注意: 这里我们将会抽出一个单独文章进行堆和栈的讲解,也会让我们这些初识Java的程序员们了解一下堆和栈的原理。
new:这里给各位程序员们介绍一个非常有意思的关键字“new”,这个关键字非常的有意思,他代表什么意义呢?
从单词本意可以看出这个单词是新鲜的,崭新的。但是他在我们Java中代表什么意义呢?
注意: 在Java中只要是new了,就是新的,我们可以通过new来创建一个对象,没对象的请注意,我们可以new一个出来!new也叫类的实例化,会调用构造方法初始化对象。
new关键字创建对象的过程:
1.将类加载到方法区
2.在堆中开辟一块内存用于存储新创建的对象
3.在栈中创建指向对象的引用
public class Demo02 {
public static void main(String[] args) {
// new 新建 -》 只要new就会分配新的地址
String info1 = new String("字符串");
String info2 = new String("字符串");
System.out.println(info1);
System.out.println(info2);
// 引用类型 == 比较的时地址
System.out.println(info1 == info2);// false
// 如果需要判断两个字符串的值是否相等
// 以后还会遇到更多的引用类型,如果需要判断值相等,重写equals
System.out.println(info1.equals(info2)); // true
int x = 100;
int y = 100;
// 基本数据类型 == 比较值
System.out.println(x == y); // true
}
}
对于字符串是否相等判断的进阶
public class Demo021 {
public static void main(String[] args) {
String info1 = "字符串";
String info2 = "字符串";
// 先到常量区中查找改字符串,没有就创建
String info3 = new String("字符串");
String info4 = new String("字符串");
System.out.println(info1 == info2); // true
System.out.println(info1 == info3); // false
System.out.println(info3 == info4); // false
// 只要判断字符串值是否相等,统一使用equals判断
System.out.println(info3.intern() == info1); // true
}
}
总结new关键字:new关键字是一个很神奇的关键字,任何的字符串只要是进行了new的操作,就会给他分配新的储存地址,从而和原先的字符串存储地址不同,进而在Java中进行判断的时候两个字符串的值不相等。因为以后还会遇到很多的引用类型,如果需要判断值相等,那么重写equals就是我们最好的选择啦。
Demo03
实例的变量与类的变量:
// 实例的变量
int a = 100;
// 类的变量
static int b = 10;
静态方法与非静态方法:我们在进行Java代码编写中,如何区分静态方法与非静态方法呢?这其实十分的简单,就是通过一个关键词“static”,包含static的方法,称为静态方法。
public class Demo03 {
// 实例的变量
int a = 100;
// 类的变量
static int b = 10;
public static void main(String[] args) {
Demo04 demo04 = new Demo04();
System.out.println(demo04.a);
// 实例.方法名调用执行
demo04.test01();
// 类的变量 类名.变量名 类名可以省略
System.out.println(b);
Demo04.test02();
}
// public 返回值类型 方法名(参数){方法体}
// 只有被调用才会执行 实例的方法
// 非静态方法--普通方法
public void test01(){
System.out.println("no static");
}
// 类的方法 包含static的方法,成为静态方法
public static void test02(){
System.out.println("static");
}
}
Demo04
return关键字:“return”关键字有两个用处;1.返回值并结束方法。2.结束方法。详细介绍看下面代码。
public class Demo05 {
public static void main(String[] args) {
Demo05 demo05 = new Demo05();
//demo05.test01();
//demo05.test02();
demo05.test03();
}
/**
* 方法一定要有一个返回值
* return 必须写,并且返回值要为int类型, 必须要确保程序最后一定要有返回值
* public 返回值类型
* @return
*/
public int test04(){
for(int i = 0; i < 10; i ++){
if(i == 5){
//结束方法,其后的不在执行
return i;
}
System.out.println(i);
}
System.out.println("test01结束");
return 0;
}
public String test05(){
String b = "aa";
if("aa" == b){
return "cc";
} else {
return "dd";
}
}
/**
* return 结束方法
* void 无返回值 return; 没有返回值的
*/
public void test01(){
for(int i = 0; i < 10; i ++){
if(i == 5){
//结束方法,其后的不在执行
return;
}
System.out.println(i);
}
System.out.println("test01结束");
}
/**
* 0 1 2 3 4 test01结束
*/
public void test02(){
for(int i = 0; i < 10; i ++){
if(i == 5){
//跳出其所在的循环
break;
}
System.out.println(i);
}
System.out.println("test01结束");
}
/**
* 0 1 2 3 4 6 7 8 9 test01结束
*/
public void test03(){
for(int i = 0; i < 10; i ++){
if(i == 5){
//跳过本次循环,继续下一次循环
continue;
}
System.out.println(i);
}
System.out.println("test01结束");
}
}
Demo05
null:对于我们新晋Java程序员来说,null是个非常令人头疼的东西。大家是不是在数组的训练过程中常常遇到NullPointerException(空指针异常)呢?就连java的发明者都承认这是他的一项巨大失误。但是为什么还要保留null呢?这个问题还在持续的研究中。尽管null被Java开发者和开源社区批评,但是我们必须与null共同存在,与其抱怨,不如共同学习null这个关键字,确保正确使用null。
null的设计初衷是为了表示一些缺失的东西。但是一年后,NullPointerException给我们Java程序员带来的不少的骚扰,这下面的一些基础,都是为了让我们尽可能减少null的检查以及如何规避NullPointerException。
1. null是Java中的关键字,像public、static、final,大小写比较敏感,我们不可以将null写成NULL,编译器是无法识别NULL的。但是,如果你使用的像IDEA、Eclipse这样的软件,可以纠正这个错误。而notepad、Vim,这个问题会在你不注意的情况下一直烦扰你。
2. 每种原始类型都有默认值,例如int默认值是0,boolean默认值是false,null是任意类型的默认值。在Java中任何的引用变量都将null作为默认值。这对所有变量都适用,如成员变量、局部变量、静态变量,但是使用时要注意初始化。
3. null既不是对象也不是一种类型,他仅仅是一种特殊的之,你可以将其赋予给任何引用类型,你也可以将null转化成任何类型。
4. null可以赋值给引用变量,我们不能将null付给基本类型变量,如int、double、boolean、float。
5. 任何含有null值得包装类在Java拆箱生成基本数据类型时都会抛出一个NullPointerException。在使用HashMap和integer键值时会发生很多上述得错误,将null赋值给了基本类型变量。
6. 如果使用带有null值得引用类型变量,instanceof操作将会返回false,这是instanceof操作的一个很重要的特性,使得对类型强制转换检查很有用。
7. 你可以使用静态方法来使用一个值为null的引用类型变量。因为静态方法使用静态绑定,不会抛出空指针异常。
8. 你可以将null传递给方法使用,这时方法可以接收任何引用类型。
9. 你可以使用==或者!=操作来比较null值,但是不能使用其他算法或者逻辑操作,例如小于或者大于。
public class Demo05 {
// 引用类型的默认值 null
static String s;
public static void main(String[] args) {
// null
System.out.println(s);
// 定义方式
// 数据类型[] 数组变量名 = .....
// 整型数组,只能存放整数
int[] arr01 = {1,4,6,8}; // 数组初始化
// 4 表示数组长度
int[] arr02 = new int[4];
// 数组变量.length 获取数组的长度
System.out.println(arr02.length);
// 访问数组, 通过下标访问,下标从0开始
// 数组最大小标 数组长度-1
System.out.println(arr01[0]);
for(int i = 0; i < arr02.length; i++){
System.out.println(arr02[i]);
}
arr02[0] = 100;
String[] strings = new String[3];
System.out.println(strings[0]);
strings[0] = "null";
}
}
下面是我们经常遇到的NullPointerException:
public class Demo051 {
// int类型的数组, 数组--引用类型
static int[] arr01;
public static void main(String[] args) {
// 如果没有完成对数组的,默认值为null
System.out.println(arr01);
// NullPointerException 经常遇到
// System.out.println(arr01.length);
arr01 = new int[4];
// ArrayIndexOutOfBoundsException
for(int i = 0; i < arr01.length; i++){
System.out.println(arr01[i]);
}
}
}
Demo06
随机数:要产生随机数,可以使用Java api中java.lang包中的Math类.Math类以静态方法的方式提供常用的数学方法,其中Math.random()方法是一个可以产生[0.0,1.0]区间内的一个双精度浮点数的方法。
public class Demo06 {
public static void main(String[] args) {
// 返回一个double类型的随机数 [0.0,1.0)
double value = Math.random();
// [0,100] 随机整数 -> [0.0,1.0) -> [0.0,101)
int val01 = (int) (Math.random() * 101);
System.out.println(val01);
// [0.0,1.0) -> 强转 - 》只能是0 不可取
int val02 = (int) (Math.random()) * 101;
System.out.println(val02);
// [30-100]
int val03 = (int) (Math.random() * 71 + 30);
Demo08 demo08 = new Demo08();
demo08.test01();
}
public void test01(){
// 整型数组,长度为5,为给他们依次赋值[0,100],之间的随机数
int[] arr = new int[5];
for(int i = 0; i < arr.length; i++){
arr[i] = (int) (Math.random() * 101);
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
Demo07
数组的最大最小值:我们总是用Java代码来求一些数组的最大值与最小值,那么我们具体应该怎么实现他呢?
public class Demo09 {
// 首先我们输入一个数组
static int[] arr = {20 ,30 ,5 , 55, 32};
public static void main(String[] args) {
// 变量max接收maxValue方法的返回值
int max = maxValue();
int min = minValue();
System.out.println(max);
System.out.println(min);
}
/**
* 求数组的最大值
* @return
*/
public static int maxValue(){
// 假设数组的第一个元素就是最大值
int maxValue = arr[0];
for(int i = 1; i < arr.length; i++){
if (maxValue < arr[i]){
maxValue = arr[i];
}
}
return maxValue;
}
/**
* 求数组的最小值
* @return
*/
public static int minValue(){
int minValue = arr[0];
for(int i = 1; i < arr.length; i++){
if(minValue> arr[i]){
minValue = arr[i];
}
}
return minValue;
}
}
Demo08
二分法查找:
二分法查找的原理是什么呢?
首先,我们应该要确定的是,采用二分法查找时,数据是需要有序不重复的。假设数据是按照升序排列的,对于给定值 x,从序列的中间位置开始比较,如果当前位置值等于 x,则查找成功;若 x 小于当前位置值,则在数列的前半段中查找;若 x 大于当前位置值则在数列的后半段中继续查找,直到找到为止。
public class demo10 {
static int[] arr = {12, 21, 33, 37, 39, 45, 52};
public static void main(String[] args) {
binarySearch(35);
//Arrays.binarySearch()
}
/**
* 二分查找
* 33-》 31
* searchValue 方法参数,由调用的时候传入
*
* 31
* 12, 21, 33, 37, 39, 45, 52
* 0 left 3 middle 6 right
* 0 lfet 2 right -> middle 1
* 2 left 2 right -> middle 2
* 9
* 12, 21, 33, 37, 45, 52
* 0 left 2 middle 5right
*
* 0left 1 right -》 middle 0
* 0left -1 right -> middle 0
*
*/
public static void binarySearch(int searchValue){
int left = 0;
int right = arr.length - 1;
int middle = (left + right) >>> 1;
// 不清楚循环次数,使用while循环
while(left <= right){
if(searchValue > arr[middle]){
left = middle + 1;
} else if(searchValue < arr[middle]) {
right = middle - 1;
} else {
// 找到了对应的元素,可以结束了
System.out.println("找到了" + middle);
break;
}
middle = (left + right) / 2;
}
}
}
Demo09
注意注意: 接下来是我们今天的重中之重,冒泡排序了!这个冒泡排序十分重要,不仅需要我们明白原理,还要会书写,一定要牢牢掌握呀,我的各位新晋Java码农们!!!废话不多说,进入代码!
public class Demo11 {
// 首先给他一个数组
static int[] arr = {23,43,21,33,29,19};
// 23,43,21,33,29,19
// for循环第一轮
// 23,43,21,33,29,19-》23,21,43,33,29,19->23,21,33,43,29,19
// 23,21,33,29,43,19 -》 23,21,33,29,19,43
// for循环第二轮
// 23,21,33,29,19>21,23,33,29,19->21,23,29,33,19->21,23,29,19,33
// for循环第三轮
// 21,23,29,19 -》 21,23,19,29
// for循环第四轮
// 21,23,19 -》 21,19,23
// for循环第五轮
// 21,19 -》 19, 21
public static void main(String[] args) {
for(int i = 0; i < arr.length-1; i++){
for(int j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j+1]){
// 交换元素位置
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for(int j = 0; j < arr.length; j++){
System.out.println(arr[j]);
}
}
}
冒泡排序的优点: 每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。如上例:第一趟比较之后,排在最后的一个数一定是最大的一个数,第二趟排序的时候,只需要比较除了最后一个数以外的其他的数,同样也能找出一个最大的数排在参与第二趟比较的数后面,第三趟比较的时候,只需要比较除了最后两个数以外的其他的数,以此类推……也就是说,没进行一趟比较,每一趟少比较一次,一定程度上减少了算法的量。
Homework
我们一起做个小练习:
/*
* 题目
* String[] tempArr = {"公孙离","孙悟空","达摩","黄忠","妲己"};
* String[] finalArr = new String[3];
* 1.依次通过随机数产生一个tempArr数组的下标,将这个下标对应的元素依次赋给finalArr值
* 2.不允许赋值重复
* */
/*附上代码 供小伙伴们参考*/
public class Practice01 {
// 实例的变量
// String[] tempArr = {"公孙离","孙悟空","达摩","黄忠","妲己"};
// 类的变量
static String[] tempArr = {"公孙离", "孙悟空", "达摩"};
static String[] finalArr = new String[3];
public static void main(String[] args) {
//test01();
int i = 10;
while (i > 0) {
test02();
i--;
System.out.println("============");
}
}
/**
* 类的方法--静态方法
*/
public static void test01() {
for (int i = 0; i < finalArr.length; i++) {
// [0,tempArr.length-1]
int index = (int) (Math.random() * tempArr.length);
finalArr[i] = tempArr[index];
}
output();
}
public static void test02() {
int[] randomMemory = new int[3];
// 2 3 2 比随机数不能重复
// finalArr[0] 黄忠 finalArr[1] 公孙离 finalArr[2] 妲己
for (int i = 0; i < finalArr.length; i++) {
// 随机数产生的下标
int index = (int) (Math.random() * tempArr.length);
System.out.println("index--->" + index);
// 产生的索引是否重复,默认不重复 ----》假设
boolean isRepated = false;
if (i == 0) {
randomMemory[0] = index;
} else {
// 对比之前产生的随机数值是否重复
for (int j = 0; j < i; j++) {
System.out.println("randomMemory[j]--->" + randomMemory[j]);
if (index == randomMemory[j]) {
isRepated = true;
// 如果重复的话。怎么办
break;
}
}
}
if (isRepated) {
// 随机数重复
// 数据重复,向反方向减一,因为for循环之后会加1,
// 要保证产生的随机数还是当前的这个位置的元素
i--;
} else {
randomMemory[i] = index;
System.out.println("tempArr[index]--->" + tempArr[index]);
finalArr[i] = tempArr[index];
}
}
output();
}
public static void test05() {
int[] randomMemory = new int[3];
// 2 3 2 比随机数不能重复
// finalArr[0] 黄忠 finalArr[1] 公孙离 finalArr[2] 妲己
for (int i = 0; i < finalArr.length; i++) {
int index = (int) (Math.random() * tempArr.length);
// 产生的索引是否重复,默认重复
boolean isRepated = true;
if (i == 0) {
randomMemory[0] = index;
} else {
while (isRepated) {
int j = 0;
// 对比之前产生的随机数值是否重复
for (; j < i; j++) {
if (index == randomMemory[j]) {
index = (int) (Math.random() * tempArr.length);
// 如果重复的话。怎么办
break;
}
}
if (j == i) {
isRepated = false;
}
}
}
randomMemory[i] = index;
finalArr[i] = tempArr[index];
}
output();
}
/**
* 遍历输出数组元素
*/
public static void output() {
for (int i = 0; i < finalArr.length; i++) {
System.out.println(finalArr[i]);
}
}
public static void test04(){
boolean[] flag = new boolean[tempArr.length];
int index = 0;
do{
int r = (int) (Math.random() * tempArr.length);
if(flag[r] == false){
finalArr[index] = tempArr[r];
flag[r] = true;
index++;
if(index == finalArr.length){
return;
}
}
}while (true);
}
}
总结
1.今天我们主要学习的是我们的排序算法,有二分法查找、冒泡排序,这两个是我们走进算法的基石,也让我们在算法的学习路上逐渐走的长远。
2.我们学习到了几个新的关键字,new、return,这两个关键字也是十分重要的,在我们以后编写Java的程序时会经常遇到这两个关键字,他就像我们的手机一样,每天都会看见他,一定要好好的学习这两个关键字,理解他们所代表的意义。
3.我们还接触了一个值,也是一个让我们这些新晋Java程序猿非常头疼的一个错误。NullPointerException,就连Java开发者都认为这是他的一大失误,但是我们还是要进行学习的,因为这个null是与我们共同存在的。
4.JVM中的堆和栈我们会在一个博客中单独进行介绍,他们的底层原理也是十分的难以理解,但是有兴趣的小伙伴可以等我更新哦。
5.今天还学习到了一个重要的命令,随机数的生成,这样我们可以在进行抽签、抽奖,这样的随机数生成中大展身手。
6.最后我们一起做的练习,巩固了我们今天所学的所有知识,就让我们快乐学习,学好每一天!
作者感悟
在Java学习的第二天,我们逐渐进入了Java的学习状态,使我变得特别爱钻研每一个我不懂得点,让我的知识库得到充实。希望我们的每一天都可以过得如此充实,就让我们快乐学习,将Java的基础打的牢固,把我们的Java学习之路走下去!通过这一天的学习,我发现我的思维还是有些改变不过来,第一时间还是以一种对待linux的态度对待Java,我会逐渐变得适应这种思想,变成一个Java与Linux双精程序猿!