匿名对象
创建一个对象,没有把它赋值给任何一个变量,只能使用一次。
static
作用:
如果在对象和方法前添加了static,那么它属于类而不属于对象。
特点:
- static修饰的内容,是随着类加载而加载的
- static修饰的内容,优先于对象存在
- static修饰的内容,被该类型的所有对象所共享
- static修饰的内容,可直接使用类名
类成员和实例成员的访问:
- 静态方法只能访问静态成员
- 非静态方法可以访问静态成员,也可以访问非静态成员
成员变量和局部变量
成员变量
直接在类中定义的变量,有默认初始值。
- 类成员变量:在成员变量前加static就是类成员变量
- 实例成员变量:不加static就是实例成员变量
注意:在方法中不能使用static变量
局部变量
定义在方法中的变量、参数或代码块中定义的变量,要手动赋初始值。
this
在一个方法中,要给变量赋值,它会先到方法当中去找有没有该变量,如果有,就给方法内部的变量赋值,就不会向上找了(调用完方法,成员变量中依然没有值);如果没有,再往它上一级找。
在方法当中变量前加上this,就代表直接给对象当中的字段赋值。
作用:
- 要区分成员变量和局部变量的二义性,必须使用this
- 在同一个类中,实例方法相互调用,可以省略this
- 可以把this作为参数传递
- 可以当作返回值返回
- static和this不能一起使用
- 构造方法的重载互调,this();此时this代表构造方法的名称,必须写在第一行
super
到父类中去调用指定的方法和属性
注意:
- super()构造方法必须要放在第一行
- 凡是子类的构造方法中,都会有super();,默认就有。
有关继承的方法调用
-
一个类在加载字节码时,先寻找父类,如果有父类,会先把父类加载成字节码放到内存当中,然后再把自己加载到内存当中。
-
当子类调用方法时,先在子类中找,没有再到父类中找。
当想输出对象所有属性时,覆盖toString()方法(有可以自动生成的办法)
多态
特点:
把子类对象赋值给父类对象,在运行时期会表现出具体的子类特征调用子类方法
基本实现:
Dog dog=new Dog();
Cat cat=new Cat();
Person per=new Person();
per.feedAnimal(dog);
per.feedAnimal(cat);
class Person{
void feedAnimal(Animal anim){
anim.eat();
}
}
作用:
当把不同的子类对象当作父类类型来看待,可以屏蔽不同子类对象之间的实现差异,从而写出通用代码达到通用编程,以适应需求的不断变化。
注意:
- 字段(我理解为属性)不存在多态,对象是什么类型就调用谁的。
- 子类对象赋值给父类对象是多态,此时当对象用到自己 特有的方法时需要强制转换成子类的类型再调用方法。
代码块
在类或方法中使用{}括起来的一段代码,称为一个代码块。代码块中定义的变量,称为局部变量。
- 局部代码块:直接定义在方法内部的代码块(很少使用)
- 初始化代码块:直接在类中定义的代码块,初始化代码块在运行时,还是会被放在构造方法中(很少使用)
- 静态代码块:在初始化代码块前加static,在加载字节码时就会自动调用,在主方法之前执行,只执行一次。
final
继承避免了代码重复,但破坏了封装。用final的目的是子类可以继承父类,但不能修改。
final可以修饰属性,方法和类。
修饰属性时子类不可更改父类属性;
修饰方法时子类不可覆盖该方法;
修饰类时该类不能被继承。
注意:
- final修饰属性时,属性是没有初始值的,必须手动设置初始值。
- final修饰变量时,就代表是一个常量,命名规则:所有字母都大写。
- 如果final修饰的是基本数据类型,代表值不能去修改了。
- 如果final修饰的是一个引用类型,地址不能再去修改。
设计模式(简)
1. 单例设计模式
一个类在内存当中只有一个对象。
饿汉模式(不能被继承,其他模式可以继承)
①必须要在该类中创建一个对象出来
②私有化自己的构造方法,防止外界通过构造方法创建新的对象
③给外界提供一个方法,能够获取已经创建好的对象(通过类名获取,设置成static)
public class ToolUtil {
private static ToolUtil instance = new ToolUtil();
private ToolUtil(){}
static public ToolUtil getInstance(){
return instance;
}
}
public class Main {
public static void main(String[] args) {
ToolUtil.getInstance();
}
}
工具类
把一些经常使用的功能,写在一个类中,称这个类为工具类。以后使用时直接调用。经常使用的包名有util/utils,tool/tools等。
设计方法:
- 工具类当中的方法一般设计成静态方法,直接使用类名来调用。
- 如果工具类中的方法没有使用static,一般把工具类设计为单例,通过单例获取对象调用工具方法。
- 如果工具类全部使用static修饰,说明工具方法只需要使用工具类名调用即可,此时必须把工具类构造方法私有化,防止对象调用静态方法。
包装类
把基本数据类型包装成一个对象,使功能更强大,以面向对象的思想使用这些类型。
byte-Byte short-Short int-Integer long-Long float-Float double-Double
char-Character boolean-Boolean
装箱操作
把基本数据类型包装成对象
public static void main(String[] args) {
int a=20;
Integer num = new Integer(a);
System.out.println(num);
System.out.println(num.MAX_VALUE);
System.out.println(num.MIN_VALUE);
System.out.println(num.TYPE);
}
也可以用valueOf()进行装箱操作
具体类和方法可以查文档 JDK API中文版(未下载)
拆箱操作
把包装类对象转换为对象的基本数据类型
int num1=num.intValue();
System.out.println(num1);
自动装箱和自动拆箱
Integer i=20;//自动装箱
int i1=i.intValue();//自动拆箱
字符串与其他类型的转换
//把字符串转成包装类型
Integer i=new Integer("12");
Double d=new Double("12.10");
//把包装类型转换成字符串
Integer i2 = Integer.valueOf(100);
String str = i2.toString();
//基本数据类型转字符串
int a = 10;
String str2 = a +"";
//字符串转基本数据类型
String str3 = "200";
int i3 = Integer.parseInt(str3);
//字符串转布尔类型(除了“true”以外,其他都输出false)
Boolean b = new Boolean("mama");
基本数据类型和包装类的区别
- 默认值不同,int-0 Integer-null
- 包装类当中提供了很多方法直接给我们使用,Integer.toBinaryString(s)
- 集合框架中不能存放基本数据类型,只能存对象
- 在类中,成员变量一般使用包装类型,方法中一般使用基本数据类型(方法中基本数据类型存储在栈中,包装类型存放在堆中)
包装类中的valueOf缓存设计
//两个地址不一样,每new一个创建一个新的地址
Integer i = new Integer(100);
Integer i2 = new Integer(100);
//包装类中的缓存设计,地址相同
Integer i3 = Integer.valueOf(123);
Integer i4 = Integer.valueOf(123);
//地址不同,缓存范围只有-128到127,超过这个范围就不会使用缓存,直接创建新地址
Integer i5 = Integer.valueOf(300);
Integer i6 = Integer.valueOf(300);
抽象类
多个类有相同的方法,可以抽出一个父类出来,把相同的方法放在父类当中。
但子类的方法体各不相同,所以父类不需要方法体。
抽象方法
在方法前面添加了一个关键字abstract
特点:
- 抽象方法没有方法体
- 抽象方法必须要定义在抽象类或接口当中
- 抽象方法不能是私有的,不能使用final,static修饰
- 子类必须要覆盖父类中的抽象方法
抽象类
必须有子类才有意义。
特点: - 抽象类是不能直接创建对象的
- 抽象类中可以有抽象方法,也可以有非抽象方法(普通方法:给子类调用的)
- 子类没有去覆盖抽象方法,可以把子类也定义成一个抽象类,但孙类要覆盖抽象方法
- 构造方法不能定义为私有的(抽象方法必须要子类继承,才能实现内部的方法体)
- 抽象类不能用final来修饰
命名:
通常在类名前加Abstract,例如AbstractSuperClass
接口
java接口表示一种规范,使用抽象方法去定义一组功能
接口是一个特殊的抽象类,方法前的abstract可以省略不写,在编译时会自动添加上
注意:
- 接口没有构造方法,不能创建对象
- 接口中定义变量,都是全局的静态常量
String name = "myxq";
public static final String name;
- 接口中定义的方法都是公共的抽象方法
void transData();
public abstract void transData();
- 接口是可以继承的,而且可以多继承,类是不能多继承的
接口继承一般不做方法覆盖
//爬行动物
interface Iwalkable{
void walk();
}
//水生动物
interface Iswimable{
void swim();
}
//两栖动物
interface Iamphibiousable extends Iwalkable,Iswimable{
}
子类中方法的权限要比父类权限大或一样大
接口的定义、实现及对象创建
interface Iwalkable{
String name = "myxq";
public abstract void walk();
}
interface Iswimable{
void swim();
}
class Cat implements Iwalkable{
public void walk(){
System.out.println("走猫步");
}
}
class Frog implements Iwalkable,Iswimable{
public void walk(){
System.out.println("跳着走");
}
public void swim(){
System.out.println("游啊游");
}
}
public class InterfaceClass {
public static void main(String[] args) {
//多态的写法
Iwalkable cat = new Cat();
cat.walk();
Frog f = new Frog();
f.walk();
f.swim();
}
}
抽象类与接口
相同点:
- 都被其他类实现或继承
- 都不能实例化
- 都可以定义抽象方法,定义的抽象方法子类都必须得要覆盖
不同点:
- 接口没有构造方法,抽象类中有构造方法
- 抽象类可以包含普通方法和抽象方法,接口中只能有抽象方法,不能有普通方法(带有方法体)
- 接口中的成员变量,public static final变量-静态常量;抽象类中成员变量为默认权限(包访问权限)
- 接口中默认方法 public abstract 方法名;抽象类中为默认权限(包访问权限)
面向接口编程
把实现类对象赋值给接口类型的变量
多态的好处:屏蔽了不同类之间 的实现差异,从而达到通用编程
interface IUSB{
public abstract void swapData();
}
class Mouse implements IUSB{
@Override
public void swapData() {
System.out.println("用鼠标");
}
}
class Keyboard implements IUSB{
@Override
public void swapData() {
System.out.println("敲键盘");
}
}
class MotherBoard{
void pluginIn(IUSB u){
u.swapData();
}
}
public class InterfaceClass {
public static void main(String[] args) {
IUSB m = new Mouse();
IUSB k = new Keyboard();
MotherBoard b =new MotherBoard();
b.pluginIn(m);
b.pluginIn(k);
}
}
内部类
定义在类中的一个类
使用内部类的原因:
- 增强封装,把内部类隐藏在外部类中,不允许其他类访问这个内部类
- 增加了代码的可维护性
- 内部类可以直接访问外部类中的成员
内部类可以分为四种:
- 实例内部类:直接定义在类当中的一个类,在类中没有任何一个修饰符
class Outter{
String name = "myxq";
class In{
void test(){
System.out.println(name);
}
}
}
public class InnerClass {
public static void main(String[] args) {
Outter out = new Outter();
System.out.println(out.name);
//创建实例内部类
//创建内部类对象当中,会有一个外部类的引用
Outter.In in = out.new In();
}
}
- 静态内部类:在内部类前面加一个static
- 局部内部类:定义在方法的内部类
- 匿名内部类:属于局部内部类的一种特殊情况
(具体内容之后再补)
枚举
java枚举:是一个特殊的类,多个常量对象的集合
不使用枚举的例子:
//定义一个星期几的常量类
class WeekDay{
public static final WeekDay MONDAY = new WeekDay();
public static final WeekDay TUESDAY = new WeekDay();
public static final WeekDay WENDESDAY = new WeekDay();
public static final WeekDay THURSDAY = new WeekDay();
public static final WeekDay FRIDAY = new WeekDay();
public static final WeekDay SATURDAY = new WeekDay();
public static final WeekDay SUNDAY = new WeekDay();
}
class Student{
private WeekDay restDay;
public WeekDay getRestDay() {
return restDay;
}
public void setRestDay(WeekDay restDay) {
this.restDay = restDay;
}
}
public class Test {
public static void main(String[] args) {
Student stu = new Student();
stu.setRestDay(WeekDay.TUESDAY);
}
}
好处:
- 安全,不会输入枚举值之外的值
- 业务逻辑合理
使用枚举:
enum Weekday{
MONDAY,TUESDAY,WENDESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
}
Main方法
当点击运行时,JVM自动调用main方法
public static void main(String[] args) {
}
public:被JVM调用的方法,它的权限要足够大
static:被JVM调用的方法,不需要创建对象,直接使用类名调用
void:被JVM调用的方法,不需要有任何返回值
main:方法的名称,只能这样写,不然JVM识别不了
String[] args:以前是指键盘录入
数组拷贝
int[] src = {1,2,3,4,5,6};
int[] dest = new int[10];
System.arraycopy(src,2,dest,2,4);
System.out.println(Arrays.toString(src));
System.out.println(Arrays.toString(dest));
src-源数组,2-源数组中的起始位置,dest-目标数组,2-目标数组起始位置,4-要复制的数组元素数量
输出:
[1, 2, 3, 4, 5, 6]
[0, 0, 3, 4, 5, 6, 0, 0, 0, 0]
gc方法与对象销毁(还需要仔细学习)
//终止正在运行的Java虚拟机,执行到这里下面就不执行了
System.exit(0);
//运行垃圾回收器,立即运行垃圾回收器,一个对象并不是立马被回收
System.gc();//一般不会主动调用该方法
随机数和UUID
//生成随机数
Random r = new Random();
int res = r.nextInt();
System.out.println(res);
System.out.println(r.nextBoolean());
System.out.println(r.nextDouble());
//相同种子生成的随机数是一样的
Random r2 = new Random(110);
System.out.println(r2.nextInt());
//生成34-229之间的随机数
//34+[0 195)
new Random().nextInt(195);
//UUID:通用唯一识别符
//在一台机器上生成的数字
//当前的时间,跟电脑网卡生成一段字符
String uuid = UUID.randomUUID().toString();
System.out.println(uuid);
日期
获取当前日期
Date date = new Date();
System.out.println(date);//英文日期
//把一个毫秒值转化为日期类型
//获取当前时间的毫秒
long curTime = System.currentTimeMillis();
//把一个毫秒值转成日期类型
Date date2 = new Date(curTime);
System.out.println(date2);
//中国人喜欢的风格
String str = date2.toLocaleString();
System.out.println(str);
生成验证码
//生成验证码
//5位的随机数 UUID生成的是16进制
String res = UUID.randomUUID().toString();
System.out.println(res);
//截取前5位
res = res.substring(0,5);
System.out.println(res);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
str = str + str.toLowerCase();
str = str + "0123456789";
System.out.println(str);
//从所有字符中随机生成5个出来
//角标要随机的值 (0,62)
//随机取5个出来
StringBuilder sb = new StringBuilder();
for(int i=0;i < 5;i++){
int index = new Random().nextInt(str.length());
char ch = str.charAt(index);
sb.append(ch);
}
System.out.println(sb);
日期格式化
//日期格式化
Date date = new Date();
System.out.println(date);
DateFormat df = DateFormat.getInstance();
//对指定日期进行格式化,具体查api文档
String time = df.format(date);
System.out.println(time);
//长日期:LONG
//短日期:SHORT
DateFormat df2 = DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT);
String time2 = df2.format(date);
System.out.println(time2);
DateFormat df3 = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String time3 = df3.format(date);
System.out.println(time3);
//获取时间
DateFormat df4 = DateFormat.getTimeInstance();
String time4 = df4.format(date);
System.out.println(time4);
//自定义日期模式
Date date = new Date();
SimpleDateFormat sd = new SimpleDateFormat();
//定义自己想要什么格式的日期
String pattern = "yyyy-MM-dd HH:mm:ss";
sd.applyPattern(pattern);
//以指定的模式格式化哪个日期
String res = sd.format(date);
System.out.println(res);