面向对象概念
面向过程
面向过程关注于一个功能实现的步骤,按步骤变成实现功能。面向过程是一种事件为中心的编程思想。就是分析出解决问题所需的步骤,然后用函数把这些步骤实现,并按顺序调用。
面向对象
面向对象是以对象为中心的编程思想。面向对象关注于对象本身,关注对象本身的状态,对象特性,对象能够提供的功能。对象本身就是一种封装。
面向环境
对象的基本特性
封装考虑内部实现,抽象考虑的是外部行为。封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块;他们都是为了解决代码重用。而多态是为了实现接口重用,为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确使用。
抽象
抽象就是抽出共同的部分,表示一类特征。Java中抽象的概念最直接的应用就是抽象类和接口,从复杂的业务逻辑中,提炼出它的本质。
封装
封装将数据以及加在这些数据上的操作组织在一起,提供给可信的其他类或对象操作。
继承
继承就是从一般到特殊的过程。通过继承可以拥有现有类的所有功能,并在无需重修编写原来类的情况下对这些功能进行扩展。
多态
多态性是指允许不同类的对象对同一消息作出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)。实现多态的两种方式:重写、重载。
抽象类和接口的区别
共同点
- 都是上层的抽象;
- 都不能被实例化;
- 都能包含抽象方法
不同点
在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,提高代码的复用性;接口中只能有抽象方法(JDK1.8新特性:默认方法(子类不一定要实现)、JDK1.9新特性:私有方法(增强默认方法));
一个类只能继承一个直接父类(普通类或抽象类),但是可以实现多个接口。
访问控制符
控制符 | 标识 |
---|---|
private | 同类可见 |
default | 同包可见 |
protected | 同包可见,子类可见 |
public | 全局可见 |
/**
* 默认 同包可见
*/
String test1;
/**
* 常用 同类可见(也叫私有化)
*/
private String test2;
/**
* 同包可见 常用于jar封装
*/
protected String test3;
/**
* 公开的 全局可见 可使用
*/
public String test4;
重载和重写
- 重载:重载是指一个类中允许存在多个同名函数(但是参数不同),调用时根据参数不同可以进行,调用不同的方法。
/**
- 方法重载演示
*/
private void hello()
private void hello(long id)
private void hello(String id)
- 重写:重写是指子类重新定义父类方法。
/**
- 方法重写演示
*/
class Animal {
public void run() {
System.out.println("动物每秒运动100M");
}
}
class Dog extends Animal {
/**
* 在这里重写了父类的 run 方法
*/
public void run() {
System.out.println("狗每秒运动1M");
}
}
构造器Constructor
- 构造器不允许被重写。
- 构造器不是方法,所有用于修饰方法特性的修饰符,都不能用来修饰构造器。
- 构造器是实例化对象过程中用来初始化这个对象用的。
1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名)
2.每个类可以有一个以上的构造器
3.构造器可以有0个、1个或1个以上的参数
4.构造器没有返回值
5.构造器总是伴随着new操作一起调用
6.不添加任何构造器会默认有空的构造器
/**
* 默认构造器,即使不写也会存在
* 但是如果写有其他的带参构造器,默认的无参构造器不写将会不存在
*/
public ConstructorDemo() {
System.out.printf("无参构造函数!");
}
/**
* 带参构造函数
* @param param
*/
public ConstructorDemo(String param) {
System.out.printf("带参构造函数!");
System.out.printf("参数:" + param);
}
public static void main(String[] args) {
/**
* 无参构造函数使用
*/
new ConstructorDemo();
/**
* 带参构造函数使用
*/
new ConstructorDemo("test");
}
继承与构造器
使用super调用父类构造器的语句必须是子类构造器的第一条语句
class Parent {
/**
* 父类构造函数
*/
public Parent() {
System.out.printf("父类构造函数!");
}
}
class child extends Parent {
/**
* 子类构造函数
*/
public child() {
/**
* 子类构造函数使用 super() 调用父类构造函数, super() 必须是子类构造函数的第一句
*/
super();
System.out.printf("子类构造函数!");
}
}
语言特性
自动装箱拆箱
/**
* 自动装箱操作(将int 类型自动包装为Integer)
*/
Integer a = 20;
Integer _a = Integer.valueOf(20); // jdk 自动编译为这种形式
/**
* 自动拆箱操作(将 Integer 类型自动拆箱为int)
*/
int b = a;
int _b = a.intValue(); // jdk 自动编译为这种形式
String、StringBuffer、StringBuilder的区别
/**
* 1.性能差别:StringBuilder > StringBuffer > String
* 2.String对字符串的操作(修改、拼接)其实是在创建新的对象,效率低下
* 3.StringBuffer线程安全、StringBuilder线程不安全
*/
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("start"); // StringBuilder 使用示例(线程不安全)
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("start"); // stringBuffer 使用示例(线程安全的)
/**
* String 使用详解
*/
String str = "";
String _str = new String(); // jdk 默认编译为这种
/**
* String 常用方法
*/
str.length(); // 获取字符串长度
str.substring(0, 1); // 字符串切割(从开始位置到指定位置,指定位置可选)
str.startsWith("prefix"); // 判断字符串是否以 prefix 开头
str.endsWith("suffix"); //判断字符串是否已 suffix 结尾
str.indexOf("test"); // 查找指定字符串在原字符串中第一次出现的位置,找不到返回-1
str.lastIndexOf("test"); // 查找指定字符串在原字符串中最后一次出现的位置,找不到返回-1
str.contains("test"); // 判断是否包含某个字符串,返回true或false 参数为 CharSequence
str.toCharArray(); // 将字符串转换为 字符数组 char[]
str.toLowerCase(); // 将字符串转换为小写字符串
str.toUpperCase(); // 将字符串转换为大写字符串
str.getBytes(); // 获取字符串数组的 byte 序列(使用平台的默认编码),返回一个byte[] 数组
str.equals("test"); // 字符串对比函数 对比字符串的值是否完全相等 , 新手容易使用 str1 == "test"
final boolean b = str == "test"; // 字符转 == 对比 ,因为字符串是引用类型,所有str本身存储的是内存地址(也可以理解为指针),这里的两个内存地址是不同的,所以不管如何都不会相等
str.equalsIgnoreCase("test"); // 字符串对比,不考虑大小写
str.trim(); // 去除字符串两端的空格,但是对于字符串中间的空格不进行处理 (注意:返回值去除,原字符串不变)
final String[] strs = str.split(","); // 根据指定字符串进行切割,返回切割后的字符串数组
/**
* String 池 (独立于栈和堆之外的存在,存储不可变量) JDK 11
* 每次创建 String 对象 (不创建String是不会去到常量池的) 将会去 String 池中寻找有没有相同对象,有的话直接返回引用,没有则创建并返回引用。
*/
String string = "1"; // 第一次将会去 String 池创建对象,返回对象引用,string变量存储引用
String string2 = "1"; // 给 string2 赋值的时候则直接 将 string2 的引用指向String 池中已经存在的 "1",不在重新创建对象
String string3 = "1" + "2"; //
String string4 = "12"; // 创建 的 12 和 string3 是同一个存储地址,只有保存 string3的时候才会去到常量池
String string5 = "1" + new String("3"); // 这个会在常量池中生成一个 3 的引用,在堆中生成一个 13 的引用,字符串对象的运算将会创建对象到堆中
String string6 = string5.intern(); // 调用intern()方法将string字符串13添加到String池中,并返回String池引用
hashCode和equals
- hashcode()方法是JDK根据对象的地址或者字符串的值计算出来的int类型的数值(哈希码值)。
- 同一对象多次调用hashcode()方法,必须返回相同的数值。
- 如果两个对象根据equals()方法比较是相等的,那么两个对象调用hashcode()方法返回的结果必须相等。
- 如果两个对象根据equals()方法比较是不相等的,那么两个对象调用hashcode()方法返回的结果不一定不相等。
/**
* hashCode 方法再源码中是看不到实现的
* @return
*/
public native int hashCode();
/**
* Object equals 方法
* 默认采用的是 == 进行判断
* @return
*/
public boolean equals(Object obj) {
return this == obj;
}
/**
* Object 默认的toString 方法
* 默认采用的是获取class名称 + @ + hash 结果转16进制
* Integer.toHexString() 将参数 转换为16进制
* @return
*/
public String toString() {
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
}