title: Java学习之路2019.07.28-《周记》
一、整体知识点
1.static关键字、继承
-
static关键字的使用:
- 可以修饰属性、方法以及引导静态代码块
- 类成员和实例成员的区别:
- 类成员:static修饰的实例成员叫做类成员
- 实例成员:普通属性和方法
- 类成员为所有对象共享
- 实例成员为每个对象私有
- 实例成员必须通过【对象.】的形式访问
- 类成员可以直接使用【类名.】的形式访问
- 类方法不能直接使用实例成员,可以直接使用类成员。
- 实例方法可以直接访问实例成员和类成员
- 在static修饰的方法和代码块中,不能使用this关键字
- 可以定义多个静态代码块,按照在源码中的先后顺序完成加载
-
继承:
-
一个类继承另外一个类,被继承的类叫做父类(超类、基类),当前类叫做子类
-
子类继承父类,可以得到父类非私有的属性和方法。 + 不能继承构造方法
-
子类的构造方法会默认调用父类的无参构造方法
-
子类继承了父类的方法,发现父类方法不能满足子类需求,那么子类可以对该方法进行重写
-
重写的要求:
1、发生在继承关系中
2、方法结构(返回值类型、方法名、参数列表)必须和继承的方法完全一致
3、使用的访问修饰符不能严于父类
public < protected <缺省<private -
继承的特点:
1.传递性
2.单根性 -
java中所有的类,都间接或者直接继承自Object类。
-
继承的语法
[修饰符] class 子类名 extends 父类名{ }
-
继承的作用:
- 提高代码的重用性
- 提高代码的安全性
-
-
super的使用:
- super:在子类中表示父类的一个实例
- 在子类中使用super.属性名的形式访问父类被隐藏的属性
- 在子类中使用super.方法名的形式访问父类被隐藏的方法
- 在子类构造方法中使用
super([参数列表])
的形式来调用父类的构造方法
2.封装以及抽象类
-
封装:
-
把客观事务描述为类的过程就是封装
一般指的是把类的属性或者方法私有化 -
属性私有化之后,需要给私有化的属性提供公开的get和set方法
-
-
final关键字的使用:
- final:最终的,可以修饰类和方法、属性
- 用在属性上,这个属性只能被使用,不能被修改,变为常量。
- 使用final修饰的变量必须初始化赋值。
- 用在方法上,这个方法不能被重写,变为终极方法
- 用在类上,这个类不能被继承,变为终极类
-
抽象类:
- 定义:当我们在定义类的时候,发现了类中方法不能确定具体实现,那么我们可以把这个方法定义成抽象方法,这个类称为抽象类。
- 语法格式:
[修饰符] abstract 返回值类型 方法名([参数列表]);
- 抽象方法没有方法体({}都没有)。
类中定义了抽象方法,那么这个类必须声明为抽象类。 - 子类继承了抽象类,必须对抽象方法进行实现。
- 抽象方法起到约定的作用。
- 抽象类不能直接实例化对象,但是可以声明类型。要想实例化对象找对应的子类。
- 抽象类中可以定义普通方法和属性。
- 抽象类中不一定有抽象方法,声明了抽象方法的类一定是抽象类。
- 向上转型:
子类对象引用赋值给父类的变量。安全。但是会丢失子类特有的属性和行为。格式:父类类型 父类引用; 父类引用=new 子类类型();
- 向下转型:
父类对象引用赋值给子类的变量。不安全。格式:子类类型 子类引用; 子类引用=(子类类型)父类引用;
- 一定是有关联的对象才能向下转型。多使用instanceof。语法 :对象 instanceof 类类型;
- 如果没有继承关系的向上或者向下转型,一定是不安全的。
-
接口
-
比抽象类还抽象的存在
-
在接口中只能定义常量和抽象方法
-
接口的作用:
1、解决java中类之间单继承的问题 2、达到约定的目的(降低耦合) -
接口:interface 接口之间的继承是多继承
语法格式:
[修饰符] class 类名 implements接口1名,接口2名.....{ 类体; }
- 类实现接口,实现接口中的抽象方法。实现是特殊的继承。
- 接口不能直接实例化对象,可以定义类型。要想实例化对象找实现类。
-
-
接口和抽象类的区别:
- 接口和抽象类之间的相同点和不同点:
- 1、不能直接实例化对象
- 2、一个是interface,一个是class
- 3、接口中只能定义常量,抽象类中既可以定义常量,也可以定义变量
- 4、抽象类的继承关系是单继承,接口之间是多继承,类对接口可以多实现
- 接口和抽象类之间的相同点和不同点:
-
多态
- 一个事物的多种形态
- 继承
- 重写
- 父类引用指向子类对象
-
接口的功能:
多个产品都存在一个相同的功能;这个功能可以被定为一个接口。
这个接口为这些商产品定义一个统一的规范约束起来。
此时所有产品实现这个接口。
然后用一个类进行对接口的具体实现,称为实现类;
将其属性定义为
接口类型 接口名
然后进行方法的具体实现
接口名.接口中方法()
最后在测试类中直接调用类中的具体实现方法。
多态的实现:
一个事物的两种状态;
一个事物拥有多种状态时,将多种状态定义为多个接口,
然后声明这个事物的类,该类同时属于多个接口的实现。重写多个接口中的抽象方法。
最后在测试时,实例化该类一个对象,并声明多个接口;
利用 接口名=对象名
向上转型实现对同一对象的不同抽象方法调用。
3.内部类(了解)
-
内部类:
- 定义:当我们定义一个类A的时候,发现类中包含另一个事物B,那么我们可以把事物B定义为内部类。
类A可以叫做外部类,类B叫做内部类
1、成员内部类,内部类的位置和外部类的实例成员同一级别
内部类可以直接访问外部类的属性和方法
外部类不能直接访问内部类的属性和方法,要想访问可以实例化内部类对象
在其他类中访问语法:内部类类型 对象名 = new 外部类类型().new 内部类类型();
2、方法内部类,定义在方法中
只能在定义了这个内部类的方法中使用
方法内部类不能使用访问修饰符,测试类直接调用方法3、静态嵌套类,使用static修饰的成员内部类
内部类可以直接访问外部类的类成员,不能直接实例成员,要想访问实例成员,必须实例外部类的对象
在其他类中访问语法:内部类类型 对象名 = new 外部类类型.内部类类型();
4、匿名内部类
继承式
接口式
参数式 - 定义:当我们定义一个类A的时候,发现类中包含另一个事物B,那么我们可以把事物B定义为内部类。
-
常用类库
- java的版本:
javaSE(标准版)、javaEE(企业版)、javaME(移动版开发) - 在当前类中使用其他包下的类,这时我们需要把其他包下的类导入到当前类中
- 在包名之下,类名之上,使用import关键字
- 语法: import 包名.类名;或者 import 包名.*;
- java.lang包,java提供的lang包是比较常用的类,使用lang包下的类,不需要导入
- java的版本:
4.常用类库
-
字符串:String类,不可变字符串,字符串常量
- 构造方法
- 常用方法
-
StringBuffer\StringBuilder,可变字符串
StringBuffer线程安全,常用于全局变量
StringBuilder线程不安全,用于局部变量,速度比StringBuffer快 -
Math类:数学类
-
八种基本数据类型对应的包装类
-
基本数据类型 — 包装类 — 字符串
-
jdk1.5之后基本数据类型和包装类对象可以自动拆封箱
-
拆箱:对象—基本数据类型
-
封箱:基本数据类型–对象
-
byte—Byte
short–Short
int-----Integer
long—Long
float—Float
double-Double
char—Character
boolean-Boolean
-
-
java.util包
Date 日期类
Calendar 日历类
Scanner 扫描器
Random 随机数类
Arrays 数组工具类 -
java.text包
DateFormat SimpleDateFormat
NumberFormat DecimalFormat
5.常用类库(Date Calender SimpleDateFormat)
- Date
Date date=new Date(); System.out.println(date.after(date2));//判断date是不是再date2之后 System.out.println(date.before(date2));//判断date是不是再date2之前 System.out.println(date.equals(date3));//当getTime得到的毫秒数相同时,结果为true
- Calender
Calendar now = Calendar.getInstance(); System.out.println(now); //获取年份 System.out.println(now.get(Calendar.YEAR)); //获取小时 System.out.println(now.get(Calendar.HOUR));//12小时制 System.out.println(now.get(Calendar.HOUR_OF_DAY));//24小时制 now.add(Calendar.YEAR, -5);//给指定的字段增减值 now.set(Calendar.YEAR, 5);
- SimpleDateFormat
SimpleDateFormat sdf=new SimpleDateFormat(); //定义一个格式 String pattern="yyyy年MM月dd日 HH:mm:ss"; //把模式设置给工具 sdf.applyPattern(pattern); //实例化一个当前的日期对象 Date date=new Date(); //把日期对象格式化成日期字符串 String str_date=sdf.format(date); System.out.println(str_date); /* * 日起到字符串:格式化 * 字符串到日期:解析 */ String sdate="2019.2.3 12:12:12"; //字符串日期 //在指定模式的时候,必须定义的模式和字符串日期一致 SimpleDateFormat sdf2=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); //解析日期字符串 Date date2=sdf2.parse(sdate); System.out.println(sdf2.format(date2));
6.集合框架
-
集合(很重要)
- 用来存储批量数据的集合
- 集合框架包含了集合接口以及对应的实现类
1.collection,集合框架的跟接口,定义了集合中的通用方法
- List接口
1、有序
2、允许null值
3、允许重复- 实现类ArrayList,线程不安全,基于动态数组实现。查询速速快,删除/新增速度慢
- 实现类LinkedList,链表实现,线程不安全。删除/新增效率高,查询效率低
- Vector,线程安全的,效率低
- Set接口
1、不允许重复
2、允许一个null值- 实现类HashSet,无序,基于哈希表实现。线程不安全
- 实现类TreeSet,有序,红黑树实现,线程不安全
2.Map接口
-
以键值对的方式来存储,键不允许重复,值允许重复
- HashMap实现类,基于哈希表,允许null键和null值,线程不安全
- hashTable实现类,基于哈希表,不允许null键和null值,线程安全
- Treemap实现类,基于红黑树,允许使用null值,不允许null键,不安全
在选择集合的时候,如果不是同步的,可以使用Collections工具类中的同步方法完成外部同步。
格式:Collections.synchronized集合(集合); -
思维导图:
Collection
Map
二、经典代码
1.类的继承
定义一个类员工类Employee,包含属性薪资和生日月份,以及获取薪资的方法,如果当月员工过生日,会有100元的生日奖励。
1-1、定义一个销售员工类,是员工类的子类,包含属性销售金额以及提成率。
1-2、定义一个销售经理类,是销售员工类的子类,包含属性基本薪资
1-3、定义一个固定薪资的员工类,是员工类的子类,包含属性固定薪资
1-4、定义一个小时工类,是员工类的子类,包含属性时薪和工作的小时数。超过160个小时的部分按照1.5倍薪资计算。
定义所有类,使用构造方法完成对象的创建。
Employee 类:
code
1-3 Fixation 类:
package com.zhiyou.day01work;
public class Fixation extends Employee{
//父类有:属性:salary birthday_month
// 方法:getSalary (int month)
int salary;
public Fixation(){//空构造函数
}
//需要获取的值包括 :birthday_month、salary;两者均可以从父类中找到
public Fixation( int birthday_month, int salary) {
super(birthday_month,salary);
}
//获取工资方法与父类方法相同
}
1-4 HourEmployee 类:
package com.zhiyou.day01work;
public class HourEmployee extends Employee {
//父类有:属性:salary birthday_month
// 方法:getSalary (int month)
double hourSalary; //时薪
int hour; //工作时间
public HourEmployee() {
}
//还需获取的有:birthday_month、hourSalary、hour ;其中需要新获得有hourSalary,hour
public HourEmployee(int birthday_month,double hourSalary, int hour) {
super(birthday_month); //父类获取生日月
this.hourSalary = hourSalary;
this.hour = hour;
}
@Override
double getSalary(int month) {
if(hour>160){
return 160*hourSalary+(hour-160)*hourSalary*1.5+super.getSalary(month);
}
return hour*hourSalary+super.getSalary(month);
}
}
1-1 SellEmployee 类:
package com.zhiyou.day01work;
public class SellEmployee extends Employee {
//父类有:属性:salary birthday_month
// 方法:getSalary (int month)
double salesAmount; //销售金额
double royaltyRate; //提成率
public SellEmployee() { //空构造方法
}
//需要获取的三个值:生日月;销售金额;提成率;其中需要新获得的为 salesAmount、royaltyRate
public SellEmployee(int birthday_month,double salesAmount, double royaltyRate) {
super(birthday_month); //生日月已定义,从父类获得
this.salesAmount = salesAmount;
this.royaltyRate = royaltyRate;
}
@Override //获取工资方法不同需要重写方法
double getSalary(int month) {
return super.getSalary(month)+salesAmount*royaltyRate;
}
}
1-2 SalesManager 类:
package com.zhiyou.day01work;
public class SalesManager extends SellEmployee{
//父类有:属性:salary、 birthday_month 、salesAmount、 royaltyRate
// 方法:getSalary (int month)
double salary; //基本工资
public SalesManager() {
}
//需要获取的有: salary、birthday_month 、salesAmount 、royaltyRate 其中 salary需要新获取
public SalesManager( int birthday_month,double salary,double salesAmount,double royaltyRate) {
super(birthday_month,salesAmount,royaltyRate);
this.salary = salary;
}
double getSalary(int month){
return salary+super.getSalary(month);
}
}
测试类:
package com.zhiyou.day01work;
public class Test {
public static void main(String[] args) {
//销售员工对象创建
SellEmployee sellEmployee =new SellEmployee(4,100000,0.2);
System.out.println(sellEmployee.getSalary(5));
//固定工资员工对象创建
Fixation fixation=new Fixation(5,4000);
System.out.println(fixation.getSalary(5));
//小时工对象创建
HourEmployee hourEmployee=new HourEmployee(8,180,15);
System.out.println(hourEmployee.getSalary(8));
//销售经理对象创建
SalesManager salesManager=new SalesManager(10,8000,10000,0.3);
System.out.println(salesManager.getSalary(10));
}
}
2.抽象类的使用:
编写一个台灯测试;有台灯和灯泡,灯泡多个,台灯一个,台灯打开后点亮相应灯泡。
分析,用抽象类规定统一标准来规范红绿灯灯泡类
抽象父类灯泡 TableLamp 类:
package com.zhiyou.abstactwork;
/**
* 台灯类
* @author XiaoHui
* 包含属性为一个灯泡类
*/
public class TableLamp {
//创建一个Bulb类型的对象
private Bulb bulb;
//空构造函数
public TableLamp() {
}
//构造函数来获取用户想要使用的灯泡的父类Bulb,此时如果传入子类灯泡,直接向上转型
public TableLamp(Bulb bulb) {
super();
this.bulb = bulb; //令传入bulb赋值给本类创建的bulb
}
public void on(){
System.out.println("台灯打开......");
bulb.shine(); //调用bulb的发光方法
}
}
子类 GreenBulb 类:
package com.zhiyou.abstactwork;
public class GreenBulb extends Bulb {
//重写父类发光方法
@Override
public void shine() {
System.out.println("绿灯泡发绿光....");
}
}
子类 RedBulb 类:
package com.zhiyou.abstactwork;
public class RedBulb extends Bulb {
//重写父类发光方法
@Override
public void shine() {
System.out.println("红灯泡发红光.....");
}
}
台灯类 TableLamp 类:
package com.zhiyou.abstactwork;
/**
* 台灯类
* @author XiaoHui
* 包含属性为一个灯泡类
*/
public class TableLamp {
//创建一个Bulb类型的对象
private Bulb bulb;
//空构造函数
public TableLamp() {
}
//构造函数来获取用户想要使用的灯泡的父类Bulb,此时如果传入子类灯泡,直接向上转型
public TableLamp(Bulb bulb) {
super();
this.bulb = bulb; //令传入bulb赋值给本类创建的bulb
}
public void on(){
System.out.println("台灯打开......");
bulb.shine(); //调用bulb的发光方法
}
}
测试类:TableLampTest 类:
package com.zhiyou.abstactwork;
public class TableLampTest {
public static void main(String[] args) {
//此时实例化一个红灯泡对象属于灯泡的子类;
RedBulb redBulb=new RedBulb();
//本来TableLamp()括号内传值为父类(Bulb),此处直接利用子类RedBulb
//子类对象向父类转型是向上转型,可以直接转型
TableLamp tableLamp=new TableLamp(redBulb);
tableLamp.on();
}
}
3. 自写工具类:Date <-> String Number <-> String
-
日期工具类
/** * 日期工具类,实现日期与字符串互转 * @author XiaoHui * dateToString(Date date,String Pattern) * stringToDate(String toDate ,String Pattern) */ package com.zhiyou.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateTool { private static SimpleDateFormat sdf=new SimpleDateFormat(); public static String dateToString(Date date,String Pattern){ sdf.applyPattern(Pattern); return sdf.format(date); } public static Date stringToDate(String toDate ,String Pattern) throws ParseException{ sdf.applyPattern(Pattern); return sdf.parse(toDate); } }
-
数字工具类
package com.zhiyou.util; /** * 数字工具类 * @author XiaoHui * numToString(Number num,String Pattern) * stringToNum(String toNum,String Pattern) */ import java.text.DecimalFormat; import java.text.ParseException; public class NumberTool { private static DecimalFormat df=new DecimalFormat(); public static String numToString(Number num,String Pattern){ df.applyPattern(Pattern); return df.format(num); } public static Number stringToNum(String toNum,String Pattern) throws ParseException{ df.applyPattern(Pattern); return df.parse(toNum); } }