Java学习的一些基础笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习的一些基础笔记相关的知识,希望对你有一定的参考价值。

classpath
.;%java_home%\lib;%java_home%\lib\tools.jar;D:\Java\;
java_home
D:\Program Files\Java\jdk1.8.0_51
path
C:\Users\BaseKing-Sunie\AppData\Local\Code\bin;%java_home%\bin;%java_home%\jre\bin;
D:\adt-bundle-windows-x86_64_20131020\sdk\tools;D:\adt-bundle-windows-x86_64_20131020\sdk\platform-tools;
TEMP
%USERPROFILE%\AppData\Local\Temp
TMP
%USERPROFILE%\AppData\Local\Temp

第一本书
【Run As】
发现程序有问题,程序无法运行,但没有错误时,可以右键,然后移到Run As,如果显示是Run Configurations,而不是Java Application,则你的主函数可能错了。

【Scanner】类
扫描仪
scan 扫描

【println】
输出信息 换行打印
System.out.println(“”); 在控制台输出

[scan.nextDouble();]
double pay=scan.nextDouble();这句程序中,只有在你用键盘输入一个double型的数字后才会开始运行这句程序之后的程序。重点是scan.nextDouble();只针对这个。

[&]
Java变量只能包含数字、字母、下划线和$,而&不能在变量命名中使用,因此会出现编译错误
int &size=20; //用&是错误的
System.out.println(&size);


[jvm]
uitec/Common/binary/com.sun.java.jdk.linux.x86_1.6.0.013/lib/visualvm/visualvm/modules


【默认】
int共有10位数,long有19位数。
除了通常的十进制数字形式,整数直接量也可以写成16进制的形式(以0X或0x开头)或8进制的形式(以0开头),请看如下直接量三种表现形式:
int a = 100000; // 10进制
int b = 0x186a0; // 16进制
int c = 0303240; // 8进制
如果要表示long直接量,需要以 L 或 l 结尾。默认的是整形直接量int。示例代码如下:
long a = 10000000000; //会有编译错误,因为10000000000编译器认为是int类型,而这个值,已经超出了int的范围
long b = 10000000000l; //正确
默认的浮点直接量为double型,如果需要表示float类型的直接量,需要加“f”或“F”后缀。例如:
float f1 = 3.14 //编译错误,应该写成3.14f


[+]
int a = 1, b = 10;
int c1 = a++;
int c2 = ++b;
System.out.println("a=" + a + ", b=" + b + ", c1=" + c1 + ", c2=" + c2);

程序运行出来的结果
a=2, b=11, c1=1, c2=11

[计时操作]时间
JDK提供 System.currentTimeMillis() 方法,返回1970年1月1日零点到此时此刻所经历的毫秒数,数据太大,故其数据类型为long。示例代码如下:

long time = System.currentTimeMillis();
System.out.println(time); //输出的结果为: 1383835712828

通过上面的代码可以看出,输出的结果已经超出int类型的最大值,因此,JDK设计的返回类型为long型,该方法常常被用于计时操作。


【char类型】
字符类型char事实上是一个16位无符号整数(都是正数),这个值是对应字符的编码,Java字符类型采用Unicode字符集编码(通用码、统一码、万国码)
,而Unicode是世界通用的定长字符集,所有的字符都是16位来表示。例如:字符a实际的值为97,字符A实际的值为65,字符0实际的值为48。
字符直接量可以采用诸如:‘中’的形式,也可以采用16进制的表示形式,例如: ‘\u4e2d’,代码如下所示:
char c1 = ‘中’; //c1中存的是”中”的编码
char c2 = ‘\u4e2d‘; //‘4e2d’为‘中’所对应的16位Unicode编码的16进制表示形式
System.out.println(c1);
System.out.println(c2);
如上代码的输出结果:c1的值为中,c2值也为中,但c1和c2内部存储的其实是”中”这个字符所对应的Unicode码,即:一个无符号的整数。
对char型变量赋值
char abc=‘1‘;
System.out.println(abc); //输出1
System.out.println(abc+1); //输出50
char abc=1;
System.out.println(abc); //输出
System.out.println(abc+1); //输出2

在对char型变量赋值时,可以采用如下三种方式:
方式一:
字符直接量:形如‘A’,变量中实际存储的是该字符的Unicode编码(无符号整数值),一个char型变量只能存储一个字符。示例如下:

char c1 = ‘A‘;

方式二:
整型直接量:范围在0~65535之间的整数,变量中实际存储的即该整数值,但表示的是该整数值所对应的Unicode字符。示例如下:
char c2 = 65;
Unicode形式:形如‘\u0041’,Unicode字符的16进制形式。示例如下:
char c3 = ‘\u0041‘;

使用转义字符
char c = ‘\\‘;
System.out.println(c); //输出的结果为:\
‘\n‘ 表示回车符
‘\r‘ 表示换行符
‘\\‘ 表示反斜杠(\)
‘\‘‘ 表示单引号(‘)
‘\"‘ 表示双引号(")
‘ ‘ 表示空格符
“\t” 输出时,空格 //System.out.println(c+“\t”);
System.out.println("请选择功能:\n 1.查看余额 2.取款 3.缴电话费");


【boolean】
boolean类型适用于关系、逻辑运算, 表示某个条件是否成立, 只允许取值true或false,true表示条件成立, 而false表示条件不成立。
boolean型变量经常用于存储关系运算的结果,所谓关系运算就是比较两个变量的大小相等等关系(此知识点,后续详细介绍)。boolean示例代码如下所示:

int age = 18;
boolean isChild = age<16;
System.out.println(isChild); // isChild的值为false
boolean running = true;
boolean closed = false;


【变量命名】 值 //引用命名 对象 八种基本数据类型以值的形式存在于内存中,而不是对象
在java语言中,对于变量、常量、方法、类、包等等都有名字,将这些名字统一称之为java标识符,标识符的命名规则如下列表所示:
可以由字母、数字、“_”或“$”符组成,但是不能以数字开头。
中文可以作为变量名,但不提倡使用。
Java大小写敏感,即:严格区分大小写,在给命名变量时需要注意。
不能使用Java保留字(一些Java语言规定好的,有特殊含义的字符),如:int、if、else、for、break等。


【赋值】
public static void main(String[] args) {
int a, b = 10;
int c = a + b; // 编译错误 变量a并未赋初始值就直接使用了,违反了java语法的规定,变量使用之前必须初始化
System.out.prinltn(c);
}

public static void main(String[] args) {
int sum = 0; //声明同时初始化

int a = 5;
int b = 6;
sum = a + b;
System.out.println(sum);
}

public static void main(String[] args) {
int sum;
sum = 0; // 在使用sum变量之前对其进行初始化。
sum = sum + 100;
System.out.println(sum);
}


int b,c,d; //声明3个变量

 

 

 

 

【溢出】
两个整数进行运算时, 其结果可能会超过整数的范围而发生溢出,正数过大而产生的溢出,结果为负数;负数过大而产生的溢出,结果为正数。示例代码如下所示:

int a = 2147483647; //int类型整数的上限
int b = -2147483648; //int类型整数的下限
a = a + 1;
b = b - 1;
System.out.println("a=" + a); //输出结果: a=-2147483648 溢出,结果错误。
System.out.println("b=" + b); //输出结果: b=2147483647溢出,结果错误。
如果可能溢出时,把相乘的几个数中的第一个加上L/l,如果加在最后面,可能数在前面就已经溢出了,再加就没意义了。

初始化时超多21亿多则是编译错误,运算时超过21亿多则是溢出。


【数据类型】八种基本数据类型
boolean byte char short int long float double


String 字符串

int[] 非基本的数据类型(引用类型)

byte b1 =20>>>1;
byte b1 = 10;byte b=b1++;
byte b1 = 10, b2 = 20;byte b=(byte)(b1+b2);

【类型转换】
byte->short->int->long->float->double
char->int->long->float->double
强制转化:从大类型到小类型需要强制转换符,语法如下:
因为大类型的精度值大于小类型,取值范围大于小类型,所以,当使用强制转化时,有可能会造成精度的损失或者溢出,
所以,在使用强制转化时要求显式的告诉编译器,正在进行强制转换。
int a = 100;
int b = 200;
long c = a + b; //自动将int转化为long
long l1 = 1024l;
int i = (int) l1; //需要加强制转化符由于1024在int的范围内,所以没有产生溢出
long l = 1024L * 1024 * 1024 * 4;
int j = (int) l; //会产生溢出
System.out.println(j); // 结果为:0
double pi = 3.1415926535897932384;
float f = (float) pi; //会造成精度的损失,因为单精度的精确度小于double
System.out.println(f); //结果为:3.1415927

如果在一个表达式中出现了多种数据类型,则运算结果会自动的向较大的类型进行转化,
//由于有long型的直接量参与,整个表达式的结果为long
long distance = 10000 * 365 * 24 * 60 * 60 * 299792458l;
//由于有double型的直接量599.0参与,整个表达式的结果为 double
double change = 800 - 599.0;
//结果为0.0,右边都是int型数据运算结果也为int类型,结果为0,再赋值给double
型,将0转化为 0.0
double persent1 = 80 / 100;
//结果为0.8,右边表达式有double型直接量参与, 运算结果为double型
double persent2 = 80.0 / 100;

int直接量可以直接赋值给byte、char和short,只要不超过其表示范围。示例如下:
byte b = 97;
short s = 97;
char c = 97;

byte、char、short三种类型参与运算时,先一律转换成int类型再进行运算。示例如下:
byte b = 97;
int num = b + b; //num的值为194

byte b1=5;
byte b2=6;
//byte b3=b1+b2; //编译错误
byte b3=(byte)(b1+b2);
int b3=b1+b2;


【MyEclipseGen】
先拖入MyEclipse 8.6软件的一个包内,然后给这个类加一个包名,然后运行,填一个用户名,回车就可以得到注册码
然后在工具栏的MyEclipse中的第五个Subscription Information栏进行注册。

【运算符】
【算术运算符】
+ - * / % ++ --
%:取模运算 意为取余 例子:5%2 取余为1 ;2%8 取余为2 ;8.567%2 取余为0.567
++/-- : 单独使用时a++,在前在后无差别;被使用时c=a++,在前在后有差别。
a++>5,是先用a和5来比,之后a再加一;++a>5,是先用a加一,之后再与5来比。
扩展赋值运算符,比较推荐,因为方便。
a += 10; //相当于a=a+10
a *= 2; //相当于a=a*2
字符串拼接运算符
+
若两边都是数字,则做加法运算
若有一边是字符串,则做字符串拼接 例如:(“age=”+age+“岁了”) //age=37
则输出 age=37岁了
String a=100+“”+300; //“100”+300 输出100300
String a=”“+100+300; //“100”+300 输出100300
Steing b=100+300+“”; //400+“” 输出400
System.out.println(2+2) // 输出4
System.out.println(‘2’+‘2’) // 输出100
System.out.println(2+”2“) // 输出22


【关系运算符】
Java中的关系运算符用于判断数据之间的大小关系,包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(= =)、不等于(!=) 六个运算符。
= =:是等于号; =:是赋值。

【逻辑运算符】
与(&&) 两个都要对 一个&指不会短路的与
或(||) 两个只要有一个对 一个|指不会短路的或
非(!) 一个反着来
逻辑运算的结果还是boolean型。

Java逻辑运算中的&&和||有短路的特性,当第一个关系表达式就可以判断出整个表达式的结果时,就不会再去判断后面的第二个表达式。
对于“&&”,当第一个操作数为false时,将不会判断第二个操作数,因为此时无论第二个操作数是什么最后的结果一定是false;
对于“||”,当第一个操作数为true时,将不会判断第二个操作数,因为此时无论第二个操作数为何,最后的运算结果一定是true。
示例代码如下所示:
int i = 100, j = 200;
boolean b1 = (i > j) && (i++ > 100);
System.out.println(b1); // 结果为:false
System.out.println(i); // 结果为:100,发生短路,i++不会被执行
boolean b2 = i > 0 || j++ > 200;
System.out.println(b2); // 结果为:true
System.out.println(j); // 结果为:200,发生短路,j++不会被执行

赋值运算符
字符运算符
三目运算符


一元运算符:! ++ --
二元运算符:+ - * /
三元运算符:

条件运算符又称“三目”运算符,其结构为:boolean表达式 ? 表达式1:表达式2。
条件运算符的规则如下: //?: ?:
先计算boolean表达式;
如果boolean表达式的值为true,整个表达式的值为表达式1的值;
如果boolean表达式的值为false,整个表达式的值为表达式2的值。
示例代码如下:
int a = 100, b = 200;
int flag = a > b ? 1 : -1; //因为a>b为false,所以整个表达式的值为-1,将其赋给flag,即:flag的值为-1。


【if】
(1)
int a=scan.nextInt();
if (a>10){
if(a>20){
System.out.println("A");

}else{
System.out.println("B");
}

}else{
System.out.println("C");
}


(2)
if(score>=90) {
System.out.println("A");
} else if (score>=80) {
System.out.println("B");
} else if(score>=60) {
System.out.println("C");
} else {
System.out.println("D");
}

 

【SWITCH】
int num = 2; //可以用 byte short char int
switch(num) {
case 1:
System.out.println(“呼叫教学部”);
break; //跳出switch
case 2:
System.out.println(“呼叫人事部”);
break;
default: //所有case都没有匹配时执行。
System.out.println(“人工服务”);
}
从JDK 7.0开始,switch-case可以支持字符串表达式,将更加方便程序的操作。

