面向对象和面向过程
面向过程:把一个任务分成一个个的步骤,当要执行这个任务的时候,只需要依次调用就行了
面向对象:把构成任务的事件构成一个个的对象,分别设计这些对象(属性和方法)、然后把这些对象包装成有自己完整功能的系统。
举例:
面向对象的特征
面向对象的四大特征:继承、多态、封装、抽象;
封装:把每一个对象的信息都隐藏起来,只留出少量的接口(方法)给外界访问来获取和更改对象的信息,良好的封装可以有效的保证数据的合理性。
继承:从已有的类中派生出新的类(新的类继承旧的类,旧的类叫做新的类的父类),新的对象具有父类的属性和方法并可以具有自己独有的属性和方法,java中继承是单继承(每一个子类都只能有一个直接的父类)
多态:多态就是事物的多种形态,在不同的情况下所表现的不同的形式。
多态的存在条件:
- 继承或实现:在多态中必须存在有继承或实现关系的子类和父类
- 方法的重写:子类对父类中的某些方法进行重新定义
- 父类引用指向子类对象,父类类型:指子类对象继承的父类类型,或实现的父接口类型
形式:
父类类型 变量名 = new 子类类型
作用:
当使用变量名调用成员变量时调用的是父类的成员变量,调用方法时则是调用的子类重写的方法。无法调用子类独特的方法和成员变量,当子类和父类拥有相同的静态变量和方法时,调用的是父类的变量和方法。
向上转型:父类引用指向子类对象,多态的一种体现。(无需强制转型)
形式:父类类型 变量名 = new 子类类型
向下转型:子类引用指向父类对象,此时可以调用子类特有的方法(需要强制转型)
形式:子类类型 变量名 =(子类类型) new 父类类型
抽象:把具体的事物使用代码表示出来。
抽象方法:没有方法体的方法
抽象类:包含抽象方法的类
如果有类继承了抽象类,那么这个类要把所继承的抽象类的所有的抽象方法给实现出来,除非这个子类也是抽象类。
java基本类型:
int、long、short、float、double、char、boolean、byte。
在保存金额时不能使用浮点型进行储存,因为浮点型在储存十进制的小数时保存的是近似值所以并不准确,如要保存可以使用BigDecimal,BigDecimal通过使用BigInteger(用于表示整数部分)和scale(用于表示小数部分的位数)来表示高精度的十进制数值,从而可以准确地表示和计算大数。
java在传输参数的时候传输的是值的副本:
如果传输的不是对象,那么传输过去的是变量的值的副本,在方法中改变值不会改变原变量的值。
如果传输的是对象,那么传输的是对象引用的副本,在方法中改变对象的值,那么对象引用的值也会和方法中一样
举例:
public class Main {
public static void main(String[] args) {
int x=5;
chang(x);
System.out.println(x);
StringBuilder stringBuilder=new StringBuilder("123");
changClass(stringBuilder);
System.out.println(stringBuilder);
}
public static void chang(int x){
x=6;
}
public static void changClass(StringBuilder stringBuilder){
stringBuilder.append("123");
}
}
运行结果:
包装类:
java中很多地方需要使用对象而不是基本数据类型比如集合(集合中只能存放对象),那么这时就轮到包装类出场了。包装类相当于把基本数据类型进行包装后使其获得对象的性质、添加了属性和方法。
|---------|-----------|
| 基本数据类型 | 包装类 |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| byte | Byte |
| boolean | Boolean |
| short | Short |
自动装箱和拆箱
装箱:将基础类型转化为包装类型。
拆箱:将包装类型转化为基础类型。
当基础类型于包装类进行运算时会自动进行装箱和拆箱。
String类
String类是不可改变的,在保存字符串时使用的是byte数组来进行存储的,而这个数组是使用final进行修饰的,所以String类是不可以改变的,对String类进行+运算则是生成了一个新的变量。
String类中对byte数组的定义
为什么不用char数组呢?因为使用byte数组更节省空间
因为String类本身是不可改变的要通过新建才能达到修改的效果,所以如果要频繁的对字符串进行修改就会对内存进行比较大的消耗,那么有没有一种类可以直接修改呢?
Stringbuffer类和Stringbuilder类
Stringbuffer和Stringbuilder都是继承的抽象类AbstractStringBuilder,可以对字符串进行直接的修改不用新建。
AbstractStringBuilder中对byte数组的定义
Stringbuffer和Stringbuilder、String的区别
|---------------|--------|-------|
| | 是否线程安全 | 是否可改变 |
| String | 是 | 否 |
| Stringbuffer | 是 | 是 |
| Stringbuilder | 否 | 是 |
Stringbuffer是所有的方法都添加了synchronized关键字来确保数据的同步的而Stringbuilder却没有,所以Stringbuilder在单线程的情况下是要比Stringbuffer的效率要高的。
StringJoiner
StringJoiner是基于String来实现的?网上说是Stringbuilder但我自己看是基于String数组实现的。
StringJoiner可以在添加字符串的时候自动的去添加用户设置的前缀、后缀、和分隔符。
import java.util.StringJoiner;
public class Main {
public static void main(String[] args) {
StringJoiner stringJoiner=new StringJoiner(",");
stringJoiner.add("张三");
System.out.println(stringJoiner);
stringJoiner.add("李四");
System.out.println(stringJoiner);
stringJoiner.add("王五");
System.out.println(stringJoiner);
}
}
运行结果
注意:
new String("suibian"); 这一条语句运行完后建立了几个对象呢?
答案是1或2个。
1.当字符串常量池没有"suibian"是会建立一个字符串对象放到字符串常量池里去。
2.new一个字符串对象放到堆栈里去。
String类的大小
Java中的字符串长度是使用int类型来表示的所以String类字符串最大长度为2^31,字符串常量在常量池中的最大长度是65534
Object类常用的方法有那些?
Object类常用的方法有 toString、equals、hashCode、clone等。
toString:默认输出对象地址。
equals:默认比较两个引用变量是否指向同一个对象(内存地址)。
hashCode:将与对象相关的信息映射成一个哈希值,默认的实现hashCode值是根据内存地址换算出来。
clone:得到一个对象的副本。
浅拷贝和深拷贝
浅拷贝:拷贝对象和原始对象里的引用类型引用同一个对象。
在下面这个例子中person1和person2的引用对象引用的是同一个对象。
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("Alice", new Address("New York"));
Person person2 = person1.clone();
System.out.println(person1.getName());
System.out.println(person1.getAddress().getCity());
System.out.println(person2.getName());
System.out.println(person2.getAddress().getCity());
person2.getAddress().setCity("123");
System.out.println(person1.getName());
System.out.println(person1.getAddress().getCity());
System.out.println(person2.getName());
System.out.println(person2.getAddress().getCity());
}
}
class Person implements Cloneable{
private String name;
private Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public Person clone() throws CloneNotSupportedException {
Person clone = (Person) super.clone();
return clone;
}
}
class Address {
private String city;
public Address(String city) {
this.city = city;
}
public Address() {
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
运行结果:
可以看到原对象的值会受到拷贝对象的影响
深拷贝:拷贝对象和原始对象的引用类型指向不同的对象
对上面的程序进行更改:使Address也实现Cloneable接口,并且在Person的clone中调用Address中的clone方法。
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("Alice", new Address("New York"));
Person person2 = person1.clone();
System.out.println(person1.getName());
System.out.println(person1.getAddress().getCity());
System.out.println(person2.getName());
System.out.println(person2.getAddress().getCity());
person2.getAddress().setCity("123");
System.out.println(person1.getName());
System.out.println(person1.getAddress().getCity());
System.out.println(person2.getName());
System.out.println(person2.getAddress().getCity());
}
}
class Person implements Cloneable{
private String name;
private Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public Person clone() throws CloneNotSupportedException {
Person clone = (Person) super.clone();
clone.address=address.clone();
return clone;
}
}
class Address implements Cloneable{
private String city;
public Address(String city) {
this.city = city;
}
public Address() {
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public Address clone() throws CloneNotSupportedException {
Address clone = (Address) super.clone();
return clone;
}
}
运行结果:
可以看到原对象的值不会受到拷贝对象的影响。