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

------- 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时,容易出现!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值