【循环结构】
(while、do…while、for)
while( boolean表达式 ) {
}
while语句的执行过程为,首先计算boolean表达式的值,而后进行判断,若值为true则执行语句块,语句块执行完后再次判断boolean
表达式的值,如果为true则继续执行语句块,如此循环往复,直到boolean表达式的值为false时退出while循环而执行while之后的语句。
int x = 0;
while ( x < 10 ) {
if ( 5 == x )
{
break;
}
System.out.println(x);
x ++ ;
}
分析上面的代码得出结论,输出结果为0 1 2 3 4,因为当x等于5时执行break语句直接退出循环结构了,即if语句块后面的输出x的值以及x++不再被执行。

do-while
do-while语句的执行过程为,先执行语句块,再判断boolean表达式,如果为true则再次执行语句块,如此循环往复,直到boolean表达式的
值为false时止。也就是说,do-while语句,无论boolean表达式是否为true,都先执行一次语句块。
do {
语句块
} while( boolean表达式 ) ;

注意:while和do-while语句的不同仅仅体现在第一次就不满足条件的循环中;如果不是这样的情况,while与do-while可以互换。
示例1:while循环方式
int pwd = 0;
while ( 123 != pwd){
System.out.print(“密码:”);
pwd = scanner.nextInt();
}
示例2: do-while循环方式
int pwd ;
do{
System.out.print(“密码”);
pwd = scanner.nextInt();
} while ( 123 != pwd) ;

分析示例1与示例2得出结论,运行结果完全一样。这是因为两段代码第一次的while条件都满足,此时while与do-whlie可以互换,所以结果完全一样。

示例3:for循环变量
for ( 表达式1;表达式2;表达式3 ) {
语句块(循环体)
}
for(int count =0;count<10;count++){ //1 2 3
System.out.println("行动是成功的阶梯"); //4
}
例子1.1:
int j = 0;
for(int i = 0;i < 100;i++){
j = j++;
}
System.out.println(j); //输出j=0
例子1.2:
int j = 0;
for(int i = 0;i < 100;i++){
j++;
}
System.out.println(j); //输出100
例子:1.3
int j = 0;
int c = 0;
for(int i = 0;i < 100;i++){
c=j++;
}
System.out.println(c); //输出99
程序运行顺序是1 2 4 3 2 4 3 2 4 3 2
for语句,首先计算表达式1,接着执行表达式2,若表达式2的值等于true,则执行大括号中的语句块,接着计算表达式3,
然后再判断表达式2的值。依次重复下去,直到表达式2的值等于false。
1可以挪到上面,3可以挪到下面,但分号不可以省。2如果省了就变成无限循环。

for ( int i =1 , j = 6 ; i <= 6 ; i +=2 , j -=2 ) {
System.out.println(“ i , j = “ + i + “,” + j );
}
上面的代码的执行逻辑如下:
i , j = 1 , 6
i , j = 3 , 4
i , j = 5 , 2


【continue】
continue语句只能用于循环中,它的作用为跳过循环体中剩余语句而执行下一次循环,
int sum = 0;
for(int i=1; i<=100; i++){
if( i % 10 == 3 ){
continue;
}
sum += i;
}
System.out.println(sum);

上面的程序需要统计1到100的累加和,条件是跳过所有个位为3的,此案例通过在if语句中使用continue
实现了跳过for语句中剩余的循环体语句,本程序最终sum的值为: 4570。


int sum = 0;
for(int i=1; i<=100; i++){
if( i % 10 != 3 ){
sum += i;
}
}
System.out.println(sum);


【循环问题】
如果业务可以转换为“当……“这样的句式时,优先选择while语句来实现。
如果业务可转换为”直到……”这样的句式时,优先选择do-while语句来实现。
如果业务中可以获取到一个确切的循环次数时可以考虑使用for循环来实现,
循环嵌套 外面循环走一次,内面循环走所有次。


【数组】数组是一种非基本的数据类型(引用类型)
数组为相同数据类型的元素组成的集合,数组元素按线性顺序排列,所谓线性顺序是指除第一个元素外,每一个元素都有唯一的
前驱元素;除最后一个元素外,每一个元素都有唯一的后继元素(“一个跟一个”),可以通过元素所在位置的顺序号(下标)
做标识访问每一个元素(下标从0开始,最大到元素个数-1)


int[] arr=new int[4]; //一个整型数组 //声明int型数组arr,包含4个元素。且每个元素都是int型,每个元素默认为0
double[] arr=new int[4]; //声明double型数组arr,包含4个元素。且每个元素都是double型,每个元素默认为 0.0
boolean[] arr=new int[4]; //声明boolean型数组arr,包含4个元素。且每个元素都是boolean型,每个元素默认为false
byte short char int long 为0
float double为0.0
boolean 为false
注意char的默认值是0(码)而不是‘0’(字符)所代表的48.


int[] arr={1,3,5,7}; //4个元素,分别是1,3,5,7
int[] arr=new int[]{1,3,5,7}; //4个元素,分别是1,3,5,7

int[] arr;
arr={1,3,5,7}; //编译错误,{}赋值只能声明的同时初始化
arr=new int[]{1,3,5,7}; //正确


int[] arr=new int[4];
System.out.println(arr.length); //数组的长度是4 arr.length指数组的长度

int[] arr=new int[]{1,3,5,7};

System.out.println(arr[arr.length-1]); //输出arr中的最后一个元素
例子:
int[] arr = new int[10];
for ( int i = 0 ; i < arr.length ; i ++ ){
arr [ i ] = 100;
}

正序输出:
int[ ] arr = new int [ ] {10,20,30,40,50 } ; //正序输出
for ( int i=0; i< arr.length; i++) {
System.out.println ( arr[ i ] ) ;
}
逆序输出:
int[] arr5 = new int[] {10,20,30,40,50 } ; //逆序输出
for ( int i = (arr5.length -1) ; i >= 0 ; i -- ) {
System.out.println ( arr5[ i ] ) ;
}


【数组的复制】
一:System.arraycopy
public static void arraycopy(Object src, int srcPos,Object dest, int destPos, int length)
如上代码的,每一个参数的意义见下列表:
src:源数组
srcPos:源数组中的起始位置
dest:目标数组
destPos : 目标数组中的起始位置
length:要复制的数组元素的数量
通过下面的代码,可实现数组的复制:
int[ ] a = { 10 ,20 ,30 ,40 ,50 };
int[ ] a1 = new int[ 6 ] ;
System.arraycopy( a , 1 , a1 , 0 , 4 ); //结果:20,30,40,50
如上方法的意义可以理解为:将a数组的从下标1(第二个)开始的4个元素复制到a1数组中,a1数组从下标0位置开始赋值。
程序执行完后,a1的值为20,30,40,50,0,0。其交互效果如图 – 3所示:

二:Arrays.copyOf()方法示例代码如下所示:
int [ ] a = { 10,20,30,40,50 } ;
int [ ] a1 = Arrays . copyOf ( a, 6 );

上段代码执行后,a1的结果为:10 20 30 40 50 0,分析其执行过程为:声明一个整型数组,数组变量名称为a,赋初始值为10 20 30 40 50,
声明整型数组a1,将a数组数据复制到a1数组,设置其为6个长度,因a数组只有5个元素,所以最后一位补0。故而输出结果为10 20 30 40 50 0。
总结出Arrays.copyOf()方法的特点如下列表所示:
生成的新数组是原始数组的副本;
newLength小于源数组,则进行截取;(自己通过代码演示效果);
newLength大于源数组,则用0或 null进行填充;


System.out.println("新数组中的数据"+Arrays.toString(arr)); //显示整个数组
//新数组中的数据[71, 45, 66, 90, 58, 91, 5, 44, 43, 50, 91]


【排序算法】
常用排序算法有:插入排序、冒泡排序、快速排序等。

long a=System.currentTimeMills();
冒泡算法 //3000毫秒
long b=System.currentTimeMills();
System.out.println(b-a); //得3000毫秒


Arrays.sort(arr)比冒泡排序要块 //升序排列 arr是函数的名称
System.out.println("新数组中的数据"+Arrays.toString(arr));

int[] a=new int[]{1,0,1,0,1,5,5,8};
int[] b=new int[]{5,5,98,4,2,3,5,4,5,4,2,5,4};
System.arraycopy(a,0,b,0,5); //a,0,b,0,5(长度不可以长于上面的也不可以长于下面的)
System.out.println(Arrays.toString(b));

 

【方法】(函数,过程)
方法常常用于封装一段特定的逻辑功能,例如:执行计算或操作
方法可以在程序中反复被调用,这样,就可以减少代码的重复,更便于程序的维护。

oid say() { } //无参方法
void say( string name ) { } //1个参数方法
int sum ( int num1 , int num2 ) { } //2个参数方法


【返回值】
若方法不需要返回数据,将返回值类型声明为void。
若方法需要返回数据,将返回值类型声明为特定数据类型。
方法的返回值 取钱 要返回值(返回钱) 存钱 可以没有返回值,没有凭条(因为网上数据已经改了)
int num

 

【参数】
double b=Math.sqrt(9);
有参数

double b=Math.random();
没参数

public static int sum(int num1 , int num2 ){ }
修饰词 返回值 方法名 参数 方法体

public static void s(){} //无参,void表示无返回值

 

 


sayHello2(); //System.out.println();不需要这个
//无参无返回值
public static void sayHello2(){
System.out.println("大家好,我叫张三");
}


double num=sayHello3(); //
System.out.println(num); //250.25
//无参有返回值
public static double sayHello3(){
return 250.25; //return;编译错误,必须返回一个值 return “wkj”;编译错误,返回值类型不匹配
}

 

sayHello("zhangsan"); //sayHello();编译错误,没提供参数 //sayHello(25);编译错误,参数类型不匹配 //System.out.println();不需要这个
//有参无返回值
public static void sayHello(String name){
System.out.println("大家好,我叫"+name);
return; //仅仅表示方法结束
}

 

int b=sayHello4(2,5);
System.out.println(b);
//有参有返回值
public static int sayHello4(int num1,int num2){
int num =num1+num2;
return num;
}

 

 

 

salary:薪水 demo:演示 var:定义变量 score:成绩 DataTypeDemo:数据类型演示 UnitPrice:单价 qty:数量
cost:花费 count:计数 correct:正确的 Error:错误 Date:日期 index:下标 array:数组 letter:字母
flag:插旗 cell:格子 info:信息 row:行 col:列 drop:向下 Override:重写 Overload:重载
area:面积 square:正方形 shape:图形 circle:圆形 circumference:周长 remove:移动 set:设定
add:增加 subtract:减去 Bill:账单 drawMoney:取款 getBalance:查询余额 award:奖品 checkPwd:检查密码
IDcard:身份证postalCode:邮编value:价值 compare:比较 matches:比较 util:有用的 regex:正则表达式
identitycard//Pattern:模式 Syntax:语法 Format:格式 Bounds:出界 Cast:造型

${cursor} 光标(用来设置快捷键)

android

RelativeLayout 相对布局
LinearLayout 线性布局
TableLayout 表格布局
FrameLayout 帧布局
GridLayout 网格布局
TableRow 表格行
TextView 显示文本的组件
Adapter 适配器

 

stretchColumns 伸展 设置网格的列数
android:stretchColumns="0,1,2"> <!--拉伸使平均分布 -->
android:stretchColumns="1" android:shrinkColumns="1"这两个属性是TableLayout所特有的,也是这两个属性影响了子对象的布局。 表格布局是按照行列来组...

 

classCastException:类型转换异常

 

 

 

 

class Var{
int a; //实例变量 //属于成员变量
static int b; //类变量,静态变量 //属于成员变量
public void display(String str1){ //参数变量
String str2; //局部变量
}
}

 

取反 ~3 等于-4

 

 

 

 

 

 

 

 

 


第二本书:面向对象
【面向过程】
面向过程的结构化程序设计
/** 打印员工信息的方法 */
public static void printEmpInfo(String name,int age, //面向过程
char gender,double salary) {
System.out.println("--------------------");
System.out.println("姓名: " + name);
System.out.println("年龄:" + age);
System.out.println("性别:" + gender);
System.out.println("薪水:" + salary);
}
/** 打印雇员信息 */
public static void main (String[ ] args ){
//雇员1
String emp1Name = "黄河大虾";
int emp1Age = 25;
char emp1Gender = ‘男‘;
double emp1Salary = 8000.00;
//打印员工信息
printEmpInfo(emp1Name, emp1Age, emp1Gender, emp1Salary);
//修改员工工资(增长20%)并打印
emp1Salary *= 120.0 / 100.0;
printEmpInfo(emp1Name, emp1Age,emp1Gender, emp1Salary);
}


【抽象数据类型】(自己创造数据类型)
面向对象的第一步就是抽象数据类型,所谓抽象数据类型可以理解为:
将不同类型的数据的集合组成个整体用来描述一种新的事物。像如上程序中,可以将姓名String、年龄int、性别char、工资double这4个不同类型的数据组成一个整体来描述雇员这个新事物。


