一、java一些关键字的含义与举例
1、native:此关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。
可以将native方法比作Java程序同C程序的接口,其实现步骤:
1、在Java中声明native()方法,然后编译。
2、用javah产生一个.h文件。
3、写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件)。
4、将第三步的.cpp文件编译成动态链接库文件。
5、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。
JAVA的native方法适用的情况:
1、为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问。
2、为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的。
3、为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现。
链接:为什么要用Java native
java native代码举例:
public interface TestInterface {
void doMethod();
}
public class Test implements TestInterface {
public native void doMethod();
private native int doMethodB();
public native synchronized String doMethodC();
static native void doMethodD();
}
2、strictfp:本关键字可应用于类、接口或方法。使用 strictfp 关键字声明一个方法时,该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合IEEE-754规范。当对一个类或接口使用 strictfp 关键字时,该类中的所有代码,包括嵌套类型中的初始设定值和代码,都将严格地进行计算。严格约束意味着所有表达式的结果都必须是 IEEE 754 算法对操作数预期的结果,以单精度和双精度格式表示。
如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp.
示例 1
下面的示例演示了一个使用 strictfp 修饰符声明的类:
public strictfp class MyClass {
public static void main(String[] args)
{
float aFloat = 0.6710339f;
double aDouble = 0.04150553411984792d;
double sum = aFloat + aDouble;
float quotient = (float)(aFloat / aDouble);
System.out.println("float: " + aFloat);
System.out.println("double: " + aDouble);
System.out.println("sum: " + sum);
System.out.println("quotient: " + quotient);
}
}
// Example of precision control with strictfp
public strictfp class MyClass {
public static void main(String[] args)
{
float aFloat = 0.6710339f;
double aDouble = 0.04150553411984792d;
double sum = aFloat + aDouble;
float quotient = (float)(aFloat / aDouble);
System.out.println("float: " + aFloat);
System.out.println("double: " + aDouble);
System.out.println("sum: " + sum);
System.out.println("quotient: " + quotient);
}
}
运行结果:
float: 0.6710339
double: 0.04150553411984792
sum: 0.7125394529774224
quotient: 16.1673363、 Volatile :Java 语言提供了一种稍弱的同步机制,即 volatile 变量.用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新. 当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的.
参考链接:
Java并发编程:volatile关键字解析
java中volatile关键字的含义4、Synchroize:多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。同步机制可以使用synchronized关键字实现。
当synchronized关键字修饰一个方法的时候,该方法叫做同步方法。
当synchronized方法执行完或发生异常时,会自动释放锁。
它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
/**
* synchronized的用法举例:
* 同步线程
*/
class SyncThread implements Runnable {
private static int count;
public SyncThread() {
count = 0;
}
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (count++));
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public int getCount() {
return count;
}
}
SyncThread的调用:
SyncThread syncThread = new SyncThread();
Thread thread1 = new Thread(syncThread, "SyncThread1");
Thread thread2 = new Thread(syncThread, "SyncThread2");
thread1.start();
thread2.start();
结果如下:
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
SyncThread2:5
SyncThread2:6
SyncThread2:7
SyncThread2:8
SyncThread2:9
当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。Thread1和thread2是互斥的,因为在执行synchronized代码块时会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象。
二、Java 基本数据类型与引用数据类型
基本数据类型:
byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0
int:整型,用于存储整数,在内在中占32位,即4个字节,取值范围-2147483648~2147483647,默认值 0
long:长整型,在内存中占64位,即8个字节-2^63~2^63-1,默认值0L
float:浮点型,在内存中占32位,即4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0
double:双精度浮点型,用于存储带有小数点的数字,在内存中占64位,即8个字节,默认值0
boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false
/*代码实例*/
public class TestInit {
boolean boo;
char cha;
byte by;
short shor;
int in;
float flo;
long lon;
double dou;
String str;
@Test
public void aa() {
System.err.println("boolean:" + boo);
if (cha == '\u0000') {
System.err.println("char:" + (int) cha);
System.err.println(cha);
}
System.err.println("byte:" + by);
System.err.println("short:" + shor);
System.err.println("int:" + in);
System.err.println("long:" + lon);
System.err.println("float:" + flo);
System.err.println("double:" + dou);
System.err.println("String:" + str);
}
}
测试结果:
boolean:false
char:0
byte:0
short:0
int:0
long:0
float:0.0
double:0.0
String:null
三、Java值传递、引用传递、副本传递的区别
1、按值传递是什么?
指的是在方法调用时,传递的参数是按值的拷贝传递。按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了.
实例:
`public class TempTest {
private void test1(int a){
a = 5;
System.out.println("test1方法中的a="+a);
}
public static void main(String[] args) {
TempTest t = new TempTest();
int a = 3;
t.test1(a);//传递后,test1方法对变量值的改变不影响这里的a
System.out.println(”main方法中的a=”+a);
}
}
运行结果:
test1方法中的a=5
main方法中的a=3
2、按引用传递是什么?
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
public class TempTest {
private void test1(A a){
a.age = 20;
System.out.println("test1方法中的age="+a.age);
}
public static void main(String[] args) {
TempTest t = new TempTest();
A a = new A();
a.age = 10;
t.test1(a);
System.out.println(”main方法中的age=”+a.age);
}
}
class A{
public int age = 0;
}
运行结果:
test1方法中的age=20
main方法中的age=20
相关参考博文:
Java:按值传递还是按引用传递详细解说
JAVA 值传递(副本传递)的理解
四、java实现快速排序算法
public class QuickSort {
public static void main(String[] args) {
int[] array = {12,15,85,65,32,78,68,32,45,78};//定义一个待排序数组
quickSort(array,0,9);
System.out.println(array);
}
public static void quickSort(int[] array,int low,int high){
if (low < high) {
int left = low;
int right = high;
int key = array[low];
while(left < right){
while(left < right && array[right] >= key )//从右向左找到第一个小于key的数字
right --;
if(left < right)
array[left ++] = array[right];
while(left < right && array[left] <= key)//从左向右找到第一个大于key的数
left ++;
if (left < right)
array[right --] = left;
}
array[left] = key;
quickSort(array,low,left-1);//开始递归调用
quickSort(array,high,right + 1);
}
}
}
六、定义多个对象,使用不同的比较方法
java中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。
//代码实例
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = "Monday";
if (s1 == s2)
{
System.out.println("s1 == s2");}
else{
System.out.println("s1 != s2");}
}
}
编译并运行程序,输出:s1 == s2说明:s1 与 s2 引用同一个 String 对象 – “Monday”!
2.再稍微改动一下程序,会有更奇怪的发现:
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
if (s1 == s2){
System.out.println("s1 == s2");
}
else{
System.out.println("s1 != s2");
}
if (s1.equals(s2)) {System.out.println("s1 equals s2");}
else{
System.out.println("s1 not equals s2");
}
}
}
我们将s2用new操作符创建
程序输出:
s1 != s2
s1 equals s2
说明:s1 s2分别引用了两个”Monday”String对象
参考链接:Java中equals和==的区别
浅谈Java中的equals和==
七、Java中的开关语句Switch
“开关”(Switch)有时也被划分为一种“选择语句”。根据一个整数表达式的值,switch语句可从一系列
代码选出一段执行。它的格式如下:
switch(整数选择因子) {
case 整数值1 : 语句; break;
case 整数值2 : 语句; break;
case 整数值3 : 语句; break;
case 整数值4 : 语句; break;
case 整数值5 : 语句; break;
//..
default:语句;
}
八、java增强循环
For-Each循环
For-Each循环也叫增强型的for循环,或者叫foreach循环。
For-Each循环是JDK5.0的新特性(其他新特性比如泛型、自动装箱等)。
For-Each循环的加入简化了集合的遍历。
其语法如下:
for(type element: array) {
System.out.println(element);
}
/*增强循环实例*/
public class ForeachTest {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7,8,9};
System.out.println("----------旧方式遍历------------");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
System.out.println("---------增强循环遍历-------------");
for (int i : array) {
System.out.print(i + " ");
}
System.out.println();
//二维数组遍历
System.out.println("---------增强循环遍历二维数组-------------");
int[][] array1 = {{11,22,33},{44,55,66},{77,88,99}};
for (int[] is : array1) {
for (int i : is) {
System.out.print(i + " ");
}
}
System.out.println();
}
}
运行结果:
----------旧方式遍历------------
1 2 3 4 5 6 7 8 9
---------增强循环遍历-------------
1 2 3 4 5 6 7 8 9
---------增强循环遍历二维数组-------------
11 22 33 44 55 66 77 88 99
总结
上面所有说的知识点应该都是比较基础的,知识点也说的比较乱,从关键字一下子跳到了基本类型与引用类型,没有什么系统性的排版,但是这都是布置作业,作为学生也是没有什么办法的,只得照做,看到的就当时为自己查缺补漏吧,知识点也比较多,篇幅也比较长,自己的大家能耐心看就看下去,如果是针对某个知识点大家还是直接百度或Google来的更加直接些。
知识点虽然比较基础的,但是对于我们初学者来说都是比较容易混淆的,比如== 和equals,都是傻傻分不清楚的。还有就是关于Arrays类中国的sort方法,看到有博文说在jdk1.5的时候,如果是基本类型比较,且数组长度小于7的话调用的就是插入排序,长度大于7就会调用快速排序,如果是引用类型的比较就是调用的归并排序,但是我这里JDK的版本是1.8的,查看源码时看到的都是调用的快速排序,自己由于也是初学者,所以也有点不清楚,待我与老师探讨探讨,得出结论在来确认修改,我们这里暂且默认为都是快速排序,毕竟源码摆在这里,也没有1.5版本的源码可查。