Java 取经之路

记录在java学习和编程过程中的遇到的问题和心得



【1.报错 】
java.lang.NoSuchMethodError: oracle.i18n.text.converter.CharacterConverterOGS.getInstance(I)Loracle/sql/converter/CharacterConverters;
发生状态:运行导入的项目,数据导入的是oracle 10g版本中,
解决办法:orai18n.jar包是oracle11g才有的,oracle11g之前的jar不叫orai18n.jar,而是nls_charset12.jar。所以在oracle数据库的安装目录下的\jdbc\lib\nls_charset12.jar 拷贝到本项目包中,剔除掉orai18n.jar包。
nls_charset12.jar下载链接


【2 eclipse debug时日志输出自动保存log】
    经常会遇到这种情况,习惯性的清掉控制台上的输出日志,再然后发现刚才的日志居然还有用,不得不又重新调试一遍,为了解决这种“手贱”的问题,我在网上搜了一些资料,还真解决的方法哈,只需要把日志同时输出到设定一个文件就行。方法如下:
    设置Eclipse保存控制台文件。右键项目 -> Debug As -> Debug Configurations菜单。 进入Common标签下,设置“Standard Input and Output”, 勾选 “File:”, 填写输出文件路径及文件名。如果你勾选了“Append”,输出的日志将会被追加写入到文件最后,否则将会覆盖重写文件。
这里写图片描述


【3 java生成指定位数的随机数】

float Max = 25, Min = 3.0f;  
BigDecimal db = new BigDecimal(Math.random() * (Max - Min) + Min);  
System.out.println(db.setScale(2,BigDecimal.ROUND_HALF_UP).toString());  // 保留2位小数并四舍五入   
db.setScale(2, BigDecimal.ROUND_HALF_UP); 
db.doubleValue();

【4 Java中的编码 】
    在Java中字符只以一种形式存在,那就是Unicode(不选择任何特定的编码,直接使用它们在字符集中的编码,这是统一的唯一方法。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求)
    但“Java中”到底指的是在哪里?是指在JVM中、在内存中、在你的代码里声明的每一个char、String类型的变量中。
    JVM 的这种约定使得一个字符分为两部分:JVM内部和OS的文件系统。在JVM内部,统一使用U你冲的表示,当这个字符被从JVM内部移到外部(即保存为文件系统中的一个文件的内容时)就进行编码转换,使用了具体的编码方案。因此可以说所有的编码转换只发生在边界的地方,JVM和OS的交界处,也就是各种输入/输出流(或者Reader、Writer类)起作用的地方。


【5 Java中自加自减运算++、–】
注意:
(1)自增运算符和自减运算符只能用于变量,而不能用于常量或表达式,如5++或(a+b)++都是不合法的。应为5是常量,常量的值不能改变。(a+b)++也不可能实现,假如a+b的值为5,那么自增后得到的6放到什么地方呢?无变量可供存放!
(2) ++和–的结合方向是“自右向左”(可以参考C语言运算符和结合性表)。一般情况下算数运算符的结合方向为“自左向右”,如果有-i++,i的左面是负号运算符,右面是自加运算符。如果i的原值等于3,若按照左结合性,相当于(-i)++,而(-i)++是不合法的,应为对表达式不能进行自加自减运算。
如果有printf(“%d”,-i++);,则先取出i的值3,输出-i的值-3,然后i增加为4。
注意-(i++)是先用i的原值3加上负号输出-3,再对i加1,不要认为先加完1后再加负号,输出-4,这是不对的。
(3) 自增(减)运算符常用于循环语句中,使循环变量自动加1;也用于指针变量,使指针变量指向下一个内存地址。更多见关于自增自减运算符的一些问题

例题

public static void main(String[] args) {
    int j=0;
    for(int i=0;i<100;i++)
        j=j++;
    System.out.println(j);//输出结果为0;
}

不仔细点很容易认为结果是100,关键在第四行代码j=j++;j=(j++),分两步,第一步执行(j++),第二步执行=的赋值运算,将右边的值再次赋值给j。
对于第一步,j++返回值为j的原始值(旧值)即0,但此时的j进行了+1变为了1;对于第二部,又重新对j进行了赋值,将j++的返回值0赋值给了j,所以j还是0。更多见Java中的中间缓存变量机制怎么理解?


【6 Java中常量问题】
十六进制整型常量:以十六进制表示时,需以0x或0X开头,如0xff,0X9A。
八进制整型常量:八进制必须以0开头,如0123,034。
长整型:长整型必须以L作结尾,如9L,342L。
浮点数常量:由于小数常量的默认类型是double型,所以float类型的后面一定要加f(F)。同样带小数的变量默认为double类型。

如:float f;

 f=1.3f;//必须加上f。

字符常量:字符型常量需用两个单引号括起来(注意字符串常量是用两个双引号括起来)。Java中的字符占两个字节。一些常用的转义字符:

①\r表示接受键盘输入,相当于按下了回车键;
②\n表示换行;
③\t表示制表符,相当于Table键;
④\b表示退格键,相当于Back Space键;
⑤\'表示单引号;
⑥\''表示双引号;
⑦\\表示一个斜杠\。

【7 Java 长整型】
MICROS_PER_DAY表示一天的微秒数
MILLIS_PER_DAY表示一天的毫秒数
然后下面例子的结果是多少呢?

public class Test3 {
    public static void main(String[] args) {
        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
    }
}

So easy
数据类型为 long ,很容易保存这两个乘积不产生溢出.
因此,结果肯定是 1000!
but…..
结果是: 5
这里写图片描述

解释:
为什么答案与我们想象不一样呢?
因为数据溢出了…
你在逗我? 但我没学过java?
long能表示 -2的63次方到2的63次方-1的整数.
数都数不过来,怎么会溢出?
哈哈,小心陷阱啊,虽然我们定义的是long类型,
准确的说最终的结果应该是long类型的.

我们看看表达式右边,
24 * 60 * 60 * 1000 * 1000
这个表达式是以int类型作为运算的,
int跟int类型相乘,结果还是int类型,
最终结果超过int所能保存的范围,所以数据溢出了,
然后才被long所保存;

改进

24 * 60 * 60 * 1000 * 1000–>24L * 60 * 60 * 1000 * 1000

在表达式随便哪个数值后面加上一个l或者L就搞定了,
其结果会自动转换为long而不是int了,然后再保存到long类型变量中.
就是这么简单,就是这么任性。


【8 Java 的控制台输入】
System.in
Scanner

System.in.read()一次只读入一个字节数据,而我们通常要取得一个字符串或一组数字
System.in.read()返回一个整数
Scanner 可以取得一个字符串或一组数字
Scanner默认使用Whitespace(即空白字符[空格,TAB和回车])作为结束符。

Scanner oin=new Scanner(System.in);
String  string=oin.next();

/*delimiter()返回此 Scanner当前正在用于匹配分隔符的 Pattern
默认分隔符输出为'\p{javaWhitespace}+'
等效于 java.lang.Character.isWhitespace()*/

System.out.println(oin.delimiter());
oin.useDelimiter(" |,|\\.");//指定 新的分隔符
System.out.println(oin.delimiter());

/*在新增一个Scanner对象时需要一个System.in对象,
因为实际上还是System.in在取得用户输入。
Scanner的next()方法用以取得用户输入的字符串;
nextInt()将取得的输入字符串转换为整数类型;
同样,nextFloat()转换成浮点型;
nextBoolean()转换成布尔型。*/

更过分析见
①java 中的Scanner(非常详细不看后悔)
②Scanner JavaAPI
③java 标准输入System.in
④Java中从控制台输入数据的几种常用方法


【9 Java反射,参数为数组】

class A{
    private void sayHello(String[] names){
        //...
        System.out.println("sayHello invoked");
    } 
}

String[] names = new String[]{"A", "B", "C"};
Method sayHello = A.class.getDeclaredMethod("sayHello", String[].class);
sayHello.setAcess(true);
sayHello.invoke(new A(), new Object[]{names});

这里有两个地方需要注意

1.A.class.getDeclaredMethod时后面的参数是数组,用加[];
2.sayHello.invoke调用时直接传一个String[]实例会报异常,需要再次用Object[]包装一下;


【10 Scanner类nextInt之后用nextLine无法读取输入】
问题描述:做搜狐笔试一道编程题时,输入是首先一整数n占一行,接着n行字符串如下:

3
hello
your 
my

首先,Scanner是一个扫描器,它扫描数据都是去内存中一块缓冲区中进行扫描并读入数据的,而我们在控制台中输入的数据也都是被先存入缓冲区中等待扫描器的扫描读取。这个扫描器在扫描过程中判断停止的依据就是“空白符”,空格啊,回车啊什么的都算做是空白符。
nextInt()方法在扫描到空白符的时候会将前面的数据读取走,但会丢下空白符“\r”在缓冲区中,但是,nextLine()方法在扫描的时候会将扫描到的空白符一同清理掉。
了解了这两个方法特性和区别,就知道了上边的代码究竟是怎么回事,以及知道了解决的方法。像是上边的代码nextInt()方法之后在缓冲区中留下了“\r”,然后nextLine()方法再去缓冲区找数据的时候首先看到了“\r”,然后就把这个“\r”扫描接收进来,并在缓冲区内清除掉。
解决办法:
1.可以再nextInt()方法后面多加一句nextLine()方法专门用来取出缓冲区中留下的空白符
2.可以只用nextLine()方法,然后通过Integer类中的parseInt()方法解析成int数据。因为nextLine()方法会自动清理掉后边的空白符。
更多详细见
java中Scanner类nextInt之后用nextLine无法读取输入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Casionx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值