【面向对象】
【类】 //雇员类,一种数据类型(非基本的)
类定义了一种抽象数据类型,而类不但定义了抽象数据类型的组成(成员变量),同时还定义了对该类型可以实施的操作(方法)。看如下代码定义了雇员类:
1.类,一种数据类型
2.现实生活中是由很多很多对象组成的
基于这些对象,抽出了类(动物是类,姚明是对象)
3.对象是一个真实的个体。类为类别。
4.类可以包含:
a.所有对象所共有的特征/属性-------数据(变量)
b.所有对象所共有的行为---------对数据的操作(方法)
5.一个类可以创建多个对象
同一个类创建的对象,结构相同,数据不同。

6.引用类型间画等号:指向同一个对象; Cell c1=new Cell(); Cell c2=c1; //有new
对一个数据的修改,会影响另一个
基本类型间画等号:赋值 int a=5; int b=a;
对一个数据的修改,不会影响另一个

7.null:空,不再指向任何对象。不能做任何操作。

/**进一步修改后的雇员类*/
public class Emp{ //面向对象
String name;
int age;
char gender;
double salary;
/**打印信息的方法*/
public void printInfo() { //定义在类中,可直接对成员变量进行操作
System.out.println("--------------------");
System.out.println("姓名: " + name);
System.out.println("年龄:" + age);
System.out.println("性别:" + gender);
System.out.println("薪水:" + salary);
}
}
/**针对修改后的Emp类的使用方式*/
public class EmpManager {
public static void main(String[] args) {
Emp emp2 = new Emp(); // cell c = new cell();
// 类(变量) 引用 对象 //类引用对象 变量引用对象
emp2.name = "白发馍女";
emp2.age = 24; //对象.
emp2.gender = ‘女‘;
emp2.salary = 6000;
/**调用方法打印信息*/ //创建完Emp对象后,对其成员变量赋值,然后调
emp2.printInfo(); //用其printInfo()方法打印各个成员变量信息
emp2.salary *= 125.0 / 100.0;
emp2.printInfo();
}
}
java中一个对象引用先后指向两个对象时,前一个对象是否是被释放掉?
第一个new的数组对象失去引用,会被垃圾回收器回收
java内存管理机制比较特殊,并不是对象不被引用了就会马上回收,也就是仍然在内存中,
直到垃圾回收器执行回收操作,不过这些java底层有一套机制,我们暂时不用纠结他什么时候释放内存
只要引用释放掉就可以了


通过上面的代码,很好的实现了对数据的封装,并且实现了数据与方法的统一。这种方式即为面向对象方式,即:以对象为中心来构建软件系统。

 

成员变量的默认值 //赋初值
定义好类之后,可以创建该类的对象,对象创建之后,其成员变量可以按照默认的方式初始化;对象成员变量的默认初始化值规则如下图 - 5所示:
byte short int long float double 默认值 0
boolean 默认值 false
char 默认值 \u0000 无
引用类型 默认值 null //String 雇员类 引用数组 默认值 null //基本类型数组的初始默认值为具体值


对象是一个客观存在的实体,是面向对象编程过程中分析与解决问题的出发点与基础。对象的实质就是内存中的一块数据存储区域,其数据结构由定义它的类来决定。

类是用于构建对象的模板,对象通过类的实例化产生,一个类可以创建多个对象,每个对象拥有自己的数据和行为。

 


class 类名 {
成员变量类型 变量名称;
………
返回值类型 方法名称(参数列表) {
方法体………
}
}

 

cell c = new cell(); //类引用对象
类 引用 对象

 

 


【方法的签名】
方法的签名包含如下两个方面:方法名和参数列表。
Java语法规定,一个类中不可以有两个方法签名完全相同的方法,即:一个类中不可以有两个方法的方法名和参数列表都完全相同,但是,如果一个类的两个方法只是方法名相同而参数列表不同,是可以的。

【方法的重载】
方法名相同,参数列表不同
class Aoo{
void say(){}
void say(String name){}
void say(String name ,int age ){}
void say(int age,String name){}
//void say(){return 1;} 编译错误和void say(){}重了
// void say(String address){} 编译错误和void say(String name){}重了
}

【构造方法】
通过构造方法初始化成员变量 //没有返回值
class Cell {
int row ; //成员变量 (堆中)在方法外
int col ; //成员变量
public Cell (int row1 , int col1){ //构造方法不需要返回值 //局部变量(栈中) 在方法内
row = row1; //默认指this.row = row1; 指c1.row=row1; c1.row=15;
col = col1;
}
}
class TestCell {
public static void main(String args[ ] ){
Cell c1 = new Cell( 15 , 6 );
printCell(c1);
}
}
1.常常用于给成员变量赋初值
2.语法与类同名,没有返回值
3.在创建对象new自动调用
4.若自己不写构造方法,则系统会提供一个默认的无参构造;若自己写了,就不在提供空的 Cell c1 = new Cell(); // Cell(){}
5.构造方法可以重载


【this】
1)this.成员变量--------访问成员变量
2)this.方法名()----调用方法
3)this()------调用构造方法
this用来指代当前对象,哪个对象调用,就指那个对象
在方法中访问成员变量的前面,默认有一个this //T(int row,int col){ this.cells[0]=new Cell(row,col);}

this在成员变量和局部变量相同时,不能省略

【扩展:(this)】
1.this 是什么?
this 是一个引用,它的值指向对象,是一个对象的地址。
2.this 用在哪里?
this 应用在非静态方法内部,永远指向调用这个方法的对象。
FAQ? 一个类可以有很多个类的对象
那this具体指向哪个对象呢?
取决于哪个对象调用此方法。

3.this的使用形式?

1)this.属性/方法
2)this(参数列表): 应用在构造方法内部,
用于调用本类其它构造方法,并且只能写在第一行。

注意:在内部类中访问外部类的this时使用"外部类的名字.this";

row++ //默认为this.row++ //指c.row++ this就是指c

1)
class Cell {
int row ; //成员变量 (堆中)在方法外
int col ; //成员变量
public Cell (int row , int col){ //构造方法不需要返回值 //局部变量(栈中) 在方法内
this.row = row; //指c1.row=row; c1.row=15;
this.col = col;
}
}
class TestCell {
public static void main(String args[ ] ){
Cell c1 = new Cell( 15 , 6 );
printCell(c1);
}
}

 

2)Cell(){
this(0,0); //(0,0)可以写但没意义,不能是(0,0,0)
}
等于
Cell(int n){
this(n,n);
}
等于
Cell (int row , int col){
this.row = row;
this.col = col;


例子:
package day28;
class Good {
int a;
int b;
public Good() {
this(00); //没有这步就是输出0 0
}
public Good(int a){
this(15,16);
}
public Good(int a, int b) {
super();
this.a = a;
this.b = b;
}
}
class Test0{
public static void main(String[] args) {
Good t= new Good();
System.out.println(t.a+" "+t.b); //15 16
}
}

引用类型数组的声明
Cell [ ] cells = new Cell [ 4 ] ;
new Cell[4]实际是分配了4个空间用于存放4个Cell类型的引用,并赋初始值为null,而并非是分配了4个Cell类型的对象。

package oo.day02;
public class Array {
public static void main(String[] args) {
int[][] arr=new int[3][4];
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
arr[i][j]=100;
System.out.print(arr[i][j]+" ");
}
}

}

}


