前言
特别基础,遗漏较多,在后期需要学习人员针对小标题知识点再过一遍
一段废话:
编程与哲学、数学是密不可分的,但是数学不好能不能学,当然能学,数学就是为了探索问题而存在,而编程是为了解决问题,二者相似,但是解决一个问题就像筑城,有很多角色,总得有不动脑的搬砖工,这个问题怎么解决不是你考虑得,你就是一搬砖的,根据当前的制度管理与欠薪数据显示写代码的跟干工地的很相似,工信部的发文也使用过IT民工这一称谓,一个筑的是真城,一个筑的是虚拟城,干个十年,你搬砖方法炉火纯青,一个砖有十八种搬法,恭喜你解决了一个了不起的问题:如何优雅的搬砖,这不是自嘲这是现状。另外入行后平时买点保健药,不然确实老的快,2年沧桑,5年油腻,十年秃头,电脑蓝光是不会骗人的。
java关键字
略;就是java语言的规则,关键字代表着某种秩序,后面会有编译器对其进行语法树的抽取之类的。
8种基础数据类型+字符串类型
boolean、byte、short、char、 double、 float、int、long 与 String
必须死记硬背,至于32位,8bit这种详细知识前期不作了解,会用就行
权限修饰符
private、public、protected、default(default不写)
都是权限修饰符,一般放在类名、方法名、变量前面,java有且只有这四个权限修饰符,作用是为了限制访问范围,java里的访问范围主要是包与类、父与子的限制,java工程里要先建一个包(可以看作一个特殊文件夹),才能建各种类,包名为防止重复一般是 公司域名倒置为前缀+模块名+功能名,例: com.duck.gaga.eat、com.duck.gaga.drink
举个权限修饰符对包与类访问范围限制的例子:
包A
类1
private 变量a
类2
protected 变量b
包B
类3
变量c
类4
public 变量d
1个包=n个类,1个类=n个方法+n个变量,类、方法、变量都可以设置被别人访问的权限,private
只能是本类访问,so想操作变量a只能在类1里,变量d是public
的是全局公开的,在类1、2、3都可以对变量d进行读取、修改之类的,后期自会理解深意,前期会用即可,default就是不写,譬如int i=0;
没有权限修饰符,其实就是default,实战中除了protected其它比较常用,private存在的意义之一就是类里内部自用的方法
尽量不要被外部看见,so用private修饰。
条件语句
当人嘲讽的时候顺口而出的就是,不就是if-else么有什么难得,说得就是这个条件语句,java条件分支语句共两种if-else、switch-case
if-else写法:
if(判断1){ //判断1一般我们称为表达式
}else if(判断2){
}else{
}
int n=0,j=1,e=3;
int i=1;
if(n>1){
//n>1时走这个逻辑分支,其它分支自动跳过
}else if(i==1){
//i==1时走这个分支
if(j<0){
if(e>=3){
//if语句可以嵌套,但是不宜过深嵌套过深会导致逻辑过于复杂
}
}
}else{
//上述if都不匹配走这个else分支,else分支不是必须的,可以没有
}
有人问如果n>1,i==1的条件都符合怎么办?
答:if-else分支按照从上至下的顺序顺位执行,哪个条件先符合进入哪个分支,其它分支跳过,
譬如n=2,i=1时上述n>1的分支先进入,则其之后的i==1的逻辑分支就不会执行了,
switch-case:
switch(变量){
case 常量值1:
break;
case 常量值2:
break;
}
break
是java的高频关键字,中断的意思,哪里都能写,万金油的角色,条件分支中代表着退出整个条件判断,如下写法1,
grade为'A'时,控制台输出“优秀”,退出整个switch判断。
grade为'B'时,控制台输出
上等
良好
因为'B'、'C'之间没有break
;执行完'B'逻辑后,逻辑没有退出会往下顺序执行'C'的逻辑
为'C'时输出结果为“良好”,default
是switch的语法,当所有条件不满足时会执行它这块逻辑,也可以省略,省略后代表当前分支逻辑没有缺省状况
char grade = 'C';
//写法1(完整的):
switch(grade)
{
case 'A' :
System.out.println("优秀");
break;
case 'B' :
System.out.println("上等");
case 'C' :
System.out.println("良好");
break;
case 'D' :
case 'E' :
System.out.println("及格");
break;
case 'F' :
System.out.println("你需要再努力努力");
break;
default :
System.out.println("未知等级");
}
//写法2(常用写法):
int fee;
switch(fee){
case 1:
System.out.println("请支付1元");
case 10:
System.out.println("请支付10元");
break;
case 10000:
System.out.println("您支付不起,请出门左转,记得关门么么哒!");
break;
}
变量定义
语法固定格式:权限修饰符+数据类型+变量名
,但是方法
里的变量定义不使用权限修饰符(因为在后面的知识点会对变量进行分类,成员变量,静态变量之类的,已经约束了其使用范围,java的设计者就不会再对其进行修饰符的访问限定)
public void duckSay(){
//这里的变量不用修饰符,会报错,它的使用范围是在当前方法内
int i=4;
}
变量的定义是1.声明 2.赋值;可以先声明不赋具体值如private int fee;
,在某个方法或者某个地方进行具体赋值,也可以连写在定义时就进行赋值private int fee = 5;
private int fee=5;
float miniFee=1.2f; //float数字后需加f表示浮点型
int[] oneFee={3,5}; //数组是特殊对象类型,学习完封装类后解锁
public static String = "天地玄宗,万炁本根";
java里的数据类型有如下几种:
1、8种数据类型
2、对象类型(在学习面向对象的知识后解锁这种类型知识)
static是关键字也是修饰符,作用是免去实例化,在学完面向对象的实例化知识后解锁,当前仅作了解
运算符
java里的运算符大致可分为:算术运算符、关系运算符、位运算符、逻辑运算符、赋值运算符、其他运算符
算数运算符:就是+-x% ++(自增运算符) --(自减运算符)
自增运算符:不用纠结++i还是i++这种问题,for循环打印出值时候自然就会了。
for(i=0;i<5;i++){
int n=6;
i++;
}
关系运算符:一般用于if语句里,==、!=、>、<、>=、<=
小学数学。
int i=0;
if(i++>=3){
//满足条件进入
}
位运算符:表层开发一般难以用到,忽略。
逻辑运算符:常用的为&&、||、!
,一般用于if语句里,大致有&、&&、|、||、!
。
&&
称为“逻辑与”英文and的意思,||
为“逻辑或”英文or的意思,!
为“逻辑非”英文not得意思
if(i>3&&n<5){
//两者都符合才进入
}
int k=5;
if(!k>5){
//逻辑非就是对true、false取反的意思,此处对k>5进行取反意思为k<=5,故符合条件。
}
注意,!false的逻辑结果是true,逻辑假+逻辑假=逻辑真,真假为假,假真为假,真真为真,高中的知识,此处若看不懂没关系,一句话就是左边条件与右边条件共同作用产生的逻辑结果,写两行一眼就会。
问:&
与&&
有何区别?
答:&&
具有短路的作用,譬如 if(n<1 && fee<50){}
左边的n若为false &&
此时就会短路不会再判断右边逻辑即fee<50,但是&
会再次判断造成计算资源浪费,||
也类似具有短路功能。
三目运算符:固定格式:V=A>B?C:D
,?
与:
是两个关键字符
三目运算符是对if else语句的简化,意思为 A>B?是的话V=C,否的话V=D。
//举例
int num1=5;
int num2=4;
int V;
int fee1=1;
int fee2=2;
V=num2>num1?fee1:fee2;//因为4<5,逻辑是假,所以取值fee2,故V的值为2
instanceof 运算符:这个运算符是java语言定义的关键字,作用就是判断对象是否相等,譬如,
int i=5;
if(i instanceof Integer){
}
此处结果为真i的值所对应的对象类型确实是int类型的封装类,封装类就是8种基础数据类型都对应着一个java对象,这些封装类专门服务于基础数据类型系列装箱拆箱操作或者其它辅助打杂的东西,具体可以搜java封装类
方法定义
说明:java里的方法就是C语言里的函数,称谓不同,用法也跟C语言相似
语法固定格式:权限修饰符 + 返回值类型 + 方法名(n个入参)
public void computeFee(){
//这里叫方法体
computeFee2(100,5.8f);//这就是方法间的调用
}
public void computeFee2(int i,float n){
i=i+1;
n=n+2;
}
方法名后面用括号把入参括起来是固定写法,多个入参之间用英文逗号分割
循环语句
java得循环语句总共有三种while
、do-while
、for
,for-each
是for
的增强版不算单独种类,自己择机而用,按照实际使用频率排序为for>while>>do-while,do-while实战至今我就见过一两次。
while:
int i=0
while(i>0) {
//循环内容
i++;
}
do-while:
do{
//循环内容
}while(i>0);
while与do-while的区别是do-while功能=先走一遍循环内容+while的功能,会先走一遍循环的逻辑后再进行是否循环的逻辑判断,不符合就退出,所以出场率不高,while足矣。
for:
//写法1:
int fee;
for (int i = 0; i < 150; i++) {
//循环体
if (i > 100) {
break;
} else if (i > 80 && i < 100) {
continue;
}
if (fee > 10000) {
return;
}
fee = fee + 10;
}
//写法2为for的增强循环,基本是从数组或集合中取东西,此处略(集合java里是一种大小可变的特殊数组)
for
一般写法就是下标循环,也就是示例的写法足以覆盖绝大部分业务。
问:循环怎么跳出来呢?
答:关键字break
与return
进行跳出整个循环,若只是想中断某一次循环的话用关键字continue
,
这三者有啥区别?
break
与continue
的区别就是break
是跳出当前整个循环逻辑,continue
是跳出本次循环在continue
后面的代码本次执行不到了,下一个循环再见,return
是方法的返回值,方法一旦返回别说本次循环,是整个方法都跳出了,当方法返回值是void时写return;
有具体返回值类型返回对应的类型值
int fee;
public int myFee() {
for (int i = 0; i < 150; i++) {
//循环体
if (i > 100) {
break;
} else if (i > 80 && i < 100) {
continue;
}
if (fee > 10000) {
return fee;
}
fee = fee + 10;
}
return 0;
}
数组
数组在运行时是对象,写法上跟普通对象有些不一样,数组在内存中是一段连续的内存区域,所以在使用前需要定义好大小让系统去开辟内存,数组写的时候跟变量意义先声明再赋值也可以连写,在实际运行后就变成内存里的实体,大小不可更改,万物皆可数组,数组下标(index)从0开始,so数组中第1个元素的index=0,第2个元素index=1。数组可以理解为数据水桶,你要多少毫升的提前说好我铸造好了就没法改了。
几种写法格式,自己挑一种
//写法一:
float[] fee2 = new float[]{2.0f,3.4f,5.5f,3.2f};//表示声明一个float数组元素,
//此处没有声明容量,直接用元素填充了,元素具体值都有了,自然不用再赘述容量了
//写法二:
long[] fee3 ={3,5,29,67};//这是省略版写法,与fee2相同简化部分由编译器补全
//写法三:
AnObject[] obj = new AnObject[15];//一个类名叫AnObject的对象数组,容量为15
int[] fee1 = new int[10]//表示声明一个名为fee1的整型数组,元素储量为10,里面元素待添加,
//实战意义较大,因为实战中只需要声明水桶不需要数据,数据后续逻辑执行会添加
//赋值写法
fee1[0]=20;//表示在数组下标0这个地方赋值,值为20,
//取值写法
int myFee = fee1[0]//这个myFee值就是20.
下图是java语句,循环用的增强for循环即foreach
,做数组练习足以,解出手机号为18013820100
上图代码等于
int[] arr = new int[]{8,2,1,0,3};
int[] index = new int[]{2,0,3,2,4,0,1,3,2,3,3};
String tel="";
for (int i = 0; i < index.length; i++) {
tel=tel+arr[i];
}
System.out.println("联系方式为:"+tel);
-
Number与Math类
image.png
上面说过基础数据类型都对应着一个辅助的封装类干各种杂事,基础数据类型的封装类除了char与boolean其余都继承自Number,学完面向对象后理解更深,此处需强行记忆。
此处略,需要写程序做习题运行才能理解,属于理论必知,看详情https://www.runoob.com/java/java-number.html
练习题:
习题1:已知一个圆的半径r=15,求圆的面积,结果用整数表示,π按3.14算。(整数保留使用强制类型转换)
习题2:将习题1的整型结果乘以1.0,1).求出平方根,2).对比平方根与习题1实际结果两个数值的大小(使用Math类)3).对习题1结果四舍五入转为整型。
习题的结果将会把浮点型转为整型,这种转换就是由封装类的拆箱封箱操作的,属于理论必知。
double k=1000.234;
int price = (int)k;//这就是强制类型转换的写法,四舍五入属于Math类的特殊算法需要使用Math类的方法
关于文字的封装类
Character是char的封装类,为char类型处理各种杂事,字符用单引号括起来书写为`F`
,每个字符对应着Ascii编码.
练习题:对比字符串“a1sdcd3r%”相邻两个非数字字符的大小,并打印出对应的数字,提示->需要用到知识涉及:数组,for循环,字符串转字符数组,Character类(自己查询可用类里哪些方法)
String
String比较特殊,它是字符串不是基本数据类型是引用数据类型,它超高频很重要,典型的问法就是
String hai = new String("hellow!");产生了几个对象。
java中+号就可以实现类型转换和字符拼接。
int fee=500;
String priceList = fee+"";
String preffix = "价格清单:"+priceList ;
+""
是拼接一个空字符串的意思,我们在书写中经常在数字类型后面写这个以让结果转换为字符串,通常在for循环中字符串拼接。
StringBuffer (一般)线程安全的,可多线程使用,速度略低于StringBuilder;
StringBuilder(高频)线程不安全,单线程使用,速度快,一般都是它,多用于循环语句中的字符串追加拼接。
两者差别可百度“StringBuffer与StringBuilder”的区别
面向对象
- 概念:软件设计一般都源于生活与哲学,面向对象的概念源自哲学理念“万物皆对象”这句话,其跟“Hello World!”是每一个学java的人都知道的名言,就像《权游》粉都知道的“Winter is coming”、“凡人皆有一死”。面向对象理念认为所有的东西都可以看作一个研究对象,这个对象可以是猫、狗这种具体的,也可以是职业、死亡这种抽象的,所以面向的其实是一个个研究对象。
- 问:一个研究对象里有什么呢?
1.属性:譬如研究房地产,它有自然属性与经济属性,这两个大的属性还可以继续拆分。譬如物理研究物体,质量就是每个物体最重要的一个属性。研究人,胳膊、腿、发量都是人自有的,可以看作人的属性,属性需要被挖掘被定义,是这个对象所携带的东西,你对这个研究对象自有的东西进行定义就是定义属性。
2.动作:无论具体的抽象的,活的死的一个研究对象总可以做点什么,这个做
在java中就是对象里的函数(java叫方法),我们用对象里的方法
去做一些事,譬如人这个对象可以吃,吃就是一个动作,走路,喝水都是动作,吃、走路、喝水就是人这个对象的方法。
总结下研究对象的属性、行为,对应着java里的属性、方法。 - 问:java类与对象是什么关系?
类很多人解释为图纸,对象解释为实体,我给来解释,假设你是一个工程师,类它就相当于你在纸上画画(类写在.java文件中,可以把.java文件看作纸张),你定义了它是什么,有哪些属性,可以做什么,程序运行时计算机会按照你定义的关系进行构造并存储在内存中,内存中的这个能实际起作用的东西就是我们心心念念叫的对象,对象它是一个实体,
举个例子:你写小作文
定义了老头乐
的属性与方法,厂家把老头乐造
出来,这个老头乐实体就叫对象,你的小作文就是类,厂家是计算机,造对象的这个行为我们叫做实例化
,所以对象是一个类的实例
,java里实例化的关键字是new,故没有对象new一个对象就行了,经常有人说你没有对象?new 一个就行了。实例可以理解为实体例子,“实例化”这个化跟“自动化”这个化意思差不多表示转变成某种性质或状态。
我在概念阶段把对象称为研究对象
,有了实体以后我才称为对象(Object)
,在图纸定义阶段称为类(Class)
,用三种称呼进行区分新手容易理解。
将类变成对象代码示例:
假使需要实例化的类名叫LiuYiFei
固定语法格式:
数据类型 接收对象的变量名 = new 类名();
//1个类也是一个数据类型,除了8种基础数据类型外,我们写的类也是数据类型
LiuYiFei liuSir = new LiuYiFei();
这句话的意思是实例化一个刘亦菲并赋值给变量liuSir,这种赋值跟int oneChui=80;是差不多的意思
- 问:liuSir与oneChui有和不同?
解释之前需要说个题外话,机器在运行程序时除了cpu运算还需要临时存储运算值,存储的地方就是运行内存(RAM),我们买电脑时说的内存多少 说的就是这个东西,但是程序运行时数据存的策略还需要人去定义,这个定义人就是管理Java虚拟机的大神,有一种工作叫JVM调优,绝大部分情况下我们用的是默认的java内存模型,可以百度了解下。
比较这两个有啥不同此处就得引入一个概念引用数据类型
,其实说的问题就是 基础数据类型 与 引用数据类型 有啥不同?比较这两个东西需要引入内存模型,栈与堆。
学过数据结构的知道栈这个东西就像一个量桶(注意量筒不是量杯,初中化学实验的量筒),它存储值就像把麻将一个一个丢进去,先进后出的特性注定了要找里面的东西只能一个个倒出来再塞回去,那么为了运算速率它就不能太大,太大不好查找遍历,它是系统自动分配的,而堆就是垃圾堆大的一批浩如烟海宛若星辰,可以理解为数据池塘,它是实例化对象的时候申请的空间,相当于每次人为向系统申请开辟,多了就成了垃圾堆。
基础数据类型(下面简称基类):int是java8种基类之一,oneChui就是麻将它存储在栈中,栈中直接存储得二进制值,所以“麻将”就是具体值。
引用数据类型:LiuYiFei已经new了,就是实例化了,是个内存中的实体对象,它的内存占用太大放在堆中,那么堆太大需要用到LiuYiFei时要查找整个池塘那太费劲了,怎么办,那就用量筒中的麻将记录他在池塘的具体位置,所以变量liuSir的值就是量筒中的麻将,注意,liuSir是你定义的变量名是名字,他在语法中叫引用变量(变量指向1个对象就叫引用变量),它的值存储在栈内存中,此处将其栈中的值举例为“麻将”,它跟基类的不一样,基类的麻将就是具体值,liuSir的值是一段堆内存的地址,即一个叫liuSir的引用变量的值是一段堆内存地址,那个堆地址上放着的值才是对象的实体,这就跟C语言的指针类似了,所以一般听到的描述是引用指向对象,这个引用就是麻将(liuSir的值),像个代理,通过它存的地址我们能直接访问对象里的方法属性等,譬如liuSir.eat("西瓜");
,梳理一下,引用数据类型的变量值与基类的变量值一样存储在栈中,但是值跟值不太一样,基类存的是具体的二进值,引用类型存的是一段堆内存地址,没有直接在栈中存储对象实体,它太大了,那个堆内存地址上的二进制值才是对象实体;我们开发时说引用访问对象,就是通过“麻将”访问了对象,像一个指针指向一个地址。量筒是栈,麻将是变量的值,池塘是堆,堆内存地址上的值是对象实体,通常开发时说某某类的引用其实就是说这个类对应的实体,譬如,变量liuSir持有了LiuYiFei的引用。
类:
java类有哪些概念
封装、继承、多态
划重点,这是面向对象的三大特性,是相对于面向过程的语言说的,这个很重要是java语言的立国之本,类在写的时候需要考虑这三大特性,故在此处才说。
-
继承: 就是两仪生四相,四相生八卦,有着父子关系,跟你熟知的遗产继承差不多,程序执行时先执行父类逻辑再执行子类,父类非private修饰的东西子类都可以继承,父子关系存在的意义就是为了扩展,譬如:十年前造了一辆五菱之光,五年前基于五菱之光造了五菱宏光,现在基于五菱宏光造了五菱神光,在之前的基础上再扩展可保持了原有逻辑的完整性,又有新逻辑可用,有人说我都有了五菱神光为啥还要保持五菱之光逻辑,假设五菱之光便宜但是丑,五菱神光颜值高但是贵,今天我要去送葬那么我肯定得用五菱之光,因为便宜,保持它得逻辑就是保留了使用得可能性,所以继承得核心是既保持原有逻辑不动,又有新东西可用,在书写上继承使用关键字
extends
,体现在代码上书写为:
分别建四个.java文件书写四个类,类名分别命名为CarWL、CarWLZG、CarWLHG 、CarWLSG ,.java的文件名须与类名一致
//CarWL.java文件 五菱
public abstract class CarWL{
public String name = "五菱系列";
}
//CarWLZG.java文件 五菱之光
public class CarWLZG extends CarWL{
public int windowCount = 4;
public int luntaiCount =3;
private int ugly=100;
public void drive(){
System.out.println("敞着开");
}
}
//CarWLHG .java文件 五菱宏光
public class CarWLHG extends CarWLZG{
private String color = "#ffffffff";
}
//CarWLSG.java文件 五菱神光
public class CarWLSG extends CarWLHG {
private int music = 5;
@Override
public void drive(){
System.out.println("优雅的开");
}
}
通过上面三个类可以发现,五菱宏光(CarWLHG)只定义了一个颜色,但实际上因为它继承自五菱之光(CarWLZG),所以它实际拥有了五菱宏光(CarWLHG)public修饰的部分,完整为windowCount 、luntaiCount 、color以及一个drive()方法 ,private修饰的东西无法被继承,所以丑就没被继承下来,有人问继承的东西能不能改动,当然可以,如上代码五菱神光(CarWLSG)这代就把开车方式给改了,以前都是敞着开到了神光这一代我就得优雅的开,这种改动涉及到一个java语法概念覆写
又叫覆盖
、重写
,在方法上方加一个@Override
关键字,表示对父类的方法进行方法体逻辑的重新定义。
总结:其实继承这个描述的本意我认为是将共性的东西向上抽取,动物->人->男人、女人,属于这种共性抽取的继承关系,越往下描述的越具体,源于生活却高于生活,这体现了一种由0到100的梯层设计,每一梯层都能满足一层的需求,这个需求其实就是做什么,定义对象的目的其实就是定义这个对象能做什么。
- 多态: 又叫变态,“冰水为之却寒于水”,这就是一种多态,三大特性就是哲学概念,一个事物不可能永远只能是一中形态,就譬如你的爷爷是你曾祖的儿子,是你爸爸的爸爸,有着多种存在形式,假设有这样一层继承关系Steam(水蒸气)➼ICE(冰)➼Water(水),水既是冰也是水蒸气,再举一个例子,狗既是狗也是动物,一个抽象物体会有多种表示形态,这就是多态的含义,它存在的意义就是两字“共性”与多样性,一个东西被多个实现,一气化三清,三清就是一气的多态,举个例子:我在一个类里定义一个变量为五菱的车,那么是不是用五菱系列的之光、宏光、神光都可以,它们都是五菱车,上代码
上述五菱的例子有这样一层继承关系
CarWLSG➼CarWLHG➼CarWLZG➼CarWL
//CarShow.java文件
public class CarShow{
public void show(CarWL carWl){
System.out.println("展示五菱的车"+carWl.toString);
}
}
//CarFactory.java
public class CarFactory{
public void doAnCarShow(){
//对象里方法的调用就是用 引用变量.方法
CarShow carShow = new CarShow(); //实例化一个车展的对象(车展对象专门负责展示车)
CarWL carWL = new CarWLSG(); //实例化一辆五菱神光,并用五菱车类型进行接收
carShow.show(carWL); //车展对象做展出,展出的东西为五菱神光
CarWL carWL = new CarWLZG();//实例化一辆五菱之光,并用五菱车类型进行接收
carShow.show(carWL); //车展对象做展出,展出的东西为五菱之光
}
}
1.向上转型: 上述代码描述的就是多态的典型在代码里的实际运用, 将子类对象赋值给父类类型的变量,这种技术称为“向上转型”;
使用场景:有时候我们只知道要展示某一类型的车但不知道具体展示什么,那么我们就可以用这一类车的公用父类定义参数类型,这种场景在封装功能时经常会用到,但是向上转型后具体类型的特有属性就无了,譬如展示的之光用五菱类型去接收,那么它只剩下了name这一属性,只能对name这属性进行操作,其它属性都丢失了,因为CarWl没有CarWLZG的属性与方法,这个类型的变量只有carWl.name
。
2.向下转型: 父类引用的对象转换为子类类型称为向下转型
//第一种:
CarWL carWL = new CarWLZG();//new1个五菱之光用五菱类接收
CarWLSG carWLSG = (CarWLSG)carWL;//强制转换为五菱神光
//第二种:
CarWL carWL = new CarWLSG();//new1个五菱神光用五菱类接收
CarWLSG carWLSG = (CarWLSG)carWL;//强制转换为五菱神光
上述两种都是向下转型,就是把父类对象强制类型转换为具体子类,譬如我定义一个五菱类型变量,由于五菱是五菱之光与五菱神光的父类,所以你传之光对象或者神光对象都行,我接收之后都转为神光,神光中有个music属性,我就用神光播放音乐,有人问这不是神经病么,不能直接传入神光么,因为我不知道后续会不会有类似神光这种五菱系列的车可以播放音乐,为了保持扩展性,在定义时我用共性的父类肯定没有问题,我的需求是播放音乐,如果车辆没有音乐功能,则它是一个缺省数据不影响我的功能,功能保持开放,选择归数据,这就是向下转型的作用,就是接收一个模糊的数据以备后用,这种也是封装功能的时候用的多。
总结:多态核心掌握就是向上转型,向下转型,有人问这种值不会丢失么,不管是向上转型还是向下转型都会丢失一些精度,这是正常的,那为什么还要这么用呢,因为数据操作本身都是目的性的,最差也有缺省值,所以实际使用中功能不会有啥影响,这一段到后期写一些泛型的封装自会理解。
- 封装: 这个东西比较好理解,就是模块化,把对象的设计细节给隐藏起来,外界想访问只能通过你提供的窗口,举例:
public class LanApple{
private int color;
private int wide;
private int high;
public void changeColor(int color){
System.out.println("颜色改为:"+color);
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getWide() {
return wide;
}
public void setWide(int wide) {
this.wide = wide;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
}
这种就是一种封装,隐藏自身信息或实现细节,外部只能通过你定义的窗口进行访问无法直接操作,有人问我直接看源码不就都知道了,还能隐藏啥,干嘛不能直接访问变量,假使第三方公司给你一个sdk(软件开发工具包,都是编译后的字节码)不给源码只有访问的API(开放接口)这时候你就只能调用别人开放的接口,因为别人隐藏变量了信息,你不知道有啥可以拿,上述例子我改一下,把getHight改为panChangJiang,这个时候别人不知道你获取的是什么东西,你只能去查他写的解释,他不解释你永远不知道这是身高,你还以为是最小高度值,有序的告知防止人人知晓,晓得越少越安全。
public int panChangJiang() {
return high;
}
再举个例子:
private BigFruitsBasket {
private LanApple apple;
private LanPear pear;
}
public class Gift {
private BigFruitsBasket fruits;
private DrinkBasket drink;
}
我定义好了一个送礼物的类,礼物有大水果篮子、饮料篮子,水果里有烂苹果跟烂梨子,我这时候想改一下礼物把烂梨子换成烂李子(plum),只需要改BigFruitsBasket ,Gift 就不用动,如果我不分类封装BigFruitsBasket这个类,把它这些水果写在Gift里面,礼物如果非常多,就会很容易改错而且不容易管理,我今天改水果,张三明天改饮料,每次修改礼物都要修改Gift,代码很容易改冲突,所以封装有句名言“高内聚,低耦合”这6个字就是封装的核心灵魂之一,在写的时候要想好一个功能可以拆分为几个对象,各个对象之间能做什么,怎么调用这种就是封装,模块化就是目的,模块与模块之前的关联越少越好就是低耦合,高内聚就是把功能越多越好的封装在自己内部。
1、封装有利于提高程序的安全性,保护数据
2、隐藏代码的实现细节,用户不可见
3、统一了接口
4、增加系统的可维护性
-
this与super
this代表当前对象的引用
super代表父类对象的引用 -
变量
-
方法
类里的三大特性说完了,再回头说说类里的方法,上面写了方法的定义,这里完善方法的知识
1.构造方法
语法格式:修饰符+类名+(若干参数);
构造方法又称构造器,是一种特殊的方法,方法名必须与类名相同,且没有返回值。对象的创建就是通过构造方法来完成。
有几个需要强记的知识:
a.每个类默认有一个无参构造方法,所以创建类后也可以不写
b.构造方法的参数可以用来做成员变量初始化,见下方源码
c.构造方法和普通方法一样也可以重载,想写几个写几个,但是写了有参构造方法,默认的无参构造方法就会被取消需要你自己去实现,譬如下面的LanApple我写了双参数的构造方法,又写了无参构造方法。
//People.java
public class LanApple{
public void buy(){
LanApple apple = new LanApple();
LanApple apple2 = new LanApple("原谅色",50);
}
}
//LanApple.java
public class LanApple{
private String mColor;
private int mWidth;
public LanApple(){
System.out.println("无参构造方法");
}
public LanApple(String color,int width){
this.mColor=color;
this.mWidth=width;
System.out.println("双参构造方法");
}
}
2.虚方法与非虚方法
静态方法、私有方法、final方法、构造方法、父类方法都是非虚方法,java中的普通方法都是虚方法可被子类覆写,在其它语言中譬如C#需要使用virtual关键字才有这个能力。
3.静态方法
在java中,静态方法指被static修饰的成员方法。静态方法不需要通过它所属的类的任何实例就可以被调用,因此在静态方法中不能使用this关键字,也不能直接访问所属类的实例变量和实例方法,但是可以直接访问所属类的静态变量和静态方法。
4.抽象方法
5.方法的重载
6.方法的覆盖
有几种方法不能被重写:
1)静态方法:static修饰的方法,父类的静态方法不可以被重写,可以继承;
2)final修饰的方法:父类中final修饰的方法不可以被重写,可以被继承;
3)构造方法:父类的构造方法不可以被重写,也不需要覆写父类构造方法;
4)private修饰的:因为父类中private修饰的方法子类不可见;
-
书写
几个注意点,java里类名用大驼峰 AnObject、BookManager,变量名用小驼峰anObject、bookManager,常量、静态变量、枚举用大写中间用下划线分割
public static int PEER_CONNECTION = 10;
public static int QINGDAO_BEER = 5;
类里面的内容怎么写
package com.book.testsourcecode;
public class AnJava {
//写代码的地方
}
网友评论