【黑马程序员】Java学习笔记之面向对象高级篇
来源:互联网 发布:淘宝促销词语 编辑:程序博客网 时间:2024/06/07 13:06
面向对象高级篇
一、static关键字
1.定义
static关键字:用于修饰成员(成员变量和成员函数)。
2.特点
被修饰后的成员具备以下特点:
1、随着类的加载而加载。(也就是说,静态成员会随着类的消失而消失,说明它的生命周期最长)
2、优先于对象存在。
3、被所有对象所共享。(节省内存空间的使用)
4、可以直接被类名调用。(使用方式:类名.静态成员 例如:Person.country)
PS:不建议定义过多的静态变量,被所有对象所共享的变量定义成静态,其他不建议定义成静态。
示例:
class Person{ //成员变量,实例变量 String name; //静态变量,类变量 //所有对象共享的属性用static修饰 static String country = "CN"; public void show(){ System.out.println(country + ":" + name); //等效语句:System.out.println(Person.country + ":" + this.name); }}class StaticDemo{ public static void main(String[] args){ Person p = new Person(); System.out.println(p.country); //可以用类名直接调用 System.out.println(Person.country); }}
运行结果:CNCN
3.区别
成员变量和静态变量的区别?
1. 两个变量的生命周期不同
成员变量(实例变量)随着对象的创建而存在,随着对象被回收而释放。
静态变量(类变量)随着类的加载而存在,随着类的消失而消失。
2. 调用方式不同
成员变量(实例变量)只能被对象调用。
静态变量(类变量)可以被对象调用,还可以被类名调用。
3. 别名不同
成员变量也称为实例变量。
静态变量也称为类变量。
4. 数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
4.注意事项
使用注意:
1. 静态方法只能访问静态成员(变量和方法),如果访问非静态成员,就会报错!
原因:静态方法和变量存在的时候,对象还不存在,非静态变量也不存在,肯定无法访问。
示例:
class Person{ String name; static String country = "CN"; //静态方法 public static void show(){ System.out.println(country + ":" + name); }}
运行结果:报错:无法从静态上下文中引用非静态 变量 name
P.S.
非静态方法既可以访问静态成员,又可以访问非静态成员。
2、静态方法中不可以写this,super关键字。
原因:静态方法存在的时候,对象还不存在,this代表的就是调用方法的那个对象,既然不存在,肯定不可以写在静态方法中。
3、主函数是静态的,主函数特殊之处:
1. 格式是固定的。
2. 被jvm所识别和调用。
二、主函数:
1、定义
public static void main(String[] args){}
2、主函数各成分解析
public:权限必须是最大的,被jvm调用。
static:不需要对象调用,直接用主函数所属类名调用即可。 命令行窗口中输入:java StaticDemo,实际上就是在执行StaticDemo.main();。
void:主函数不需要具体的返回值。
main:函数名,不是关键字,只是一个jvm识别的固定的名字。
String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
示例:
class MainDemo{ public static void main(String[] args){ for(int x = 0; x < args.length; x++){ System.out.println(args[x]); } }}
运行结果:
三、什么时候使用静态?
1、什么时候定义静态变量
a.当分析对象中所具备的成员变量的值都是相同时,这时这个成员就可以被静态修饰。
b.只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。
c.如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态的。
2、什么时候定义静态函数
a. 函数是否用静态修饰,就参考一点,就是该函数功能是否需要访问到对象中的特有数据(对象的特有数据也叫非静态数据、非静态成员)。
b.简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。
c.如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用。
d.如果没有访问特有数据的方法,该对象的创建是没有意义。
示例:
class Demo{ int age ; static int num = 9; public static void speak(){ System.out.println(num); } public void show(){ System.out.println(age); }}class StaticDemo{ public static void main(String[] args){ Demo.speak(); new Demo().show(); }}
运行结果:90
3、静态的应用:每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用。
以数组工具类的操作使用为例,代码如下:
public class ArrayTool{ //该类中的方法都是静态的,所以该类是不需要创造对象的 //为了保证不让他人创建该类对象,可以将构造函数私有化 private ArrayTool(){} //获取整型数组的最大值 public static int getMax(int[] arr){ int maxIndex = 0; for(int x = 1; x < arr.length; x++){ if(arr[x] > arr[maxIndex]) maxIndex = x; } return arr[maxIndex]; } //对数组进行选择排序 public static void selectSort(int[] arr){ for(int x = 0; x <arr.length -1; x++){ for(int y = x + 1; y < arr.length; y++){ if(arr[x] > arr[y]) swap(arr,x,y); } } } //用于给数组进行元素的位置置换。 private static void swap(int[] arr, int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //获取指定的元素在指定数组中的索引 public static int getIndex(int[] arr, int key){ for(int x = 0; x < arr.length; x++){ if(arr[x] == key) return x; } return -1; } //将int 数组转换成字符串,格式是:[e1,e2,...] public static String arrayToString(int[] arr){ String str = "["; for(int x = 0; x < arr.length; x++){ if(x != arr.length - 1) str = str + arr[x] + ","; else str = str + arr[x] + "]"; } return str; }}class ArrayToolDemo{ //保证程序的独立运行 public static void main(String[] args){ int[] arr = {4,8,2,9,7,82,6}; int max = ArrayTool.getMax(arr); System.out.println("max = " + max); int index = ArrayTool.getIndex(arr,10); System.out.println("index = " + index); }}
运行结果:max=82index=-1
四、文档注释
1、格式
/**
注释内容
*/
2.示例
/*** 建立一个用于操作数组的工具类,其中包含着常见的对数组操作的函数,如:最值,排序等。* @author 哈哈小云* @version v1.0*/public class ArrayTool{ private ArrayTool(){} /** * 获取整型数组的最大值 * @param arr 接收一个元素为int 类型的数组 * @Return 该数组的最大的元素值 */ public static int getMax(int[] arr){ int maxIndex = 0; for(int x = 1; x < arr.length; x++){ if(arr[x] > arr[maxIndex]) maxIndex = x; } return arr[maxIndex]; } /** * 对数组进行选择排序 * @param arr 接收一个元素为int 的数组 */ public static void selectSort(int[] arr){ for(int x = 0; x <arr.length -1; x++){ for(int y = x + 1; y < arr.length; y++){ if(arr[x] > arr[y]) swap(arr,x,y); } } } //用于给数组进行元素的位置置换。 private static void swap(int[] arr, int a,int b){ int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /** * 获取指定的元素在指定数组中的索引 * @param arr 接收一个元素为int 类型的数组 * @param key 要找的元素 * @return 返回该元素第一次出现的位置,如果不存在则返回 -1 */ public static int getIndex(int[] arr, int key){ for(int x = 0; x < arr.length; x++){ if(arr[x] == key) return x; } return -1; } /** * 将int数组转换成字符串,格式是:[e1,e2,...] * @param arr 接收一个元素为int类型的数组 * @return 返回该数组的字符串表现形式 */ public static String arrayToString(int[] arr){ String str = "["; for(int x = 0; x < arr.length; x++){ if(x != arr.length - 1) str = str + arr[x] + ","; else str = str + arr[x] + "]"; } return str; }}
运行结果:
P.S.
1、如果想把一个类进行文档化,该类必须是public的。
2、私有的方法在文档中不会体现,例如ArrayTool类中的swap方法。
五、静态代码块
1.格式
static
{
静态代码块中的执行语句
}
2.特点:随着类的加载而执行,而且只执行一次。并优先于主函数执行
3.作用:用于给类进行初始化。
4.示例:
class StaticCode{ static{ System.out.println("a"); }}class StaticCodeDemo{ static { System.out.println("b"); } public static void main(String[] args){ new StaticCode(); new StaticCode(); System.out.println("over"); } static { System.out.println("c"); }}
运行结果:b c a over
4.区别:构造代码块作用:可以给所有对象进行初始化。
六、单例设计模式
1.定义
设计模式:对问题行之有效的解决方式,其实,它是一种思想。
单例设计模式解决的问题:就是可以保证一个类在内存中的对象唯一性。 比如多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
2.对象唯一性
如何保证对象唯一性呢?
1、不允许其他程序用new创建该类对象。
2、在该类创建一个本类实例。
3、对外提供一个方法让其他程序可以获取该对象。
3.操作步骤:
1、私有化该类构造函数。
2、通过new在本类中创建一个本类对象。
3、定义一个公有的方法,将创建的对象返回。
示例(饿汉式):
class Single{ //类已加载,对象就已经存在了 private static Single s = new Single(); private Single(){} public static Single getInstance(){ return s ; }}class SingleDemo{ public static void main(String[] args){ Single s1 = Single.getInstance(); Single s2 = Single. getInstance(); System.out.println(s1 == s2); }}
运行结果:true
P.S.
之所以不用Single.s;的方式获取Single对象,而采用getInstance获取是因为在getInstance方法中我们可以做一些判断来决定是否返回Single的对象,也就是实现了对单例对象的可控。所以,给Single的构造方法加上了private限制,禁止使用者直接采用Single.s;的方式获取。
示例(懒汉式):
class Single{ //类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象 //延迟加载形式 private static Single s = null; private Single(){} public static Single getInstance(){ if(s == null) s = new Single(); return s ; }}class SingleDemo{ public static void main(String[] args){ Single s1 = Single. getInstance(); Single s2 = Single. getInstance(); System.out.println(s1 == s2); }}
运行结果:true
- 【黑马程序员】Java学习笔记之面向对象高级篇
- 【黑马程序员】Java学习笔记之面向对象基础篇
- 黑马程序员---java学习笔记之面向对象知识点
- 黑马程序员---java学习笔记之面向对象知识点2
- 黑马程序员---java学习笔记之面向对象:继承
- 黑马程序员---java学习笔记之面向对象:接口
- 黑马程序员—Java基础学习笔记之面向对象
- 黑马程序员 java编程之面向对象学习笔记
- 黑马程序员 java编程之面向对象学习笔记总结
- 【黑马程序员】 学习笔记 - Java面向对象
- 黑马程序员-java学习之面向对象
- 黑马程序员---Java基础学习笔记(面向对象篇)
- 黑马程序员-Java学习笔记之面向对象(多态 在上一篇笔记中)
- 黑马程序员之C#学习笔记:面向对象小结
- 黑马程序员之C#学习笔记:面向对象
- 黑马程序员——面向对象之继承学习笔记
- 黑马程序员学习笔记_OC之面向对象思想
- 黑马程序员-学习笔记java基础-面向对象
- Android统一风格 —— 主题
- 如何在ListView中嵌入ViewPager
- java快速排序算法
- 我的Git的使用
- 配置jbpm6.1的eclipse开发环境
- 【黑马程序员】Java学习笔记之面向对象高级篇
- Keil建立STM32项目工程
- Spring AOP声明式事务异常回滚
- VS2010的附加依赖项和库怎么永久保存
- OCP-1Z0-051-2015-31题
- 【6.13】 定义基类Base,其数据成员为高h,定义成员函数disp为虚函数。然后再由High派生出长方体类Cuboid与圆柱体类Cylinder。并在两派生类中定义成员函数disp为虚函数。在主函
- Win7 X64家庭普通版 + VS2012 安装OpenSSL过程
- NuGet学习笔记(2)——使用图形化界面打包自己的类库
- RocksDB介绍:一个比LevelDB更彪悍的引擎