【super】
super();调用父类的无参数构造方法。可省略不写。 // super(5);调用父类的有参数构造方法
super.方法()----调用父类的方法
super.成员变量----调用父类的成员变量

【方法区】【内存】【JVM】
在JAVA中,有java程序、虚拟机、操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统交互。编译好的java字节码文件运行在JVM中。
程序中无论代码还是数据,都需要存储在内存中,而java程序所需内存均由JVM进行管理分配,
开发者只需关心JVM是如何管理内存的,而无需关注某种操作系统是如何管理内存的,这就保证了java程序的平台无关性。
JVM会将申请的内存从逻辑上划分为三个区域:堆、栈、方法区。这三个区域分别用于存储不同的数据。

堆内存用于存储使用new关键字所创建的对象;
栈内存用于存储程序运行时在方法中声明的所有的局部变量;
方法区用于存放类的信息,Java程序运行时,首先会通过类装载器载入类文件的字节码信息,经过解析后将其装入方法区。
类的各种信息(包括方法)都在方法区存储。
Foo foo = new Foo();
foo.f();
以上代码的内存实现原理为:
1.Foo类首先被装载到JVM的方法区,其中包括类的信息,包括方法和构造等。
2.在栈内存中分配引用变量foo。
3.在堆内存中按照Foo类型信息分配实例变量内存空间;然后,将栈中引用foo指向foo对象堆内存的首地址。
4.使用引用foo调用方法,根据foo引用的类型Foo调用f方法。

 

【堆内存】
【生命周期】
成员变量的生命周期
当声明好对象之后,对该对象(堆中的Cell)的访问需要依靠引用变量(栈中的c),那么当一个对象没有任何引用时,
该对象被视为废弃的对象,属于被回收的范围,同时该对象中的所有成员变量也随之被回收。
可以这样认为,成员变量的生命周期为:从对象在堆中创建开始到对象从堆中被回收结束。
【null】
请看如下的代码,演示了对象不再被引用:
Cell c = new Cell();
c = null ;
当将c赋值为null时,表示c不再指向刚刚分配的对象空间,此时成员变量失效。 //没有地址,再不能指向任何东西
Cell c = new Cell();
Cell c1=c; //此时不会被回收,虽然栈中c不再指向堆中Cell,但栈中c1依然指向堆中Cell
c = null ;

【垃圾回收机制】 //堆
垃圾回收器(Garbage Collection,GC)是JVM自带的一个线程(自动运行着的程序),用于回收没有任何引用所指向的对象。
GC线程会从栈中的引用变量开始跟踪,从而判定哪些内存是正在使用的,若GC无法跟踪到某一块堆内存,
那么GC就认为这块内存不再使用了,即为可回收的。但是,java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。

【内存泄露】
Java程序的内存泄露问题
内存泄露是指,不再被使用的内存没有被及时的回收,严重的内存泄露会因过多的内存占用而导致程序的崩溃。在程序中应该尽量避免不必要的内存浪费。
GC线程判断对象是否可以被回收的依据是该对象是否有引用来指向,因此,当确定该对象不再使用时,应该及时的将其引用设置为null,这样,该对象即不再被引用,属于可回收的范围。

 


【非堆】----【栈】
栈用于存放方法中的局部变量
【生命周期】
局部变量的生命周期
一个运行的Java程序从开始到结束会有多次方法的调用。JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间称为该方法的栈帧。
一个栈帧对应一个正在调用中的方法,栈帧中存储了该方法的参数、局部变量等数据。当某一个方法调用完成后,其对应的栈帧将被清除,局部变量即失效。
main(){
Aoo o=new Aoo();
o.test(55); // 栈帧 正在调用中的方法 存储了该方法的参数、局部变量等数据。
}

成员变量和局部变量
成员变量与局部变量的差别如下:
局部变量:
1) 定义在方法中;
2) 没有默认值,必须自行设定初始值;
3) 方法被调用时,存在栈中,方法调用结束时局部变量从栈中清除;
成员变量:
1) 定义在类中,方法外;
2) 由系统设定默认初始值,可以不显式初始化;
3) 所在类被实例化后,存在堆中,对象被回收时,成员变量失效;

堆内存 非堆----栈 非堆----方法区

 

【方法区】
方法区用于存放类的信息,Java程序运行时,首先会通过类装载器载入类文件的字节码信息,经过解析后将其装入方法区。类的各种信息(包括方法)都在方法区存储
方法只有一份
当类的信息被加载到方法区时,除了类的类型信息以外,同时类内的方法定义也被加载到方法区;
类在实例化对象时,多个对象会拥有各自在堆中的空间,但所有实例对象是共用在方法区中的一份方法定义的。意味着,方法只有一份。看如下代码:
JFrame f1 = new JFrame();
JFrame f2 = new JFrame();
f1.setSize(200, 300);
f2.setSize(300,400);
如上的代码中,对象有两个,但是setSize方法只有一份,分别针对f1指向的对象和f2指向的对象调用了两次。

【继承】
泛化的过程
前面的案例中定义了T类和J类, 通过分析可以发现, 在这两个类中存在着大量的重复代码,像cells属性、print方法、drop方法、
moveLeft方法、moveRight方法,在这两个类中都存在,并且实现上基本也是相同的,本着代码重用的原则,可以使用继承的方式来实现。
首先,构建T类和J类的父类Tetromino类,将公共的(T类和J类公有的)信息存放在父类中, T类和J类继承Tetromino父类。此时,子类即可以共享父类的数据。这个过程就是泛化的过程。

【extends】关键字
使用继承可以实现代码的重用,在java语言中,需要通过extends关键字实现类的继承。继承完成后,
子类(Sub class)可以继承父类(Super class)的成员变量及成员方法,同时子类也可以定义自己的成员变量和成员方法。届时,子类将具有父类的成员及本类的成员。
需要注意的是,Java语言不支持多重继承,即:一个类只能继承一个父类,但一个父类可以有多个子类。看下面的代码:

【继承】:
目的:避免代码重复;
通过:extends;
父类:所有子类所共有的
子类:子类所独有的
一个子类只能继承一个父类;
继承具有传递性a继承->b; b继承->c;

 

【System.gc()方法】
GC的回收对程序员来说是透明的,并不一定一发现有无引用的对象就立即回收。一般情况下,当我们需要GC线程即刻回收无用对象时,
可以调用System.gc()方法。此方法用于建议JVM马上调度GC线程回收资源,但具体的实现策略取决于不同的JVM系统。

