您的位置:首页 > 职场人生

黑马程序员---java学习笔记之面向对象知识点2

2013-12-13 11:39 906 查看
------- android培训java培训、期待与您交流! ----------

1、关于主函数

a):main不是关键字,但是是特殊的单词,可以被jvm识别;

b):某个类中可以存在main的重载函数,比如说public static void main(int x)等等,但是jvm只能识别一种形式(public static void main(String[] args)),作为程序的入口;

c):主函数中参数变量名args是可以改变的,比如说public static void main(String[] a)也是可以的;

d):可以向主函数传递参数的,如果没有传入,虚拟机默认传给main函数的参数时 new String[0],传递参数在dos窗口下以及myeclipse下都可以设置;

e):主函数可以被调用,示例如下:

public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] arr = {"hello","hi","good","bad"};
MainTest2.main(arr);
}

}
class MainTest2
{
public static void main(String[] args)
{
for( int i = 0; i < args.length; i++ )
System.out.println(args[i]);
}
}


运行结果如下:



2、什么时候使用静态成员?

静态变量,当对象遇到共享数据时,该数据的属性应设置为静态的;

静态函数,当类中的某方法并没有访问到该类中的非静态成员时,该函数应定义成静态的。

3、静态的应用----工具类

工具类,没有该类对象的特有数据可操作,为了调用简单,将该类中所有函数设置为静态可访问的,并将其构造函数设置为private的。

4、默认构造函数的小知识点:

默认构造函数的权限修饰符与其类相一致。

5、下面是我模仿视频中的代码做的一个java api文档

/**
* 这是一个处理数组的工具类,功能主要有获取最值,排序,打印输出等
* @author 张三
* @version 1.0
*/
public class ArrayTool
{
/**
* 私有化的空参数构造函数
*/
private ArrayTool()
{
}

/**
* 获取数组中元素的最大值
* @param arr 传入一个int型数组
* @return 返回一个最大的元素值
*/
public static int getMax(int[] arr)
{
int max = arr[0];
for( int i = 1; i < arr.length; i++ )
if( max < arr[i] )
max = arr[i];
return max;
}
/**
* 获取数组中元素的最大值
* @param arr 传入一个int型数组
* @return 返回一个最大的元素值
*/

public static int getMin(int[] arr)
{
int min = arr[0];
for( int i = 1; i < arr.length; i++ )
if( min > arr[i] )
min = arr[i];
return min;
}

/**
* 对数组进行选择排序
* @param arr 传入一个int型数组
*/
public static void selectSort(int[] arr)
{
for( int i = 0; i < arr.length; i++ )
for( int j = i + 1; j < arr.length; j++ )
if( arr[i] > arr[j] )
swap(arr,i,j);
}
/**
* 对数组进行冒泡排序
* @param arr 传入一个int型数组
*/
public static void bubbleSort(int[] arr)
{
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] )
swap(arr,j,j+1);
}
/**
*交换数组中的两个元素
@param arr 传入一个int型的数组
@param 元素1的下标
@param 元素2的下标
*/
private static void swap(int[] arr, int i, int j)
{
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
/**
* 打印输出数组的所有元素,打印的格式为[element1,element2,elenmet3,element4……].
* @param arr 传入一个int型数组
*/
public static void printArray(int[] arr)
{
System.out.print("["+arr[0]);
for( int i = 1; i < arr.length; i++ )
if( i != arr.length-1 )
System.out.print(","+arr[i]);
else
System.out.println("]");

}
/*public static void main(String[] args)
{
int[] arr = {75,59,68,25,64,113,103,97};
System.out.println(getMax(arr));
System.out.println(getMin(arr));
//selectSort(arr);
bubbleSort(arr);
printArray(arr);

}*/
}


6、静态代码块

a):随着类的加载而加载,只执行一次,下面是示例:

class StaticCode{
static
{
System.out.println("abc");
}
}

public class StaticDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub
new StaticCode();
new StaticCode();

}

}
运行结果只有一个“abc”

虽然在主函数里面创建了两个StaticCode的对象,但是输出时只有一个“abc”输出,也就是说某个类加载时执行一次静态代码块,加载之后再用这个类创建对象时就不在执行静态代码块了,这就是说“静态代码块随着类的加载而加载,并且只执行一次”。

b):如果一个函数中含有静态代码块和主函数,运行时,静态代码块优先于主函数执行

public class StaticDemo {

static
{
System.out.println("a");
}

public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("c");

}
static
{
System.out.println("b");
}

}


运行的结果是:



由此可知静态代码块优先于主函数执行。

c):静态代码块给类作初始化,构造代码块给该类的所有对象初始化,构造函数给相应的对象作初始化

7、什么时候才把一个类加载进内存呢?

当调用到某类的成员时,就会把该类加载进内存。比如说,new一个该类的对象时,因为要调用该类的某一个构造函数,所以会把该函数加载进内存;在比如说,调用该类的某个静态方法时,也会将该类加载进内存。另外需要注意的是,只声明某一个类的引用,java虚拟机是不会把该类加载进内存的。示例如下:

class StaticCode{
static
{
System.out.println("abc");
}
}
public class StaticDemo {

public static void main(String[] args){
StaticCode s = null;

}

}


这是没有运行结果的!因为只是声明某类的引用,而没有具体调用该类的成员,所以静态代码块是不会执行的!

8、对象初始化过程

结合一个具体的代码来说明这个过程,以下是代码:

public class Person {

private int age;
private String name;
static String nationality = "cn";

static
{
show();
}

public static void show()
{
System.out.println(nationality);
}

{
System.out.println("a");
}

public Person(int age)
{
this.age = age;
}

public Person(int age,String name)
{
this.age = age;
this.name = name;
System.out.println("age = "+age+",name = "+name);
}

public static void main(String[] args) {

Person p2 = new Person(16,"zhangsan");
}

}


运行结果为:



a):将java源程序编译出.class文件,当运行该.class文件时,系统会产生一个java进程,并且为该进程分配了内存空间(即堆、栈、方法区、本地方法区等),然后该文件被java虚拟机加载进分配的方法区内存;

b):随着该类的加载,该类中的静态成员 (静态属性nationality和静态方法show) 就可以被访问,静态代码块就会执行,所以“cn”最先被输出;

c):接着,java虚拟机就会找到该类的主函数(找不到就报错!注意,一个没有主函数的类是可以编译通过的,但是该类运行时就会报错!),然后开始执行主函数的语句;

d):当读到创建对象那行代码"Person p2 = new Person(16,"zhangsan");",java虚拟机就会在栈中为Person型的引用p2开辟内存空间,然后在堆中创建对象实体;

e):对堆中对象实体的非静态变量进行默认初始化;

f):对堆中对象实体的非静态变量进行显式初始化;

g):然后一次执行构造代码块和构造函数对该对象进行进一步的初始化,所以一次会输出“a”、“age = 16,name = zhangsan”;

h):将该对象的地址复制给引用p2.

9、单例设计模式

单例设计模式三要素的代码体现:

private static Single s = new Single();

private Single()
{}

public static Single getInstance()
{
return s;
}
静态且私有的唯一实例s,私有化的构造函数,以及静态公有的获取单例引用的函数,上述为饿汉式的单例设计模式

还有一种是懒汉式的单例设计模式:

private static Single s = null;

private Single()
{}

public static Single getInstance()
{
if( s == null )
s = new Single();
return s;
}
懒汉式的单例设计模式是有安全隐患的,所以一般开发用的是饿汉式的单例设计模式。懒汉式的安全隐患是,在多个线程同时调用getInstance时,容易出现!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: