精华内容
下载资源
问答
  • asp VBScript 数组变量

    千次阅读 2013-02-17 13:12:04
    asp VBScript 数组变量 数组可以存储一系列相同类型的数据....有时候,将多个相关值赋给一个变量更为方便,因此可以创建包含一系列值的变量,称为数组变量数组变量和标量变量是以相同的方式声明的,唯

    asp VBScript 数组变量

    数组可以存储一系列相同类型的数据.这个例子告诉你怎么定义一个数组.(我们可以使用循环读取数组中的所有值.如for) 

    标量变量和数组变量 
    多数情况下,只需为声明的变量赋一个值。只包含一个值的变量被称为标量变量。有时候,将多个相关值赋给一个变量更为方便,因此可以创建包含一系列值的变量,称为数组变量。数组变量和标量变量是以相同的方式声明的,唯一的区别是声明数组变量时变量名后面带有括号 ( )。

    下例声明了一个包含 11 个元素的一维数组:

    Dim A(10)

    虽然括号中显示的数字是 10,但由于在 VBScript 中所有数组都是基于 0 的,所以这个数组实际上包含 11 个元素。在基于 0 的数组中,数组元素的数目总是括号中显示的数目加 1。这种数组被称为固定大小的数组。

    在数组中使用索引为数组的每个元素赋值。从 0 到 10,将数据赋给数组的元素,如下所示:

    A(0) = 256 
    A(1) = 324 
    A(2) = 100 
    . . . 
    A(10) = 55

    与此类似,使用索引可以检索到所需的数组元素的数据。

    例如:

    . . . 
    SomeVariable = A(8) 
    . . .

    数组并不仅限于一维。数组的维数最大可以为 60(尽管大多数人不能理解超过 3 或 4 的维数)。声明多维数组时用逗号分隔括号中每个表示数组大小的数字。在下例中,MyTable 变量是一个有 6 行和 11 列的二维数组:

    Dim MyTable(5, 10)

    在二维数组中,括号中第一个数字表示行的数目,第二个数字表示列的数目。

    也可以声明动态数组,即在运行脚本时大小发生变化的数组。对数组的最初声明使用 Dim 语句或 ReDim 语句。但是对于动态数组,括号中不包含任何数字。

    例如:

    Dim MyArray() 
    ReDim AnotherArray()

    要使用动态数组,必须随后使用 ReDim 确定维数和每一维的大小。在下例中,ReDim 将动态数组的初始大小设置为 25,而后面的 ReDim 语句将数组的大小重新调整为 30,同时使用 Preserve 关键字在重新调整大小时保留数组的内容。

    ReDim MyArray(25) 
    . . . 
    ReDim Preserve MyArray(30)


    重新调整动态数组大小的次数是没有任何限制的,将数组的大小调小时,将会丢失被删除元素的数据。

    重定义数组的事例

    <% 
    dim x() 
    for i=0 to 10 
    redim x(i) 
    x(i)=i 
    response.write x(i) 
    next 
    %>
    展开全文
  • 八种数据类型、三种变量类型、显式转换与隐式转换、两种修饰符、六种表达式、数组使用、Math类介绍、分支结构和循环结构、关键字、JVM、JDK与JRE

    文章目录

    本系列文章:
      Java基础(一)基本数据类型、变量类型、修饰符、表达式、数组、分支循环、关键字
      Java基础(二)字符串、四种引用、内存泄漏、克隆、语法糖、IO
      Java基础(三)面向对象、封装继承多态、重写和重载、内部类、包装类
      Java基础(四)异常、枚举、日期、反射、泛型
      Java基础(五)Lambda表达式、Stream流、正则表达式

    一、初识Java

    1.1 Java语言的特点

    • 1、跨平台性
        所谓跨平台性,是指java语言编写的程序,经过编译后生成字节码,可以在多个平台的虚拟机上运行。
    • 2、面向对象
        Java是面向对象的语言,使用面向对象的思想,可以降低程序耦合度,提高内聚性。
    • 3、安全性
        安全性可以分为四个层面,即语言级安全性、编译时安全性、运行时安全性、可执行代码安全性。语言级安全性指Java的数据结构是完整的对象,这些封装过的数据类型具有安全性。编译时要进行Java语言和语义的检查,保证每个变量对应一个相应的值,编译后生成Java类。运行时Java类需要类加载器载入,并经由字节码校验器校验之后才可以运行。
    • 4、多线程
        多线程可以提高程序的运行效率。
    • 5、简单易用,有丰富类库
        简单易用指的是Java程序的开发不必非得依赖特定的开发环境,用notepad等文本编辑工具就可开发。
    • 6、健壮性
        Java语言的强类型机制、异常处理、垃圾的自动收集等。

      强类型语言也称为强类型定义语言,求变量的使用要严格符合定义,所有变量都必须先定义后使用。

    1.2 JVM、JRE和JDK的关系

      JVM(Java Virtual Machine):Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。
      JRE(Java Runtime Environment):Java运行环境,包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统默认加载这个包。
      如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
      JDK(Java Development Kit)是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等。
      JVM&JRE&JDK关系图:

    1.3 什么是字节码?采用字节码的最大好处是什么?

    • 字节码
        Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。
    • 采用字节码的好处

      Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。

      总结:Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。

    Java源代码 —> 编译器 —> JVM可执行的Java字节码 —> JVM —> JVM中解释器 —> 机器可执行的二进制机器码 —> 程序运行

    1.4 什么是Java程序的主类?

      一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类,主类是Java程序执行的入口点。应用程序的主类一般是public类。示例:

    	//主类
    	public class TestDemo {
    		
    		public static void main(String[] args) {
    			Test2 test2 = new Test2();
    			System.out.print(test2);
    		}
    	}
    	
    	class Test2{
    	}
    

    1.5 Java和C++的区别

    • 1、都是面向对象的语言,都支持封装、继承和多态。
    • 2、Java不提供指针来直接访问内存,程序内存更加安全。
    • 3、Java的类是单继承的,但是一个类可以实现多个接口,接口可以多继承;C++支持多重继承。
    • 4、Java有自动内存管理机制,不需要程序员手动释放无用内存。

    1.6 Java语言采用何种编码方案?有何特点?

      Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。

    二、基本数据类型

      Java中,变量的目的是申请内存来存储值。也就是说,当一个变量被创建时,就需要在内存中申请空间,内存管理系统根据变量的类型为变量分配相应的存储空间,此时分配的空间只能用来存储该类型数据。
      Java有两大数据类型:基本数据类型引用数据类型

    • 1、基本数据类型
        基本数据类型有:整数类型(byte,short,int,long)、浮点类型(float,double)、字符型(char)和布尔型(boolean)。
        基本类型的取值范围如下:
    • 2、引用数据类型
        引用类型有:类(class)、接口(interface)和数组([ ])。

    2.1 整型数据

    • 1、byte
        8位(1字节),有符号整数,范围为-27 ~ 27-1,默认值是0。
    • 2、short
        16位(2字节),有符号整数,范围为-215 ~ 215-1,默认值是0。
    • 3、int
        32位(4字节),有符号整数,范围为-231~ 231-1(约-21亿 ~ 21亿),默认值为0,一般整型变量默认为int型。
    • 4、long
        64位(8字节),有符号整数,范围为-263 ~ 263-1,默认值为0L。赋予long型变量初始值时,需要在数字后面加上L。

      测试代码:

    	static byte b1;
    	static short s1;
    	static int i1;
    	static long l1;
    	public static void main(String[] args){
            System.out.println("byte型变量默认值 :"+b1 ); //byte型变量默认值 :0
            System.out.println("short型变量默认值 :"+s1 ); //short型变量默认值 :0
            System.out.println("int型变量默认值 :"+i1 );  //int型变量默认值 :0
            System.out.println("long型变量默认值 :"+l1 );  //long型变量默认值 :0
    	}
    

      在进行整型数据运算时,要注意溢出的问题,比如以int型为例,Integer.MAX_VALUE+1的运算结果是Integer.MIN_VALUE。即:

    		int i1 = Integer.MAX_VALUE;
    		int i2 = Integer.MIN_VALUE;
    		System.out.println("i1+1:"+(i1+1));  //-2147483648
    		System.out.println("i2:"+i2);   //-2147483648
    

    2.2 浮点型数据

    2.2.1 浮点型数据介绍

     浮点型数据分为2种:

    1. float
        单精度,32位,默认值是0.0f。
    2. double
        双精度,64位,默认值是0.0d,浮点型变量默认为double型

      测试代码:

    	static float f1;
    	static double d1;
    	public static void main(String[] args){
            System.out.println("float型变量默认值 :"+f1 ); //float型变量默认值 :0.0
            System.out.println("double型变量默认值 :"+d1 ); //double型变量默认值 :0.0
    	}
    

    2.2.2 浮点型数据引起的运算误差怎么解决?

      先看一个例子:

    		System.out.println(0.06+0.01);
    		System.out.println(2.0-1.1);
    		System.out.println(3.3*3);
    		System.out.println(3.3/3);
    

      在我们的预想中,这4个语句的执行结果应该是0.07、0.9、9.9、1.1,但是事实却不是这样的,实际的结果是:

    0.06999999999999999
    0.8999999999999999
    9.899999999999999
    1.0999999999999999

      其实浮点数的计算是可能不准确的,float和double类型的使用局限:

    1. 单精度浮点型变量float可以处理6 ~ 7位有效数,双精度浮点型变量double可以处理15~16位有效数,在实际应用中,如果需要对更大或者更小的数进行运算和处理,这时候float和double就无能为力了。
    2. float和double类型的主要设计目标是为了科学计算和工程计算,他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的。然而,它们没有提供完全精确的结果,所以不应该被用于要求精确结果的场合

      商业计算往往要求结果精确,这时候就需要用到BigDecimal。BigDecimal的使用,示例:

    public class DoubleTest {
    	
    	public static void main(String[] args)  {
    		System.out.println(add(0.06,0.01));
    		System.out.println(subtract(2.0,1.1));
    		System.out.println(multiply(3.3,3));
    		System.out.println(divide(3.3,3,1));
    	}
    	/* 加法运算*/
    	public static double add(double x, double y) {
    		BigDecimal vala = new BigDecimal(Double.toString(x));
    		BigDecimal valb = new BigDecimal(Double.toString(y));
    		return vala.add(valb).doubleValue();
    	}
    	
    	/*减法运算*/
    	public static double subtract(double x, double y) {
    		BigDecimal vala = new BigDecimal(Double.toString(x));
    		BigDecimal valb = new BigDecimal(Double.toString(y));
    		return vala.subtract(valb).doubleValue();
    	}
    	
    	/*乘法运算*/
    	public static double multiply(double x, double y) {
    		BigDecimal vala = new BigDecimal(Double.toString(x));
    		BigDecimal valb = new BigDecimal(Double.toString(y));
    		return vala.multiply(valb).doubleValue();
    	}
    	
    	/*除法运算(结果进行四舍五入)*/
    	public static double divide(double x, double y, int scale) throws ArithmeticException {
    		if (scale < 0) {
    			throw new ArithmeticException("精确度不能小于0");
    		}
    		
    		BigDecimal vala = new BigDecimal(Double.toString(x));
    		BigDecimal valb = new BigDecimal(Double.toString(y));
    		return vala.divide(valb, scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();
    	}
    }
    

      此时的结果就和我们预想的一致了:

    0.07
    0.9
    9.9
    1.1

    2.3 布尔型数据

      boolean,1位,只有两个取值:true和false,默认值是false。
      测试代码:

    	static boolean b1;
    	public static void main(String[] args){
            System.out.println("boolean型变量默认值 :"+b1 ); //boolean型变量默认值 :false
    	}
    

    2.4 字符型数据

      char,16位Unicode字符,范围为0 ~ 215-1(\u0000到\uffff),可存储任意字符,默认值是’u0000’。
      一个char类型变量中可以存储一个中文汉字,因为char类型变量使用的默认编码格式是 Unicode,一个 char 类型占 2 个字节(16 比特),所以放一个中文是没问题的。
      每种数据类型的取值范围可以通过其包装类来查看,如下:

    类型位数最大值最小值
    byteByte.SIZEByte.MAX_VALUEByte.MIN_VALUE
    shortShort.SIZEShort.MAX_VALUEShort.MIN_VALUE
    intInteger.SIZEInteger.MAX_VALUEInteger.MIN_VALUE
    longLong.SIZELong.MAX_VALUELong.MIN_VALUE
    floatFloat.SIZEFloat.MAX_VALUEFloat.MIN_VALUE
    doubleDouble.SIZEDouble.MAX_VALUEDouble.MIN_VALUE
    charCharacter.SIZECharacter.MAX_VALUECharacter.MIN_VALUE

      char类型比较特殊,其最大值和最小值不是数字。Character.MAX_VALUE的值是'\uFFFF',Character.MIN_VALUE的值是'\u0000'
      包装类还可以用来实现基本数据类型之间的转换,每个包装类中总有xxValue方法,来获得其对应的简单数据类型。
      String不是Java的基本数据类型,默认值为null
      其他数据类型转换为String的方式:

    1. X.toString()
    2. X+""
    3. String.valueOf(X)

      此处以int型数据转换为String为例,测试代码:

    		Integer i1 = 1;
    		String str1 = i1.toString();
    		String str2 = i1+"";
    		String str3 = String.valueOf(i1);
    		System.out.println(str1+","+str2+","+str3);   //1,1,1
    

      String数据转换为其他简单类型的方式:

    1. 包装类的xxValue(),比如:Double.valueOf(“32.1”).doubleValue()。
    2. 包装类的静态parseXX方法,比如:Double d = Double.parseDouble(s)。

      Java中,任何类型与字符串相加,都是进行拼接。原理为:先用String.valueOf()方法,再通过StringBuilder进行拼接
      此处以int型数据转换为String为例,测试代码:

    		String str1 = "123";
    		int i1 = Integer.valueOf(str1).intValue();
    		int i2 = Integer.parseInt(str1);
    		System.out.println(i1+","+i2);  //123,123
    

      Java中,引用类型的变量类似于C/C++中的指针,引用类型指向一个对象,指向对象的变量是引用变量。引用变量在声明时被指定为一个特定类型,并且不允许更改。
      对象、数组是引用数据类型,引用类型的默认值是null。
      final修饰常量,为了便于识别,一般用大写字母表示。
      Java常用转义字符:

    符号\n\r\f\b\0\s\t"\
    意义换行回车换页退格空字符字符串制表符双引号单引号反斜杠

    2.5 显式转换与隐式转换

      Java中,整型、常量、字符型数据可以混合运算。不同类型的数据进行运算时,会先转换为同一类型(更高的数据类型),再进行运算。
      各变量优先级如下:
        低 ----------------------------------------------------> 高
        byte,short,char—> int —> long—> float —> double
      在8种基本数据类型中,char是比较特殊的一种类型,一共有2的16次方个数值。char<int<long<float<double;Char类型可以隐式转成int,double类型,如果char类型转成byte,short类型的时候,需要强转。示例如下:

    		char num1 = 1;
    		int num2 = num1;
    		double num3 = num1;
    		short num4 = num1; //编译报错
    		byte num5 = num1;  //编译报错	
    

      再用个更清晰的图来表示的话,如下:

      数据类型转换时需要注意的规则:

    1. 不能对boolean类型进行类型转换。
    2. 把优先级高的转换为优先级低时必须使用强制类型转换。
    3. 转换过程中可能导致溢出或损失精度。

      自动类型转换发生在转换前的数据类型的位数低于转换后的数据类型。
      强制类型转换发生的条件是转换前后的数据类型必须是兼容的。
      强制类型转换的格式为:(type)value。
      类型转换可分为两种:隐式转换和显式转换。

    2.5.1 隐式转换

       从表示范围小的类型转换为表示范围大的类型,可以直接转换,称为隐式转换。示例:

    		short m = 912;
            int n = m;
    

       因为int可以存储的范围要比short存储的范围大,所以short类型可以直接转换成int类型。

    2.5.2 显式转换

       从表示范围大的类型转换为表示范围小的类型,需要强制转换,称为显式转换。示例:

    		double m = 9.12;
            int n = (int)m;
            System.out.println(n); //9
    

      从该例子可以看出,显式转换可能伴随着精度的丢失

    2.5.3 隐式转换中需要注意的问题

      在使用+=、-=等符号时,常常伴随着隐式类型转换的进行,如果参与运算的两个变量数据类型相同,一般不会有什么问题。如果两个变量数据类型不同,就需要注意了。

    • 1、整型数据运算时的特殊情况
        先看如下代码存不存在问题:
            byte a=1;
            a=a+4;
            System.out.println(a);
    

      看上去,好像没什么问题,实则不是。在执行语句’a=a+4’时,a是byte类型,而数字4默认是int 类型。在java中,在a+4时,会进行 自动类型转换 ,所以a+4 会转换成int类型。而变量a还是byte类型,将int 类型的a+4赋值给byte类型的a ,无疑会报错。
      此时如果要消除错误,可以使用强制类型转换,示例:

            byte a=1;
            a=(byte)(a+4);
            System.out.println(a);
    

      也可以用如下方法修改:

            byte a=1;
            a+=1;
            System.out.println(a);
    

      依然先看如下代码存不存在问题:

    		byte a = 127;
    		byte b = 0;
    		b = a + b; 
    

      粗看之下好像也没问题,其实也有问题,报错如下:

      此时建议将上述代码,修改为如下形式:

    		byte a = 127;
    		byte b = 0;
    		a += b; 
    

      上面现象产生的原因是:整型数据和整型数据进行运算的时候,如果两边的值都是小于或者等于int的,那么其结果就是int型
      此外还有一种情况,先看下面代码:

    		int a = 0;
    		long b = 10L;
    

      a + b 的结果是long型,原因是:整型数据和整型数据进行运算的时候,如果有一边的长度超过int,那么运算结果就按照最长的长度

    • 2、隐式转换相关的建议
        当操作的变量涉及非int型变量时,建议使用'a += b',不用'b = a + b'

    2.6 short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

      对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。这种现象产生的原因是:整型数据和整型数据进行运算的时候,如果两边的值都是小于或者等于int的,那么其结果就是int型

      而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

    三、变量类型

      Java中的变量类型大致可分为3种:

    1. 类变量,方法体之外的变量,用 static 修饰。
    2. 实例变量,方法体之外的变量,无 static 修饰。
    3. 局部变量:方法体中的变量。

    3.1 局部变量

      局部变量的特征:

    1. 声明在方法、构造方法或者语句块中。
    2. 在方法、构造方法、或者语句块被执行的时候创建,执行完后,变量将会被销毁。
    3. 只在声明它的方法、构造方法或者语句块中可见,访问修饰符不能用于局部变量
    4. 所占用的内存空间在栈。
    5. 没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。

      局部变量示例:

    	public int addOne(int a) {
    		int ONE = 1;
    		return a + ONE;
    	}
    

      假如用访问修饰符修饰,局部变量,会报错:

      假如局部变量没有赋予默认值,也会报错:

    3.2 实例变量

      实例变量的特征:

    1. 声明在一个类中,但在方法、构造方法和语句块之外。
    2. 当一个对象被实例化之后,每个实例变量的值就跟着确定。
    3. 实例变量在对象创建的时候创建,在对象被销毁的时候销毁。
    4. 访问修饰符可以修饰实例变量。
    5. 实例变量对于类中的方法、构造方法或者语句块是可见的。
    6. 实例变量具有默认值,数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null
    7. 实例变量可以直接通过变量名访问。

      实例变量示例:

    public class TestDemo {
    	
    	private int a;
    	int ONE = 1;
    	
    	public TestDemo() {
    		a = 2;
    	}
    	
    	public static void main(String[] args) {
    		TestDemo testDemo = new TestDemo();
    		System.out.println("a:"+testDemo.a+",addOne(5):"+testDemo.addOne(5)); //a:2,addOne(5):6
    	}
    	
    	public int addOne(int num) {
    		return num + ONE;
    	}
    }
    

    3.3 静态变量

      静态变量也称类变量,其特征:

    1. 在方法体之外,用static关键字声明。
    2. 静态变量的数量与该类创建的对象数量无关,只有一个。
    3. 静态变量储存在静态存储区
    4. 静态变量在第一次被访问时创建,在程序结束时销毁。
    5. 默认值和实例变量相似。数值型变量默认值是0,布尔型默认值是false,引用类型默认值是null。
    6. 可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。

      静态变量被声明为public static final类型时,静态变量名称一般建议使用大写字母,此时的作用就是与常量相同。
      静态变量示例:

    public class TestDemo {
    	
    	private static int a;
    	public static final int ONE = 1;
    	
    	public static void main(String[] args) {
    		System.out.println("a:"+a+",addOne(5):"+addOne(5)); //a:0,addOne(5):6
    	}
    	
    	public static int addOne(int num) {
    		return num + ONE;
    	}
    }
    

      静态变量与实例变量的区别:

    1. 静态变量属于类,该类不生产对象,一般通过类名.静态变量方式调用。
    2. 实例变量属于该类的对象,必须创建该类对象,才能调用实例变量

    四、修饰符

      Java中修饰符主要分为:访问修饰符和非访问修饰符。

    4.1 访问修饰符

      顾名思义,该类修饰符重要控制访问权限。不同访问修饰符的修饰对象及权限,如下:

    1. default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
    2. private : 在同一类内可见。使用对象:变量、方法。
    3. protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。
    4. public : 对所有类可见。使用对象:类、接口、变量、方法。

      用表格展示的话:

    修饰符当前类同包类子类其他类
    publicYYYY
    protectedYYYN
    defaultYYNN
    privateYNNN

      接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为public
      声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。也就是说,声明为private的方法和变量,都是当前类内部使用的,外部不能访问。

    • protected特征:
    1. 子类与基类在同一包中,被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问。
    2. 子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
    • 访问控制和继承规则:
    1. 父类中声明为 public 的方法在子类中也必须为 public。
    2. 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
    3. 父类中声明为 private 的方法,不能够被继承。

      这三条规则体现的访问权限放大机制,即子类方法的方法访问权限>=父类的方法访问权限

      关于private、default、protected、public四种修饰符在平时开发中的使用,不太知道怎么使用的话,可以简单参考以下几条原则:

    1. 属性通常使用private封装起来。
    2. 方法一般使用public用于被调用。
    3. 会被子类继承的方法,通常使用protected。
    4. 作用范围最小原则。即能用private就用private,不行就放大一级,用default,再不行就用protected,最后用public, 这样就能把数据尽量的封装起来

    4.2 非访问修饰符

     非访问修饰符,主要有static、final、abstract。此处先简单介绍,后面会详细说明。

    • 1、static
        static修饰变量,就是静态变量,一个类只有一个静态变量。
        static修饰方法,通过类名而不是该类实例化的对象调用。
    • 2、final
        final修饰变量,声明的时候必须初始化,不能被修改。
        final修饰方法,可以被子类继承,但是不能被子类重写。
        final修饰类,不能被继承。
    • 3、abstract
        abstract修饰类,不能被实例化。
        abstract修饰方法,需要被子类重写,除非子类也是抽象类。

    五、表达式

      Java表达式是变量、常量、运算符、方法调用的序列,执行指定的计算并返回特定的值。
      表达式一般是按运算符来划分的,表达式种类:

    1、算术表达式
    2、关系表达式
    3、布尔逻辑表达式
    4、位运算表达式
    5、赋值表达式
    6、条件表达式

    5.1 算术运算符

    +   -   *   /   %  ++   --
    

      a++代表先使用,再+1,;–a代表先减1,再使用。测试代码:

    		for(int i=0;i<3;i++){
    			System.out.print(i+" ");   //0 1 2 
    		}
    

      由这个例子可以看出,i++这种自增或自减符号在运算表达式或变量后面的,是先使用,再变化。

    5.2 关系运算符

    ==  !=   >   <   >=    <=
    

      关系运算符比较的都是值,而非引用。

    5.3 位运算

      位运算应用于char、short、int、long型数据。
      位运算方式:

     &,都为1,结果则为1,否则为0。
     |,都为0,结果为0,否则为1。
     ^,相同为0,不同为1。
     ~,取反。
      <<,按位左移运算符,乘2的n次方。
      >>,按位右移运算符,除2的n次方。

    5.4 逻辑运算符

      逻辑运算有三种:

     &&,逻辑与运算,都为真结果则为真。
     ||,逻辑或运算符,有真则为真。
     !,逻辑非运算符,取反。

      &&为短路逻辑与运算符,即前面的判断条件为false时,不再进行后面条件的判断。
      ||为短路或运算符,即如果左边的运算结果已经是true,右边的语句不会再执行。
      关于短路功能,测试代码:

    		int i=1;
    		if(i==2 && (i++)==2)
    			System.out.println("test");
    		System.out.println("i:"+i);  //i:1
    

      由这个例子可以看出:当&&前面的判断条件i==2不成立时,后面的判断语句也没有进行

    5.5 赋值运算符

    =   +=   -=  *=  /=    %=   <<=   >>=  &=  ^=  |= 
    

      特殊赋值运算符(如:+=)可以在不改变原有数据类型的情况下实现运算,如果两个值数据类型不一致,会进行强制数据类型转换。测试代码:

    		int i=1;
    		i+=2;
    		System.out.println("i:"+i);  //i:3
    		i+=2.0f;
    		System.out.println("i:"+i);  //i:5
    

    5.6 条件运算符

      即三元运算符,形式为:

    x = (expression) ? trueVal : falseVal
    

      测试代码:

    		int gradeA=98;
    		int gradeB=93;
    		int betterGrade=0;
    		betterGrade=gradeA>gradeB?gradeA:gradeB;
    		System.out.println("两个同学中较好的成绩是:"+betterGrade); //两个同学中较好的成绩是:98
    

    5.7 instanceof运算符

      此处借鉴网上的一篇博客:Java关键字(一)——instanceof
      instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:

    	boolean result = obj instanceof Class
    

      其中obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
      此处需要注意的是:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。

    5.7.1 obj 必须为引用类型,不能是基本类型

      instanceof 运算符只能用作对象的判断,所以下面两种写法都会编译报错:

    5.7.2 obj为null时的情况

      Java中,数据分为基本数据类型和引用数据类型,null不属于这两种类型,自然不能算作引用类型。因此,对 instanceof 运算符的规定就是:如果 obj 为 null,那么将返回 false。示例

    	System.out.println(null instanceof Integer); //false
    

    5.7.3 obj为类的实例对象的情况

      这是最常用的情况,示例:

    		Integer integer = new Integer(1);
    		System.out.println(integer instanceof  Integer); //true
    

    5.7.4 obj为class接口的实现的情况

      此处以List接口和其数组实现ArrayList为例,instanceof 运算符比较的是instanceof符号前面的引用的对象是否后面接口的实现,示例:

    		ArrayList arrayList = new ArrayList();
    		System.out.println(arrayList instanceof List);//true
    		List list = new ArrayList();
    		System.out.println(list instanceof ArrayList);//true
    

    5.7.5 obj为class 类的直接或间接子类的情况

      该情况与上种情况类似,instanceof 运算符比较的是instanceof符号前面的引用的对象是否后面类或其子类,示例:

    /*父类*/
    public class Person {
    
    }
    /*子类*/
    public class Man extends Person{
    
    }
    /*测试类*/
    public class ClassTest {
    	public static void main(String[] args)  {
    		Person p1 = new Person();
    		Person p2 = new Man();
    		Man m1 = new Man();
    		System.out.println(p1 instanceof Man);//false
    		System.out.println(p2 instanceof Man);//true
    		System.out.println(m1 instanceof Man);//true
    	}
    }
    

      在前面提过这样一句话“编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定”,这句话可以仍然用上面的Person类和Man类来说明,示例:

    	System.out.println(p1 instanceof String);//编译报错
    	System.out.println(p1 instanceof List);//运行时报错
    	System.out.println(p1 instanceof List<?>);//运行时报错
    	System.out.println(p1 instanceof List<Person>);//编译报错
    

    5.7.6 instanceof运算符的实现

      先看JDK1.8中的实现,用伪代码表示为:

    	boolean result;
    	if (obj == null) {
    	    result = false;
    	} else {
    	    try {
    	        T temp = (T) obj; // checkcast
    	        result = true;
    	    } catch (ClassCastException e) {
    	        result = false;
    	    }
    	}
    

      在执行obj instanceof T运算时,首先,会检查obj的类型是否是引用类型或空类型,如果不是则会发生编译时错误;
      其次,如果 obj 强制转换为 T 时发生编译错误,则关系表达式的 instanceof 同样会产生编译时错误;
      最后,在运行时,如果 T 的值不为null,并且 obj 可以转换为 T 而不引发ClassCastException,则instanceof运算符的结果为true。 否则结果是false。
      简单来说就是:如果 obj 不为 null 并且 (T) obj 不抛 ClassCastException 异常则该表达式值为 true ,否则值为 false

    5.8 运算符优先级比较

      Java运算符优先级(从上往下依次递减):

    类别操作符运算顺序
    后缀() [] . (点操作符)左到右
    一元+ + – (此处指的是先执行自增或自减,再执行表达式)左到右
    一元+ + – (此处指的是先执行表达式,再执行自增或自减) ! 〜右到左
    乘性* /%左到右
    加性+ -左到右
    移位>> >>> <<左到右
    关系> > = < < =左到右
    相等== !=左到右
    按位与、异或、或&、^、
    逻辑与、或&&、
    条件?:左到右
    赋值= + = - = * = / =%= >> = << =&= ^ ==

      如果在程序中,要改变运算顺序,可以使用()。

    六、数组

      一个数组就代表在内存中开辟一段连续(意味着有序)、用来存储相同类型数据的空间,其特征如下:

    1. 数组名代表的是连续空间的首地址。
    2. 通过首地址可以依次访问数组所有元素,元素在数组中的位置叫做下标,从0开始。
    3. 数组长度一旦声明,不可改变不可追加。

    6.1 声明数组

      数组的声明方式有两种,以int型数组举例:int[ ] array和int array[ ],一般用第一种方式。

    6.2 创建数组

      数组的创建方式也有两种,以int型数组举例。

    	int[ ] array = new int[10]
    

     该语句的意思是创建一个容量大小为10的int型数组,数组中默认值是0。也就是说,当数组元素未赋值时,数组元素的值为数组元素类型的默认值(此处是int型,所以默认值是0)。

    	int[ ] array1 = {1,2,3,4,5,6};
    	int[ ] array2 = new int[ ]{1,2,3,4,5,6};
    

     这两个语句的意思都是创建一个容量大小为6的int型数组,数组中的初始值为1,2,3,4,5,6。

    6.3 遍历数组

      数组的遍历方式也有两种,以int型数组举例。

    • 1、for循环
       最常用的遍历方式,示例:
        for(int i=0;i<array.length;i++)
            System.out.println(array[i]+" ");
    
    • 2、foreach循环
       示例:
        for(int arr:array)
            System.out.println(arr+" ");
    

    6.4 数组复制

      对数组进行复制的方法,常常有System.arraycopy和使用Arrays工具类两种方法。此处介绍第一种,具体的方法是:

    	System.arraycopy(src, srcPos, dest, destPos, length)
    

     src: 源数组
     srcPos: 从源数组复制数据的起始位置
     dest: 目标数组
     destPos: 复制到目标数组的起始位置
     length: 复制的长度

      示例:

    	static int[] arr1 = {1,2,3,4,5,6};
    	static int[] arr2 = new int[6];
    	
    	public static void main(String[] args) {
    		System.arraycopy(arr1, 0,arr2, 1, 3);
    		for(int i=0;i<arr2.length;i++) {
    			System.out.print(arr2[i] + " "); //0 1 2 3 0 0 
    		}
    	}
    

    七、工具类

    7.1 Math类

      Math类包含用于执行基本数学运算的方法。常用方法有:三角函数类方法和数值计算类方法。

    7.1.1 三角函数类方法

    1. 反余弦值
    public static native double acos(double d)
    
    1. 反正弦值,范围在 -pi/2 到 pi/2 之间
    public static native double asin(double d)
    
    1. 反正切值,范围在 -pi/2 到 pi/2 之间
    public static native double atan(double d)
    
    1. 余弦值
    public static native double cos(double d)
    
    1. 正弦值
    public static native double sin(double d)
    
    1. 正切值
    public static native double tan(double d)
    

    7.1.2 数值计算类方法

    1. 绝对值
    public static double abs(double d)
    public static float abs(float f)
    public static int abs(int i)
    public static long abs(long l)
    
    1. 对一个数进行上舍入,返回值大于或等于给定的参数,类型为双精度浮点型
    public static native double ceil(double d)
    

      测试代码:

            double d = 10.6;
            float f = -95;   
            System.out.println(Math.ceil(d));   //11.0
            System.out.println(Math.ceil(f));    //-95.0
    
    1. 对一个数进行下舍入,返回给定参数最大的整数,该整数小于或等给定的参数
     public static native double floor(double d)
    

      测试代码:

            double d = 10.6;
            float f = -95;   
            System.out.println(Math.floor(d));   //10.0
            System.out.println(Math.floor(f));   //-95.0
    
    1. 返回参数的自然数底数的对数值
    public static native double log(double d)
    

      测试代码:

        System.out.printf("log(%.3f) 为 %.3f%n", 
        	Math.E*Math.E,Math.log(Math.E*Math.E));  //log(7.389) 为 2.000
    
    1. 返回 double 值的底数为 10 的对数
    public static native double log10(double d)
    

      测试代码:

    	System.out.printf("log(%.3f) 为 %.3f%n", 
    		100.0,Math.log10(100.0));   //log(100.000) 为 2.000
    
    1. 返回较大值
    public static double max(double d1, double d2)
    public static float max(float f1, float f2)
    public static int max(int i1, int i2)
    public static long max(long l1, long l2)
    
    1. 返回较小值
    public static double min(double d1, double d2)
    public static float min(float f1, float f2)
    public static int min(int i1, int i2)
    public static long min(long l1, long l2)
    
    1. 返回第一个参数的第二个参数次幂的值
    public static native double pow(double x, double y)
    

      测试代码:

            double d1 = 10.0;
            double d2 = 2.0;   
            System.out.println(Math.pow(d1,d2));  //100.0
    
    1. 返回一个随机数,随机数范围为 [0.0 ,1.0]
    public static synchronized double random()
    
    1. “四舍五入”,算法为Math.floor(x+0.5) ,即将原来的数字加上 0.5 后再向下取整
    public static long round(double d) / static int round(float f)
    

      测试代码:

        System.out.println(Math.round(11.5));    //12
        System.out.println(Math.round(-11.5));   //-11
    
    1. 正平方根
    public static native double sqrt(double d)
    

    7.2 Arrays类

       Arrays是一个封装好一些对数组操作的类,其中的public方法都是静态的,主要有以下几大类:

    • 1、搜索类
       该类方法的作用是在数组中搜索某个值,返回该值在数组中的下标。该类方法的实现是二分搜索,例如在int数组中搜索某个值,方法实现代码:
        public static int binarySearch(int[] array, int startIndex, int endIndex, int value) {
            checkBinarySearchBounds(startIndex, endIndex, array.length);
            int lo = startIndex;
            int hi = endIndex - 1;
    
            while (lo <= hi) {
                int mid = (lo + hi) >>> 1;
                int midVal = array[mid];
    
                if (midVal < value) {
                    lo = mid + 1;
                } else if (midVal > value) {
                    hi = mid - 1;
                } else {
                    return mid;  // value found
                }
            }
            return ~lo;  // value not present
        }
    
    • 2、赋值类
       该类方法的作用是给数组中元素赋予默认值,实现是遍历赋值。方法实现代码:
        public static void fill(int[] array, int start, int end, int value) {
            Arrays.checkStartAndEnd(array.length, start, end);
            for (int i = start; i < end; i++) {
                array[i] = value;
            }
        }
    
    • 3、计算哈希值类
       该类方法的作用是计算数组中元素的哈希值。方法实现代码:
        public static int hashCode(int[] array) {
            if (array == null) {
                return 0;
            }
            int hashCode = 1;
            for (int element : array) {
                // the hash code value for integer value is integer value itself
                hashCode = 31 * hashCode + element;
            }
            return hashCode;
        }
    
    • 4、比较值类
       该类方法的作用是比较两个数组是否相等。
    • 5、排序类
       该类方法的作用是对数组中的元素进行排序,用到的排序方式是快速排序。方法实现代码:
        public static void sort(int[] array, int start, int end) {
            DualPivotQuicksort.sort(array, start, end);
        }
    
    • 6、转换为字符串类
       即toString方法。
    • 7、拷贝类
       该类方法的作用是拷贝数组中的元素,可以指定起始位置,未指定初始位置的话,默认从0开始。方法实现代码:
        public static int[] copyOf(int[] original, int newLength) {
            if (newLength < 0) {
                throw new NegativeArraySizeException(Integer.toString(newLength));
            }
            return copyOfRange(original, 0, newLength);
        }
    
    • 8、转换为List
       asList,使用示例:
    int[] datas = {1,2,3,4,5,6};
    List list = Arrays.asList(datas);
    

    7.3 Collections类

      Collections类是针对集合操作的工具类。

    public class Collections extends Object
    

      常用方法:

    1. 排序,默认是自然排序(排序算法是修改的归并排序算法)
    public static void sort(List list)
    

      使用默认排序规则和自定义规则的示例:

            Collections.sort(list);
            Collections.sort(list,new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    if(o1.length()>o2.length()){
                        return 1;
                    }else if(o1.length()<o2.length()){
                        return -1;
                    }else{
                        return 0;
                    }
                }
            });
    
    1. 二分查找(前提元素有序)
    //二分查找的时候需要先进行排序操作,如果没有排序的话,是找不到指定元素的
    public static int binarySearch(List<?> list,T key)    
    
    1. 获取集合中最大值
    public static T max(Collection<?> coll)
    
    1. 获取集合中最小值
    public static T min(Collection<?> coll)
    
    1. 反转集合
    public static void reverse(List<?> list)
    

    八、分支循环

      Java中,除了普通的顺序结构外,特殊的结构有三种:

    8.1 分支结构

      if、if-else、if-else if-else结构适合某个变量值在连续区间情况下的语句执行。
      如果某个变量值不是在连续区间的话,比如是整数,可以用switch。switch基本语法:

    switch(expression){
        case value :
           //语句
           break; //可选
        case value :
           //语句
           break; //可选
        //你可以有任意数量的case语句
        default : //可选
           //语句
    }
    

      switch-case结构与多种if结构作用相似,但是有局限性,其特点如下:

    1. JDK1.7之前的版本中,switch语句支持的数据类型有byte、short、int、char和枚举类型(即在整数类型中,唯独不支持long类型);在JDK1.7及以后的版本中,增加了对String类型的支持(编译后是把String转化为hash值,其实还是整数)。
    2. 用于等值判断
    3. break是每种case的结束标志,如无break则会继续走下个case。
    4. 一般最后都会有个default,用来处理匹配不到任何case的情况。

      switch使用的示例代码:

    		int grade=80;
    		switch(grade){
    			case 60:
    			case 70:
    				System.out.println("你的成绩为60或70分");
    				break;
    			case 80:
    				System.out.println("你的成绩为80分");
    				break;
    			default:
    				System.out.println("你的成绩为60、70、80之外的分数");
    				break;
    		}
    

    8.2 循环结构

      Java中循环结构有两种:

    1. for循环,有三部分:初始化操作、判断终止条件表达式及迭代部分。for循环一般用于循环次数已知的情况
    2. while循环,有两种:
    while(判断条件){
    	循环体
    }
    
    do{
    	循环体
    }while(判断语句);
    

      do-while先执行循环体语句,然后进行判断,也就是无论如何会先执行一次循环体语句。

    8.3 跳转语句

      跳转语句有三种:break、continue、return。此外,异常处理也可以改变程序执行流程。
      break有以下作用:

    1. 在switch中,用来终止一个语句序列。
    2. 用来退出一个循环。

      continue只能用来for、while、do while循环中,用于跳过当前循环,直接进行下一次循环。
      return语句使程序控制返回到调用它的地方,也就是:

    1. 返回方法的返回值;
    2. 终止当前程序。

      关于break、continue、return的使用,可以通过一段测试代码来查看其具体使用,测试代码:

    public class SkipTest {
    	public static void main(String[] args) {
    		int result = sum(10);
    		System.out.println("所求的数字之和是:"+result);
    	}
    	
    	private static int sum(int num){
    		int s = 0;
    		for(int i=1;i<=num;i++){
    			if(i==3)
    				continue;
    			System.out.println("i:"+i);
    			s=s+i;
    			if(i==(num-1))
    				break;
    		}
    		return s;
    	}
    }
    

      测试结果:

    i:1
    i:2
    i:4
    i:5
    i:6
    i:7
    i:8
    i:9
    所求的数字之和是:42

      这段代码是一个序列的数字之和,不过不需要+3,所以在i == 3时,使用continue,表示跳过此次循环,进入下一次循环。我们也不希望+10,所以在i == (num-1)时,使用了break,直接跳出循环。return的作用就是返回到调用该方法的地方,有返回值的话将返回值返回,无返回值的话则不用返回。

    8.4 switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

      在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型。从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的

    • 为什么只支持上面几种?int、String 都可以,为什么不支持 long ?

    原因就是 switch 对应的 JVM 字节码 lookupswitch、tableswitch 指令只支持 int 类型。 byte、char、short 类型在编译期默认提升为 int,并使用 int 类型的字节码指令。所以对这些类型使用 switch,其实跟 int 类型是一样的。

    九、关键字与标识符

      Java关键字的标准定义是电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字,还有特别意义的变量。Java的关键字对Java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名、方法名、类名、包名和参数

    9.1 所有关键字

      java关键字共53个,包含两个保留字const,goto,具体如下:

    关键字意义
    abstract抽象
    assert断言assert是jdk1.4引入的;jvm断言默认是关闭的;断言只适用复杂的调式过程;断言一般用于程序执行结构的判断,千万不要让断言处理业务流程
    boolean布尔类型,值为true或false
    break结束一个语句块的执行,常用于switch…case和循环语句中
    byte字节类型
    case用于switch…case语句中,表示其中一个分支
    catch用于try…catch语句中,用来捕捉异常
    char字符类型
    class
    const保留关键字
    continue结束本次循环,进行下一次循环,主要用于for、while循环中
    default用于switch…case语句中,表示匹配不上任何case的情况
    do用于do…while循环中,其后是要默认执行一次的语句库
    double双精度浮点类型
    else表示条件不成立的情况
    enum枚举
    extends继承,用于类和类、接口和接口之间
    final不可修改
    finally用于try…catch语句中,用来处理不论是否捕捉到异常,都执行的语句
    float单精度浮点类型
    forfor循环,常用于有序序列的遍历
    goto保留关键字
    if某种条件的判定
    implements实现接口,即实现接口文件中定义的空方法
    import导入其他package中的类,用于跨包间的代码调用
    instanceof判断某个对象是否属于某种类型
    int整型数据类型
    interface接口,声明一些空方法,待实现该接口的类去实现
    long长整型数据类型
    native代表调用本地C语言实现的接口
    new创建对象
    packagejava语言中组织代码的一个单位
    private私用,代表最低的访问优先级
    protected被保护的,代表有继承等关联关系等的访问优先级
    public公共的,代表最高访问优先级
    return返回,结束方法
    short短整型数据类型
    static静态
    super表示父类
    switch多条件分支判定
    synchronized同步,代表要保证线程安全
    this表示当前类
    throw抛出某个具体异常
    throws声明在当前定义的成员方法中所有需要抛出的异常
    transient表示不需要被序列化
    try用于try…catch语句
    void表示该方法无返回值
    volatile表明两个或者多个变量必须同步地发生变化
    while用于while和do…while循环语句中

    9.2 部分重要关键字

    9.2.1 abstract

      abstract代表抽象,可以修饰类和方法。

    • 1、抽象方法
        abstract修饰方法时,代表抽象方法。抽象方法的特点:
    1. 抽象方法没有自己的方法体;
    2. 抽象方法不能用private修饰,因为抽象方法必须被子类实现(覆写),而private权限对于子类来说是不能访问的,所以就会产生矛盾;
    3. 抽象方法也不能用static修饰,如果用static修饰了,就可以直接通过类名调用,而抽象方法压根就没有任何实现,这样的调用是没有意义的。
    • 2、抽象类
        abstract修饰类时,代表抽象类。抽象类的特点:
    1. 抽象类不能被实例化,也就是说我们没法直接new一个抽象类,抽象类只能由它的继承类实例化;
    2. 抽象类虽然不能被实例化,但有自己的构造方法;
    3. 抽象类与接口有很大的不同之处,接口中不能有实例方法去实现业务逻辑,而抽象类中可以有实例方法,并实现业务逻辑,比如可以在抽象类中创建和销毁一个线程池;
    4. 抽象类不能使用final关键字修饰,因为final修饰的类是无法被继承,而对于抽象类来说就是需要通过继承去实现抽象方法,这又会产生矛盾。
    • 3、抽象类和抽象方法的关系
    1. 如果一个类中至少有一个抽象方法,那么这个类一定是抽象类,但反之则不然。也就是说一个抽象类中可以没有抽象方法。这样做的目的是为了此类不能被实例化。
    2. 如果一个类继承了一个抽象类,那么它必须全部覆写抽象类中的抽象方法,当然也可以不全部覆写,如果不覆写全部抽象方法则这个子类也必须是抽象类。

    9.2.2 final

      final代表最终的、不可更改的,可以修饰变量、方法和类。
      final修饰变量时, 如果引用为基本数据类型,则该引用为常量,该值无法修改(更准确的说法:该变量只有一次赋值的机会);如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改;如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
      当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。
      final修饰方法时,表示该方法无法被子类重写,但是可以被继承。
      final修饰类时,表示该类无法被继承,同时类中的所有成员方法都会被隐式定义为final方法(只有在需要确保类中的所有方法都不被重写时才使用final修饰类)。

    9.2.3 static

      static关键字主要用来修饰成员变量和成员方法,在《Java编程思想》中对static关键字有如下阐述:

    static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。

      简言之,使用static的目的是为了在不创建对象的前提下来调用方法/变量

    • 1、静态方法
        static修饰方法时,该方法称为静态方法。在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
    • 2、静态变量
        static修饰变量时,称为静态变量。静态变量在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。
    • 3、静态代码块
        除了修饰变量和方法外,static还可以修饰代码块,称为静态代码块。一个类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次

      static是不允许用来修饰局部变量。
      类的初始化顺序(先父类,后子类;先静态,后实例;先变量,后代码块,最后构造函数):

    1. 父类静态变量
    2. 父类静态代码块
    3. 子类静态变量
    4. 子类静态代码块
    5. 父类普通变量
    6. 父类普通代码块
    7. 父类构造函数
    8. 子类普通变量
    9. 子类普通代码块
    10. 子类构造函数

      关于该初始化顺序,可以通过如下测试代码来验证。父类测试代码:

    package Basic;
    
    public class BaseClass {
    
        /*父类静态变量*/ 
        public static String baseStaticVariable = "父类-->静态变量";
        /*父类普通变量*/ 
        public String baseVariable = "父类-->普通变量";   
      
        /*静态代码块*/ 
        static{   
            System.out.println(baseStaticVariable);   
            System.out.println("父类-->静态代码块");   
        } 
        
        /*父类构造函数*/ 
        public BaseClass() {   
            System.out.println("父类-->构造函数"); 
        }   
        
        /*普通代码块*/ 
        {   
            System.out.println(baseVariable);   
            System.out.println("父类-->普通代码块");   
        }   
    } 
    

      子类测试代码:

    package Basic;
    
    public class SubClass extends BaseClass{
    	
        /*子类静态变量*/ 
        public static String subStaticVariable = "子类-->静态变量";
        /*子类普通变量*/ 
        public String subVariable = "子类-->普通变量"; 
        
        public static void main(String[] args) {
            new SubClass();   
        }  
        
        /*静态代码块*/ 
        static {   
            System.out.println(subStaticVariable);   
            System.out.println("子类-->静态代码块");   
        }   
        /*普通代码块*/ 
        {   
            System.out.println(subVariable);   
            System.out.println("子类-->普通代码块");   
        }   
      
        /*子类构造函数*/ 
        public SubClass() {   
            System.out.println("子类-->构造函数"); 
        }   
    }
    

      测试结果:

    父类–>静态变量
    父类–>静态代码块
    子类–>静态变量
    子类–>静态代码块
    父类–>普通变量
    父类–>普通代码块
    父类–>构造函数
    子类–>普通变量
    子类–>普通代码块
    子类–>构造函数

    • static关键字特点
    1. static是一个修饰符,用于修饰成员(成员变量,成员函数)。static修饰的成员变量 称之为静态变量或类变量。
    2. static修饰的成员被所有的对象共享。
    3. static优先于对象存在,因为static的成员随着类的加载就已经存在。
    4. static修饰的成员多了一种调用方式,可以直接被类名所调用(调用方式:类名.静态成员)。
    5. static修饰的数据是共享数据,对象中的存储的是特有的数据。
    • 成员变量和静态变量的区别
    1. 生命周期的不同

     成员变量随着对象的创建而存在随着对象的回收而释放。
     静态变量随着类的加载而存在随着类的消失而消失。

    1. 调用方式不同

     成员变量只能被对象调用。
     静态变量可以被对象调用,也可以用类名调用(推荐用类名调用)。

    1. 别名不同

     成员变量也称为实例变量。
     静态变量称为类变量。

    1. 数据存储位置不同:

     成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据。
     静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。

    • 静态使用时需要注意的事项
    1. 静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)
    2. 静态方法中不可以使用this或者super关键字。
    3. 主函数是静态的。

    9.2.4 super

      super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。super的三种使用情况:访问父类的方法;调用父类构造方法;访问父类中的隐藏成员变量。
      调用父类构造方法的两种情况:

    1. 直接调用super()会执行父类的无参构造方法,可以默认不写。
    2. 使用super(“父类参数”),调用父类有参构造方法,把参数传递进来就好。

      父类只有带参构造器(无参构造器没有),子类必须有相同参数的构造方法。子类必须有相同参数的构造方法,并且还需要调用super(参数)。

    1. 构造方法中使用super关键字时,要位于构造方法的第一行,并且super构造方法和this构造方法不能同时使用。
    2. 当子类的构造方法中没有显式调用父类的构造方法时,会隐式使用super调用父类的无参构造方法。

      Super的使用示例:

    class Person{
        protected String name;
     
        public Person(String name) {
            this.name = name;
        }
     
    }
     
    class Student extends Person{
        private String name;
     
        public Student(String name, String name1) {
            super(name);
            this.name = name1;
        }
     
        public void getInfo(){
            System.out.println(this.name);      //Child
            System.out.println(super.name);     //Father
        }
     
    }
    
    public class Test {
        public static void main(String[] args) {
           Student s1 = new Student("Father","Child");
           s1.getInfo();
        }
    }
    

    9.2.5 this

      super表示父类,this表示当前对象。
      this访问本类中的属性,如果本类没有此属性则从父类中继续查找。
      this访问本类中的方法,如果本类没有此方法则从父类中继续查找。
      this调用本类构造,必须放在构造方法的首行。super调用父类构造,必须放在子类构造方法首行
      this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
      this的用法在java中大体可以分为3种(常见的是后两种):

    1. 普通的直接引用,this相当于是指向当前对象本身。
    2. 形参与成员名字重名,用this来区分
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    1. 引用本类的构造函数
    class Person{
        private String name;
        private int age;
        
        public Person() {
        }
     
        public Person(String name) {
            this.name = name;
        }
        public Person(String name, int age) {
            this(name);
            this.age = age;
        }
    }
    
    • this和super的联系
    1. 在对拥有父类的子类进行初始化时,父类的构造方法也会执行,且优先于子类的构造函数执行;因为每一个子类的构造函数中的第一行都有一条默认的隐式语句super();(如果子类的构造方法中没有手动调用父类的构造方法,则会默认调用父类的无参构造方法)
    2. this() 和super()都只能写在构造函数的第一行;
    3. this() 和super() 不能存在于同一个构造函数中。第一,this()和super()都必须写在构造函数的第一行;第二,this()语句调用的是当前类的另一个构造函数而这个另一个构造函数中必然有一个父类的构造器,再使用super()又调用一次父类的构造器, 就相当于调用了两次父类的构造器,编译器不会通过;
    4. this和super不能用于static修饰的变量,方法,代码块;因为this和super都是指的是对象/实例。

    9.3 标识符

      可以由自己命名的地方都称为标识符。例如,对于常量、变量、函数、语句块、类、项目等都需要一个名字,这些我们都统统称为标识符。

    • 标识符的命名规则(硬性要求)
    1. 标识符可以包含英文字母,0-9的数字,$以及_。
    2. 标识符不能以数字开头。
    3. 标识符不是关键字。
    • 标识符的命名规范(非硬性要求)
    1. 类名规范:首字符大写,后面每个单词首字母大写(大驼峰式)。
    2. 变量名规范:首字母小写,后面每个单词首字母大写(小驼峰式)。
    3. 方法名规范:同变量名。

    9.4 在Java中定义一个空实现、无参构造方法的作用【重要】

      Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

    十、传值调用和传引用调用

    10.1 两者定义

      要了解传值调用和传引用调用,需要先明白形参和实参。

    • 形参和实参
        形参:用来接收调用该方法时传递的参数。只有在被调用的时候才分配内存空间(也就是仅仅在方法内有效),一旦调用结束,就释放内存空间。
        实参:传递给被调用方法的值。
    • 传值调用和传引用调用
        传值调用:传值调用中传递的参数为基本数据类型,参数视为形参。
        传引用调用:传引用调用中,如果传递的参数是引用数据类型,参数视为实参。在调用的过程中,将实参的地址传递给了形参,形参上的改变都发生在实参上。

    10.2 传参举例

    10.2.1 传值调用

      传值调用都是传递的基本类型,示例代码:

    public class BasicTest1 {
    	public static void main(String[] args) {
    		int num = 1;
    		System.out.println("形参初始值:"+num); //形参初始值:1
    		print(num);
    		System.out.println("形参最终值:"+num); //形参最终值:1
    	}
    	
    	public static void print(int number){
    		number++;
    		System.out.println("形参修改值:"+number); //形参修改值:2
    	}	
    }
    

      在该例子中,main方法里的num是形参,print方法体内的number是实参。
      从这个例子可以看出,虽然方法体print内的number值改变了,但是main方法内的num值仍然是原来的值。这就证明了:传值调用时,方法不会改变实参的值

    10.2.2 传引用调用

      传引用调用都是传递的对象类型,示例代码:

    public class BasicTest2 {
    	
    	private String name;
    	public BasicTest2(String name){
    		this.name = name;
    	}
    	public void setName(String name){
    		this.name = name;
    	}
    	public String getName(){
    		return this.name;
    	}
    	
    	public static void main(String[] args) {  
    		BasicTest2 basicTest2 = new BasicTest2("hello");  
    		test(basicTest2);  
    		System.out.println(basicTest2.getName());  //hello world
    	}  
    	
    	public static void test(BasicTest2 basicTest2){  
    		basicTest2.setName("hello world");
    	}  
    }
    

      从这个例子可以看出:传引用调用时,可以改变对象的属性,但属性的引用是的不变的

    10.3 传参总结

    类别传值调用传引用调用
    参数类型基本类型数据对象
    是否改变原始值改变的是形参的值,并没有改变实参的值。同时,这个传递是单向的,形参不能传递回实参对对象做何种操作,都不会改变实参对象的引用,但是如果改变了对象的内容,就会改变实参对象的内容
    接收值方法其实接收的是参数的一个副本方法接收的是原始值的内存地址,而不是值的副本

      同时,还有一句比较具有迷惑性的话:“在Java里面参数传递都是按值传递”。这句话可以这样理解:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递
      Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。

    展开全文
  • 1.使用New运算符创建一维数组 type *name = new type[size]; size可以是常量也可以是变量 2.使用New运算符创建二维数组 一定要注意,必须b维度是确定的,type name[a][b]; 在C++中,数组可以被视为一种类型,二维...

    1.使用New运算符创建一维数组
    type *name = new type[size];
    size可以是常量也可以是变量

    2.使用New运算符创建二维数组
    一定要注意,必须b维度是确定的,type name[a][b];
    在C++中,数组可以被视为一种类型,二维数组本身会被解释成一个一维数组:这个数组的元素类型为另一种一维数组。
    第一种方法示例:
    void TestFunc_(unsigned int n)
    {
    unsigned int i, j;

    // 元素类型为‘int[5]’的数组,可赋值给‘int[5]’类型的指针.
    int (* array2D)[5] = new int[n][5];
    for(i=0; i<n; ++i)
    {
        for(j=0; j<5; ++j)
        {
            array2D[i][j] = i * 5 + j;
        }
    } 
    // 回收方法和普通动态数组相同,使用'delete[]'即可
    delete[] array2D;
    

    }
    第二种方法:使用指针间接引用
    首先创建若干个大小一致的动态数组,然后将这些数组的首地址(转化为指针)按顺序存储到一个动态数组中,就相当于模拟了一个二维动态数组。
    示例代码:

    void TestFunc_pointer(unsigned int height, unsigned int width)
    {
    unsigned int i, j;
    // 数组的元素类型为‘int *’,可赋值给指向‘int *’的指针.
    int **array2D = new int *[height];
    for(i=0; i<height; ++i)
    {
    array2D[i] = new int[width];
    }
    // 访问.
    for(i=0; i<height; ++i)
    {
    for(j=0; j<width; ++j)
    {
    // 内存非连续,注意防止越界.
    array2D[i][j] = i * width + j;
    }
    }
    // 首先回收低一级的动态数组.
    for(i=0; i<height; ++i)
    {
    delete[] array2D[i];
    }
    // 然后回收高一级的动态数组.
    delete[] array2D;
    }
    方法三:使用vector
    借助STL中的vector,我们可以很直观的创建一个二维数组,而不需要用到基本数组的概念。
    示例代码:
    void TestFunc_vector(unsigned int height, unsigned int width)
    {
    typedef std::vector IntVector;
    typedef std::vector IntVector2D;
    unsigned int i, j;
    IntVector2D *pArray2D = new IntVector2D;
    // 动态设置大小.
    pArray2D->resize(height);
    for(i=0; i<height; ++i)
    {
    (*pArray2D)[i].resize(width);
    }
    for(i=0; i<height; ++i)
    {
    for(j=0; j<width; ++j)
    {
    (*pArray2D)[i][j] = i * width + j;
    }
    }
    delete pArray2D;
    }
    原文:https://blog.csdn.net/samuelcoulee/article/details/8674388

    展开全文
  • JS定义数组变量时,在不需要给定数组的维度和长度的情况下,通常有两种方法: var arrTest=new Array(); var arrTest=[]; 两者效果一样。但是经过查看与对比,在各种对外公开的JS大型开源类库的代码中,第一种方法...

    前言

    JS定义数组变量时,在不需要给定数组的维度和长度的情况下,通常有两种方法:

    代码块1-1

    var arrTest=new Array();
    
    var arrTest=[];
    

    两者效果一样。但是经过查看与对比,在各种对外公开的JS大型开源类库的代码中,第一种方法基本看不到。
    又或者你曾经尝试过下面这段代码:

    代码块1-2

    console.time('using[]')
    for(var i=0; i<2000000; i++){var arr = []};
    console.timeEnd('using[]')
     
    console.time('using new')
    for(var i=0; i<2000000; i++){var arr = new Array};
    console.timeEnd('using new')
    

    你会发现以上这段代码(1-2)的结果有一些有意思的规律
    那就是:使用using new的时间总是会比using []来的长
    有可能你会觉得是因为代码的顺序的问题,那么我们改一下代码的顺序,但是你会很遗憾的发现,结果依然是使用using new的时间总是会比using []来的长

    如下面三图所示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    对使用Array和[]创建数组的区别的解释

    针对这个问题进行了搜索与寻找,相关帖子中提到了两者的细微差别:
    使用new关键字的方法会在内存中开辟一些空间,用来记录与存储该变量,也就是这是一个实例化过程。
    

    new关键字的使用,除了在需要实例化一个对象,或罕见的需要延时加载数据的情况外,你基本上不需要使用new关键字。在Javascript里分配大量的new变量地址是一项很慢的操作,为了效率起见,你应该始终使用对象符号。

    在另外一个搜索结果中,有提到这样的一个说法:很简单,Array()是一个对象,[]是一个数据原型。使用new
    Array()系统每次都会新生成一个对象(浏览器每生成一个对象都会耗费资源去构造他的属性和方法),他的子集是[];个人推荐使用[],效率高。浏览器对于CPU很吃紧,所以很多时候要有技巧。比如数字转换成字符只要a=a+’’;就可以了,比用String效率高了很多。但是如果乱用是会造成错误的。

    在数据类型一章中有提到过一种数据包装类型,创建一个字符串的方式有:‘字符串’或者是new String(‘字符串’),一种是直接创建了一个字符串,一个是调用字符串的构造函数创建字符串对象然后再创建这个字符串,中间多了一个创建对象的过程,也许这在一般情况下是看不出什么区别的,但是像上述例子中,当这个技术足够大的时候,就会发现了问题所在。因此,如果可以通过[]创建一个纯净的数组,就不需要通过new Array()来创建数组。

    原文章地址:https://www.cnblogs.com/shcrk/p/9280343.html

    本文完

    展开全文
  • 数组定义及使用

    2021-07-19 15:25:58
    1.数组 概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。 格式1:数组存储的数据类型[] 数组名字; 格式2:数组存储的数据类型 数组名字[];...new:关键字创建数组使用关键字。 数组
  • ---------------------- 黑马程序员 Android培训、期待与您交流! ---------------------- 概念:同一种类型数据的集合。其实数组就是一个容器。...但是,Java去掉了C/C++中的可以使用指针来访问元素的功能。
  • C语言修饰变量关键字程序在内存中的分段变量的属性变量的分类修饰变量关键字 程序在内存中的分段 当程序开始运行后,会加载到内存中,会把内存分成若干段,每一段的功能、权限不同。 代码段(txt):程序中的二...
  • 概述· 数组是存储多个变量的容器。 存储的多个变量必须是同一种数据类型。· 数组既可以存储基本数据类型,也可以存储引用数据类型 数组定义的格式:数据类型[] 数组 3.访问数组中的元素数组中的每个元素都是...
  • js 用"name"做数组变量命名的问题

    千次阅读 2016-01-10 18:07:23
    最近用因为用“name”做js数组类型变量名称时候发现个问题html代码&lt;!doctype html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;title&gt;Document&lt;/title&...
  • 在C++编程中,使用new创建数组然后用delete来释放。 一、创建并释放一维数组   #include using namespace std; int main() { int n; cin>>n; //分配动态一维数组 int *arr=new int[n]; for(int ...
  • Java创建数组的几种方式 1、一维数组的声明方式: type[] arrayName; 或 type arrayName[]; 附:推荐使用第一种格式,因为第一种格式具有更好的可读性,表示type[]是一种引用类型(数组)而不是type类型。建议不要...
  • Numpy(Python)创建数组方式

    千次阅读 2020-04-07 22:54:49
    Numpy(Python)创建数组方式 首先我们要知道为什么要使用numpy。 python是一门高级汇编语言,标准的Python中用列表(list)保存一组值,可以当作数组使用。但由于列表的元素可以是任何对象,因此列表中保存的是对象的...
  • 创建数组的三种方式

    2018-08-10 20:55:00
    1、关键字 var 变量名= Array(); 当传入一个值的时候代表数组的长度 如果输入2个值的时候代表数组的数据 var arr = Array(30,20); console.log(arr); 2、构造函数方式 var 变量名 = new Array();...
  • Day07一、构造方法1、构造方法的创建和作用2、构造方法的注意事项3、构造方法和set方法的区别二、Static关键字1、静态2、静态方法3、静态变量和成员变量的区别三、数组工具类的封装四、API的使用五、总结 ...
  • const关键字数组、指针

    千次阅读 2018-11-03 14:40:56
    C中使用指针是很危险的事情,一个不慎就会造成程序崩溃,因此对于传入函数的参数进行保护就是必须的了,特别是针对数组。 const关键字 const关键字用于将一个变量声明为只读,也就是常量,无法被修改。 const int ...
  • 数组

    2020-10-20 13:11:12
    数组 概念: 数组就是存储数据长度固定的容器,保证多个...new:关键字创建数组使用关键字。 数组存储的数据类型: 创建的数组容器可以存储什么数据类型。 [长度]:数组的长度,表示数组容器中可以存储多少个元素。
  • NumPy NumPy是Python语言的一个扩充程序库。...使用numpy库中的函数前,需使用import关键字引入numpy库,本博客采用以下方式引入numpy: import numpy as np 引入numpy库,并重命名为np,通过np.使用n...
  • 在Java中,我们需要标识代码的很多元素,包括类名、方法、字段、变量、包名等等。我们选择的那个名称就称为标识符,一个正确的标识符需要遵循以下规则: 1. 标识符可以由字母、数字、下划线(_)、美元符($)组成,...
  • 首先就是Java中的内存分配: ...每个对象都有成员变量和成员方法,这其中又有成员变量和局部变量的区别: A:在类中的位置不同 成员变量:在类中方法外 局部变量:在方法定义中或者方法声明上 B:在...
  • javascript数组 (4)

    2020-08-15 11:18:11
    使用new关键字创建数组 使用字面量的方式创建数组 数组中每个元素之间用逗号相隔 使用new关键字创建数组 使用new创建关键字 <script> var arr = new Array(); //创建一个空数组 console.log(arr) <...
  • JavaScript&jQuery.数组

    2018-05-12 11:55:00
    创建数组时,先声明数组变量使用关键字var;数组的值由一对中括号([])括起来,数组中的值由逗号(,)分开;数组中的值可以是数字、字符串、布尔值。 访问和更改数组中的值 数组使用索引来确定值,访问数组中的...
  • 数组的定义

    2019-09-22 11:17:31
    数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];...new:关键字创建数组使用关键字。 数组存储的数据类型: 创建的数组容器可以存储什么数据类型。 [长度]:数组的长度,表示数组容器中...
  • 汇编中定义数组变量

    千次阅读 2019-01-08 05:12:52
    但它不像其它高级语言那样把变量分成许多类型,它是按照变量的长度来区分的,所以定义(define)变量时就用5个不同的关键字:DB,DW,DD,DQ,DT(事实上常用的只有DB,DW)DB(DEFINE BYTE)即定义的变量占一个字节的...
  • 昨日内容回顾 debug 是idea的一种操作方法,可以...其中一维数组长度可以省略,如果省略了,java不会帮我们把一维数组创建出来,需要我们自己手动创建一维数组,然后再将创建好的一维数组保存到二维数组中;好处是可以让每一
  • 数组 一组数的意思 c语言中给数组的定义:一组相同类型元素的集合 int main() { int arr[10]={1,2,3,4,5,6,7,8,9,10};//arr为数组名,int为元素类型 int arr1[10]={1,2,3,4,5}//初始化数组arr1的前5个元素为1,2,...
  • JAVA SE自学 基础篇 封装(二)什么是方法(method)如何定义方法如何调用方法什么是this关键字局部变量和成员变量的区别对象数组单元测试 目标 理解方法是个黑盒子 理解方法的参数和返回值 会定义方法 会调用方法 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 237,241
精华内容 94,896
关键字:

创建数组变量一般使用关键字