分析上面的代码,在子类构造方法中没有写super调用父类构造方法,这时编译器会默认添加super()来调用父类的无参构造方法,但是父类中又没有定义无参的构造方法,因此会发生编译错误。
针对上面的问题,可以有两种解决方案,方案一为在父类中添加无参的构造方法,
方案二为在子类构造方法中显示调用父类的有参构造方法(常常使用),这样可以保证父类的成员变量均被初始化,参见下面的代码:

class Goo extends Foo {
int num;
Goo(int value, int num) {
super(value);
this.num = num
}
}


【向上造型】
//动物是动物
Animal 01=new Animal();
//老虎是老虎
Tiger 02= new Tiger();
//一个新的老虎是动物
Animal 03= new tiger();
//动物是老虎 //编译错误,逻辑错误
Tiger 04=new Animal();

【向上造型】
(1)
Same t =new SameT(5, 5); //向上造型
printwall(t); //向上造型后传值

public static void printwall(Same same) { }
(2)
SameJ j= new SameJ(3,4);
printwall(j); //传值的同时向上造型

public static void printwall(Same same) { }

(A)
class Moo{
int m;
void show(){}
}
class Zoo extends Moo{ //隐藏一个Zoo(){super();} 隐藏一个无参构造,默认super();调用父类的无参数构造方法
int n;
void say(){}
}

Moo a=new Zoo(); //一个子类到父类
a.m=1;
a.show();
// a.n=2; //编译错误,只能点出父类的,能点出什么看类型,左边的。

///////

Zoo b=new Zoo(); //子类是子类 全可以点出来
b.m=1;
b.show();
b.n=2;
b.say();

Moo c=new Moo(); //父类是父类
c.m=1;
c.show();
//c.n=2; //编译错误,
//c.say(); //编译错误,

 


(B)
int row; // 行号
int col; // 列号
Cell(int row,int col){ //有参构造方法
this.row=row;
this.col=col;
}
Cell(int n){ //有参构造方法
this(n, n+1);
}
Cell(){ //无参构造方法
this(0,0);
}


【父类】
父类的构造方法不是被继承的,而是被调用的。

 

【重写】
在java语言中,子类可以重写(覆盖)继承自父类的方法,即方法名和参数列表与父类的方法相同,但是方法的实现不同。
Person p1 =new Person();
p1.sayHi(); //调用父类Person的。


Student s1=new Student();
s1.sayHi(); //调用子类Student的。
当子类重写了父类的方法后,该重写方法被调用时(无论是通过子类的引用调用还是通过父类的引用调用),运行的都是子类重写后的版本。看如下的示例:
class Foo {
public void f() {
System.out.println("Foo.f()");
}
}
class Goo extends Foo {
public void f() {
System.out.println("Goo.f()");
}
}
class Test{
public static void main(String[] args){
Goo obj1 = new Goo();
obj1.f();
Foo obj2 = new Goo();
obj2.f();
}
}

分析代码得出结论:输出结果均为“Goo.f()”,因为都是Goo的对象,所以无论是子类的引用还是父类的引用,最终运行的都是子类重写后的版本。

1.两同:方法名,参数列表相同
2.1)子类返回值类型小于或等于父类的:
1.1)父类void ------子类也必须是void
1.2)父类八种基本类型 ---子类也必须是八种基本类型
1.3)父类引用类型-------子类返回值类型小于或等于父类的
2)子类方法抛出的异常小于或等于父类
3.子类的访问权限大于或等于父类

 

【重载重写】
重载Overload: 是指在一个类中定义多个方法名相同但参数列表不同的方法,在编译时,根据参数的个数和类型来决定绑定哪个方法。看类型(编译器)
重写Override: 是指在子类中定义和父类完全相同的方法(方法名,参数列表都相同),在程序运行时,根据对象的类型(而不是引用类型)而调用不同的方法。看对象(运行器)
向上造型能点出什么看类型 强制类型转换 看对象

【包的概念】package语句
定义类时需要指定类的名称,但是如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突问题,
这会给组件复用以及团队间的合作造成很大的麻烦!因为原则上来说,类名是不可以重复的。
在Java语言中,命名冲突问题是用包(package)的概念来解决的,也就是说,在定义一个类时,除了定义类的名称一般还要指定一个包的名称,定义包名的语法如下所示:
package 包名;
需要注意的是,在定义包时,package语句必须写在Java源文件的最开始处,即在类定义之前,如下面的语句将为Point类指定包名为“test”:
package test;
class Point{
……
}
一旦使用package指定了包名,则类的全称应该是“包名.类名”,如上语句的Point类的全称为test.Point。
使用package即可以解决命名冲突问题,只要保证在同一个包中的类名不重复即可,而不同的包中可以定义相同的类名,
例如:test1.Point和test2.Point是两个截然不同的名称,虽然类名相同,但包名不同,亦表示两个完全不同的类。
在命名包名时,包名可以有层次结构,在一个包中可以包含另外一个包,可以按照如下的方法定义package语句:
package 包名1.包名2…包名n;

org.apache.commons.lang.StringUtil
如上类的定义可以分为4个部分,其中,StringUtil是类名,org.apache.commons.lang是多层包名,其含义如下:org.apache
表示公司或组织的信息(是这个公司或组织域名的反写);commons表示项目的名称信息;lang表示模块的名称信息。

同一个包内的类,可以直接引用
不同包内,不可以直接引用
要用 import 包名+类名 //引用两个同类名的类时 import p1.Aoo; import p2.Aoo; //p1.Aoo a=new p1.Aoo() ; p2.Aoo a=new p2.Aoo() ;

完全限定名 包名+类名 ---不建议p1.Aoo a=new p1.Aoo() ;


【封装】
封装的意义就是提供可调的稳定的功能
降低代码出错的可能性,更便于维护。
当内部实现细节改变时,只要保证对外的功能定义不变,其他的模块不需要更改。
在软件系统中,封装常常需要依靠一些访问控制修饰符来实现。

 

【访问修饰符】
public:公共的,任何地方都可以
protected:受保护的,本类,子类,同包类
默认的:什么也不写, 本类,同包类
private:私有的,本类
类只能用public或默认的来修饰
类中的成员或方法都可以


