zoukankan      html  css  js  c++  java
  • 201521123091 《Java程序设计》第2周学习总结

    Java 第二周总结

    第二周的作业。

    一个简陋的目录
    1.本章学习总结
    2.Java Q&A
    3.使用码云管理Java代码
    4.PTA实验
    5.小任务


    1.本章学习总结

    基本数据类型

    • String类
    • Java的标准输入输出和文件输入输出
    • Java控制执行流程
    • Java数组的使用
    • 类管理机制:包

    2.Java Q&A

    1.使用Eclipse关联jdk源代码(截图),并查看String对象的源代码?简单分析String对象的设计思路。

    1. 从“Window (菜单项目)”上选择“Preferences (菜单项目)”
    2. 展开“Java (框线项目)”(位于“Preferences”中)
    3. 选择“Installed JREs (框线项目)”(位于“Preferences”中)
    4. 选中当前JRE,并且点击Edit按钮
    5. 展开JRE系统库的第二项,选中展开后的第一项,点击“Source Attachment”按钮
    6. 打开JDK目录,选中src.zip,最后一路确定出去

    7. ctrl+鼠标左键选中某一个类,或者选中类之后按F3,源代码文件弹出,第一问就搞定了

    到此为止,只是这一问的第一小问结束了0.0(各位看官不急,我还在码)

    String对象的设计思路(我们可以看到在源代码文档里面已经有说了,所以我们要做的仅仅是翻译一下,当然英文不好的同学(比如我这种),可以借助类似金山词霸之类的划译)

    我们可以看到就是这点,字符串是常量,往下翻翻我们就会看到private final char value[];,用一个final修饰的字符数组来实现这个字符串的

    2.为什么要尽量频繁的对字符串的修改操作应该是用StringBuilder而不是String?
    这个东西我们就有讲头了,不妨来看几个String类自带的方法吧。

    //这是一个字符串连接的方法
    public String concat(String str) {
            int otherLen = str.length();
            if (otherLen == 0) {
                return this;
            }
            int len = value.length;
            char buf[] = Arrays.copyOf(value, len + otherLen);
            str.getChars(buf, len);
            return new String(buf, true);
        }
    
    //这是一个替换的方法
    public String replace(char oldChar, char newChar) {
            if (oldChar != newChar) {
                int len = value.length;
                int i = -1;
                char[] val = value; /* avoid getfield opcode */
    
                while (++i < len) {
                    if (val[i] == oldChar) {
                        break;
                    }
                }
                if (i < len) {
                    char buf[] = new char[len];
                    for (int j = 0; j < i; j++) {
                        buf[j] = val[j];
                    }
                    while (i < len) {
                        char c = val[i];
                        buf[i] = (c == oldChar) ? newChar : c;
                        i++;
                    }
                    return new String(buf, true);
                }
            }
            return this;
        }
    

    在对字符串进行相应修改(例如替换或者是连接)的时候,我们可以发现最后都返回了一个新的字符串常量。所以我们可以想见,如果有大量的字符串拼接的话,那么我们的代码一定会new出很多的String变量,然后又会有很多的垃圾回收。这样的话,代码的效率就会有所降低。

    这边来看个代码吧(当然是从Thinking in Java上抄下来的。。。)

    public class Concatenation{
    	public static void main(String[] args) {
    		String mango = "mango";
    		String s = "abc" + mango + "def" + 47;
    		System.out.println(s);
    	}
    }
    

    然后使用javap进行反汇编看看发生了什么。。。

    Compiled from "Concatenation.java"
    public class Concatenation {
      public Concatenation();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String mango
           2: astore_1
           3: new           #3                  // class java/lang/StringBuilder
           6: dup
           7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          10: ldc           #5                  // String abc
          12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
    ngBuilder;
          15: aload_1
          16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
    ngBuilder;
          19: ldc           #7                  // String def
          21: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
    ngBuilder;
          24: bipush        47
          26: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          29: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          32: astore_2
          33: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
          36: aload_2
          37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          40: return
    }
    

    好了,我们看到这个编译器自动引入了一个叫做StringBuilder的东西,,使用它来进行字符串的拼接。这当然是因为StringBuilder更好了,我们刚才说String是immutable的,那这个StringBuilder是专门为字符串修改而生的,在Java SE5引入。所以编译器很聪明的对代码进行了优化。那也就是说,我可以随意使用String,等着代码优化吗?当然不行咯,Java编程思想又给我们举了个反例,来看看。

    哦,对了,在String的源文档里面有这样一句话,一样的意思

    String concatenation is implemented through the {@code StringBuilder}(or {@code StringBuffer}) class and its {@code append} method.

    利用循环来进行字符串的拼接

    //输入一个n,从0-n的数字转成字符串进行拼接
    public class Main{
    	public static void main(String[] args) {
    		int n = 5;
    		String result1 = "";
    		for (int i = 0; i < n; i++) {
    			result1 += i;
    		}
    		System.out.println(result1);
    		
    		StringBuilder result2 = new StringBuilder();
    		for (int i = 0; i < n; i++) {
    			result2.append(i);
    		}
    		System.out.println(result2.toString());
    	}
    }
    

    我们再来反汇编(* * *大法好,虽然我不是很懂)

    Compiled from "Main.java"
    public class Main {
      public Main();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: iconst_5
           1: istore_1
           2: ldc           #2                  // String
           4: astore_2
           5: iconst_0
           6: istore_3
           7: iload_3
           8: iload_1
           9: if_icmpge     37
          12: new           #3                  // class java/lang/StringBuilder
          15: dup
          16: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          19: aload_2
          20: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
    ngBuilder;
          23: iload_3
          24: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          27: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          30: astore_2
          31: iinc          3, 1
          34: goto          7
          37: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
          40: aload_2
          41: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          44: new           #3                  // class java/lang/StringBuilder
          47: dup
          48: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          51: astore_3
          52: iconst_0
          53: istore        4
          55: iload         4
          57: iload_1
          58: if_icmpge     74
          61: aload_3
          62: iload         4
          64: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          67: pop
          68: iinc          4, 1
          71: goto          55
          74: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
          77: aload_3
          78: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          81: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          84: return
    }
    

    代码中9-34行是第一个循环(用String的那个),我们可以看到,每次循环开始都会new一个StringBuilder变量,58-71行是第二个循环(用StringBuilder的那个),当然是只在我们一开始new了一个。这个循环更简短,效率当然更高。

    3.比较两个字符串的值是否相等?为什么不能用==直接进行比较?

    因为用进行比较并不能保证结果总是正确的(假设下面的情况字符串的内容都是相同的),比较的是两个对象的引用

    • 首先如果两个字符串都是以 String xxx = "xxxxx";的方式创建出来的,在第一个字符串如此创建时,JVM就会在字符串池中维护这么一个String的实例,那么以后只要有内容完全相同的字符串,就直接指向这个实例,所以引用会相同

    • 只要有一个是以new的方式创建新的实例,就会创建一个新的对象,当然就有不一样的引用,所以这时候==的两边是不同的引用,当然会返回false

    综上所述,我们要对两个字符串进行内容的比较的话,我们要选用一种不是==的方法,那就是equals()方法,看下面的具体实现,没毛病

     public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    

    但是不是所有的equals()方法都是比较内容,我们这边可以举个小小的反例

    class Value{
    	int i;
    }
    
    
    
    public class EqualsMethod2 {
    	public static void main(String[] args) {
    		Value v1 = new Value();
    		Value v2 = new Value();
    		v1.i = v2.i = 100;
    		System.out.println(v1.equals(v2));
    	}
    }
    

    输出结果是false,这是因为equals()的默认行为是比较引用,只是Java类库当中的许多类都已经自己实现了equals()方法,显然我们这边并没有重写这个equals()的方法,所以这边还是只是比较引用

    4.尝试使用字符串池的概念解释如下程序段输出结果,并回答这段代码创建了几个字符串对象:

    String str1 ="hi", str2="hi";
    String str3 = new String(str1);
    System.out.println(str1==str2);
    

    最后输出true
    分析在前面已经说过了,一共会有两个对象,str1创建的时候,字符串池里面会有一个,也就是str2直接指向字符串池中的那个实例。
    然后str3在字符串池外面又new了个

    5.Integer i = 100;//100是基本类型,i是引用类型,为什么可以将100赋值给i

    public class Main {
      public Main();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: bipush        100
           2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
           5: astore_1
           6: return
    }
    

    同样看到反汇编,我们就可以看到只是调用了Integer类的valueOf的方法而已,然后这个方法是public static Integer valueOf(int i)这样子的,返回一个Integer

    6.尝试分析下面代码输出结果

    Integer i1 = 127;Integer i2 = 127;
    i1 == i2;//true of false?
    Integer i1 = 128;Integer i2 = 128;
    i1 == i2;//true of false
    

    输出结果分别是truefalse
    上回我们刚刚谈到,我们用到了valueOf()这个方法,去给这个Integer进行赋值,so我们需要研究一下这个方法,贴上JDK源码。

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    

    !这是什么东西,对于不同的范围还区别对待?
    是这样的,这个IntegerCache,整数缓存是?再贴源代码(截取部分)

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
    

    好了,这样我们就知道了,这个IntegerCache是通过Cache数组来实现的,然后-128-127这256个数就被放在了这个数组里,当我valueOf()方法的参数在这个范围内的话,我就将数组中的值返回去,也就是说一开始i1和i2都指向了数组的同一位置,所以当然是相等的咯
    然后这个128就相当的尴尬了,因为他正好就在这个范围之外了,所以我们用最朴素的方法创建这个Integer对象,那么就像我们之前所说,通过new来创建的对象具有不同的引用,so传回了false

    7.package与javac、 java、 -classpath、 -d
    在 com.ibm包中编写 StringUtil类,内有一方法

    public static void foo1(){
     System.out.println(StringUtil.class+" method:foo1");
    }
    
    • 尝试用命令行进行编译并运行,截图使用javac -d. StringUtil.java使用-d编译选项,建立了相应的文件,将生成的字节码放在了comibm下面

    编写Main.java,在第一行加上package edu.jmu,编译后再次生成相应字节码文件
    然后再用java命令执行,结果如截图

    • 将生成的StringUtil.class放到d:lib正确的目录结构下,将Main.class在d: est正确的目录结构,尝试在命令行下运行,并截图。
      目录结构如下所示:
      • D
        • lib
          • com
            • ibm
              • StringUtil.class
        • test
          • edu
            • jmu
              • Main.class

    之前用powershell搞了很久,怼不出来。最后换成cmder就成功了

    • Eclipse中源代码放在哪个目录、class文件放在哪个目录。在Eclipse项目中按一下ctrl+f11就可以直接运行Main,尝试分析背后实现的原理

    源代码放在src里面,class放在bin文件夹中。

    8.自己在这门课的目标与计划

    • 请描述一下你的技术基础(会什么语言,都写了多少行代码)

      • C 有上万吗,可能有,可能没有吧
      • Matlab 上一千行,应该是有了
      • Python 上百行
    • 一周准备花多少时间在这门课上?一周准备写多少行代码?采用怎样的学习方式?遇到困难打算怎样解决?

      • 具体多长时间不清楚,毕竟还得顾着我的蓝桥杯
      • 一周写个一百多行什么的,还是可以的吧,具体的代码量同样还是不清楚
      • 遇到困难
        • 百度、谷歌……
        • 看书
        • 问老师
        • 放弃,我不搞了,开玩笑的
    • 关于这门课的smart目标
      首先这个是SMART

    S pecific:具体的,无二义性的,能描述 “成功” 是什么样的。
    M otivating: 目标能激发对目标的兴趣么?实现目标对学生来说说意味着什么?他们会为之自豪么?
    A chievable: 能做到么?是挟泰山以超北海?还是把墙角一堆砖头搬走?
    R elevant: 和学生来到大学的大方向、目标吻合
    T rackable: 能衡量进度的,和有些资料提到的 Measurable 相似。

    要不就姑且试试Java web?虽然别人说这都是套框架,可是我连框架都不会套……

    这让我想到职业规划的SWOT(S trengths, W eaknesses, O pportunities, T hreats)。那我就分门别类的说下吧。

    • 我觉得对于一门语言来说,怎么算是学成功了呢,应该就是能够使用这门语言真的做一件有实际用途的事情,可能主要是做开发之类的吧(现在还不是很清楚)
    • 分情况,假如我刚开始学编程的时候,会打printf("%d", a + b);我都会很开心。然而我们不可能总是停留在这个层次,我们总是需要向上走
    • 至于可行性,如果暂且把目标放的低一点,做一些简单功能的实现,我觉得还是可以的吧,不能一口吃成一个大胖子,也不能推得太慢吧。
    • 没什么大方向,也没什么具体的目标吧。很惭愧,感觉还是把现在的事情做好了再说。
    • 没试过啊,进度什么的先放着吧,要是凡事都能有个进度条就好了,很可惜并不是

    话再说回来,很想在这个学期继续打牢计算机以及数学基础。不然就可以直接去培训机构,三个月上岗,而不用来大学了

    9.选做:公交卡里应该还有多少钱?请分析原因

    -0.1(元)参考腾讯新闻
    可能是无符号浮点数下溢了。
    不过……
    新闻里说是这台闸机的问题,所以其他的闸机肯定是能正常显示的,那至于这个为什么不对,就不清楚了。

    3.使用码云管理Java代码


    4.PTA实验

    • 第一题,是函数调用,就是要注意需要sort的数组需要在循环输入选项的代码块外面就创建,如果在sort数组里面临时创建,当然其它选项是找不到的啦
    • 第二题,StringBuilder类的基本使用,就是一开始的时间限制压得很死,所以一会能A,一会又不能A。
    • 第三题,就是要自己去实现一下Comparator,然后就很流畅了
    • 第四题,for循环也可以,就是要一个二维数组,因为数据量不是很大,所以我是直接初始化了
    • 第五题,使用BigDecimal类来实现浮点数的精准计算,当然也可以用数组的方式来实现。不过既然有现成的,就用现成的好了
    • 第六题,枚举的基本使用
    • 第七题,可以用BigInteger实现的东西,就是学会用
    • 第八题,ArrayList的基本使用,相当于数据结构中提到的链表

    5.小任务

    代码有点丑陋……不过效果还行吧

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.PrintWriter;
    import java.util.Scanner;
    
    public class Main {
    	//用来找第一个不是空格的字符
    	private static int firstCharNotSpace(String string) {
    		int i;
    		for (i = 0; i < string.length(); i++) {
    			if (string.charAt(i) != ' ') {
    				break;
    			}
    		}
    		return i;
    	}
    	//如果是ABCD或是数字啥的,那么前面有空格就要删
    	private static Boolean needToDeleteSpace(char ch) {
    		if (Character.isDigit(ch) || ch >= 'A' && ch <= 'D') {
    			return true;
    		}
    		return false;
    	}
    	public static void main(String[] args) throws FileNotFoundException {
    		Scanner sc = new Scanner(new File("C:/Users/LJL36/Desktop/choice.txt"));
    	    PrintWriter printWriter = new PrintWriter("C:/Users/LJL36/Desktop/output.txt");
    	    int res = 0;//记录有多少道题目
    	    
    	    //这边很蠢的先统计了一下题目
    	    while (sc.hasNextLine()) {
    	    	String string = sc.nextLine();
    	    	if (string.trim().length() == 0) {
    	    		continue;
    	    	}
    	    	int index = firstCharNotSpace(string);
    	    	if (Character.isDigit(string.charAt(index))) {
    	    		res++;
    			}
    		}
    	    printWriter.println(res);
    	    
    	    //重新打开文件
    	    sc = new Scanner(new File("C:/Users/LJL36/Desktop/choice.txt"));
    	    while(sc.hasNextLine()){
    	    	StringBuilder stringBuilder = new StringBuilder(sc.nextLine());
    	    	String string = stringBuilder.toString();
    	    	//如果是空格串,就跳过
    	    	if (string.trim().length() == 0) {
    				continue;
    			}
    	    	//删空格
    	    	int index = firstCharNotSpace(string);
    	    	if (needToDeleteSpace(string.charAt(index))) {
    				stringBuilder.delete(0, index);
    			}
    	    	
    	    	//将答案在后面用pta要求格式输出
    	    	index = string.lastIndexOf('。');
    	    	if (index != -1 && index != string.length()) {
    	    		boolean flag = false;
    	    		String string2 = "@[";
    	    		for (int i = index + 1; i < string.length(); i++) {
    	    			if (Character.isLetter(string.charAt(i))) {
    	    				flag = true;
    						string2 += Character.toUpperCase(string.charAt(i));
    					}
    	    		}
    	    		string2 += "](2)";
    	    		
    	    		stringBuilder.delete(index + 1, string.length());
    	    		
    	    		if (flag) {
    	    			stringBuilder.append(string2);
    				}
    	    	}
    	    		
    	    	stringBuilder.append("  ");
    	    	printWriter.println(stringBuilder.toString());
    	    }
    	    sc.close();
    	    printWriter.close();
    	}
    }
    
    

    下面贴一下最后的运行结果

    看的不过瘾的请点下面
    回到顶部


    最后总是要说句废话什么的,有同学和我说我的排版太丑陋了。嗯……我只能顾上眼前的苟且了,非常感谢偷偷看我博客的同学,可是能不能粉我一下,我也会回粉你们的,谢谢~

  • 相关阅读:
    第六周作业
    第五周作业
    2019春第四周作业软件
    2019年春季学期第三周作业
    2019年春季学期第二周作业(文件指针)
    7-2 求最大值及其下标 (20 分)
    7-1 查找整数 (10 分)
    7-1 抓老鼠啊~亏了还是赚了? (20 分)
    秋季学期学习总结
    第6周作业
  • 原文地址:https://www.cnblogs.com/ljl36/p/6492118.html
Copyright © 2011-2022 走看看