【static】 静态的
1. static修饰成员变量 静态变量
1.1)属于类的,而不属于对象
1.2)和类的信息一起存储在方法区,只有一份。
1.3)常常通过;类名来访问
1.4)何时用:所有对象都一样时
// Students.classname="JSD1503";
class Same { // 类的共同点,被继承的父类
Cell[] cells;
static int size; //
Same() {
this.cells = new Cell[4];
Same.size=100; //
System.out.println(Same.size);
}
}
2. static修饰方法 静态方法
2.1)没有this传递
2.2)静态方法中不能直接访问实例成员
可以直接访问静态成员 //但非static静态方法可以访问static成员(方法)
2.3)常常通过类名来访问
2.4)何时用:方法的操作与对象无关与成员变量无关,而仅与参数相关 //很少用 //Math.random();
3. static块 静态块
3.1)static块为属于类的代码块,在类加载期间执行的代码块,只执行一次,因为类只加载一次
3.2)可以用来在软件中加载静态资源(图像、音频等等)。

成员变量可分为
实例变量 不用static修饰
静态变量 static修饰

静态变量输出时,可以通过类名来访问
Ioo o1=new Ioo();
System.out.println(Ioo.b) ; //类.
System.out.println(o1.b) ; //可以但不建议


//方法中访问成员变量前面默认有个this

实例成员必须通过对象.来访问
静态方法没有隐式this

 

【final】
1)修饰变量:变量不可以被修改
1.1)成员变量: 声明同时初始化 构造方法中初始化 //之后就不可以在其他方法中改变其值的大小,不然就是编译错误
A)
class Loo{
final int a=100; //声明同时初始化
final int b;
Loo(){
b=200; //构造方法中初始化
}
void show(){
final int c; //用之前初始化即可 局部变量
//a=250; //编译错误,不可被修改
}
}
B)
public class Emp {
private final int no = 100; // final成员变量声明时初始化
public static void main(String[] args) {
no = 99;
}
}
如上的语句,no=99会出现编译期错误,因为final的变量不可被改变。
1.2)局部变量:在使用之前初始化即可
2)修饰方法:方法不可以被重写 //可以重载,不可以被重写
class Moo{
void show(){}
final void say(){}
void say(int a){}
}
class Noo extends Moo{
void show(){}
// void say(){} //无法被重写
}
3)修饰类:类不可以被继承
final class Moo{ //可以继承别人
void show(){}
final void say(){}
}
/*
class Noo extends Moo{ //Moo不能被继承
void show(){}
}
*/


【static final常量】
static final 修饰的成员变量称为常量,必须声明同时初始化,并且不可被改变。常量建议所有字母大写。
实际应用中应用率较广,因为static final常量是在编译期被替换的,可以节约不必要的开支,如下代码演示了static final的用法:
class Foo {
public static final int NUM = 100; //public final static int NUM = 100; static 和 final二者的前后顺序不限。
}
class Goo {
public static void main(String[] args) {
System.out.println(Foo.NUM); //类.
// 代码编译时,会替换为:System.out.println(100);
}
}
说明:static final常量Foo.NUM会在编译时被替换为其常量值(100),在运行Goo类时,Foo类不需要被载入。这样减少了不必要的开支。


【顺序】
新建引用了一个子类时:
父类静态块
子类静态块
父类成员变量
父类构造方法
子类成员变量
子类构造方法

//通过类调用静态方法时,会先加载类 //Config.getIntValue("port");
//静态方法不会被加载
//静态块和静态成员变量按顺序加载,哪个在前面先运行哪个
//静态块内有方法的话,会运行这个方法


【抽象类】【抽象方法】
抽象方法:由abstract修饰的方法为抽象方法,抽象方法即只有方法的定义,没有方法体实现,用一个分号结尾。
即方法五要素中,抽象方法缺少了一个要素(即:方法体)。也可以将抽象方法理解为不完整的方法。
若将抽象方法包含在类中,则该类也应该为抽象的,可以理解为,该类也不完整。抽象类由abstract关键字声明。
抽象类是不能实例化对象的,而一个类不能实例化是没有意义的,所以,需要定义类来继承抽象类,而如果一个类继承了抽象类,
则其必须重写其抽象方法(变不完整为完整),除非该类也声明为抽象类。看下面的代码,定义了抽象方法和抽象类:
没有抽象方法,也可以生成抽象类
abstract class Shape {
private double c;
public Shape(double c) {
this.c = c;
}
public abstract double area();
}

通过上面的代码可以看到,area()方法没有方法体(连大括号也不存在),由abstract修饰,此为抽象方法。而Shape方法也由abstract修饰,即为抽象类。
【抽象类不可以实例化】
抽象类不可以实例化,若Shape是抽象类的话,下面的代码是错误的: 不可以创建对象,但可以创建数组 Shape[] s1 = new Shape[4];
// Shape s1 = new Shape(); //代码是错误的
即使一个类中没有抽象方法,也可以将其定义为抽象类,同样,该类不可以实例化。
需要注意一点:abstract和final关键字不可以同时用于修饰一个类,因为final关键字使得类不可继承,而abstract修饰的类如果不可以继承将没有任何意义。两者放在一起,会起冲突。

【设计原则】
1.只要是几个类共有的方法,就搞到父类中。
2.所有子类的工作(方法)都一样时用普通方法
所有子类都不一样时用抽象方法。
3.符合既是也是关系时,使用接口。
----接口是对继承单根性的扩展

【继承抽象类】
一个类继承抽象类后,必须实现其抽象方法,不同的子类可以有不同的实现。看下面的代码,Square类与Circle类
都继承自Shape类,并分别实现了重写的area()方法,只是其具体实现的代码不同:
class Square extends Shape {
private double c;
public Square(double c) {
super(c);
}
public double area() {
return 0.0625*c*c;
}
}
class Circle extends Shape{
private double c;
public Circle(double c) {
super(c);
}
public double area() {
return 0.0796*c*c;
}
}

 

【抽象类的意义】
定义抽象类的意义在于:
为其子类提供一个公共的类型(父类引用指向子类对象); 公共的入口
封装子类中的重复内容(成员变量和方法);
定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的。(子类需要实现此抽象方法)。
看如下的代码:
Shape[] sArr = {new Circle(100), new Square(100),
new Circle(200), new Square(150) };
for(int i=0; i<sArr.length; i++) {
Shape shape = sArr[i];
System.out.println(shape.area());
}
通过上面的代码可以看出,以Shape类型的引用访问其子类,所有子类都会有area方法,只是其具体的实现各不一样。

 

【接口】 接口可以申明 成员变量 和int int[] 类一样
1)是一个标准,规范
实现了接口,就能干某件事-------API后就能体会
2)由interface定义
3)接口中只能包含常量(默认)和抽象方法(默认)
interface Inter{ //只有interface是默

以上是关于Java学习的一些基础笔记的主要内容,如果未能解决你的问题,请参考以下文章

[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段

Swift学习笔记——基础语法

C#学习笔记——需要注意的基础知识

关于JAVA 反射 基础知识/编码经验的一些总结

关于JAVA 异常 基础知识/编码经验的一些总结

关于JAVA 反射 基础知识/编码经验的一些总结