一、Java基础
1、什么是面向对象?面向对象和面向过程的区别?
面向过程:注重事情的每一个步骤及顺序
面向对象:注重事情有哪些参与者(对象),及各自需要做什么
比如洗衣机:
面向过程是将任务拆解为一系列的步骤:1、打开洗衣机 2、放衣服 3、放洗衣粉 4、清洗 5、烘干 6、晾晒
面向对象是拆分出人和洗衣机两个对象
对于人:打开洗衣机 放衣服 放洗衣粉 晾晒
对于洗衣机:清洗 烘干
从上面的例子看出,面向过程比较直接高效,面向对象易于复用、扩展和维护从上面的例子看出,面向过程比较直接高效,面向对象易于复用、扩展和维护。
2、java的特性
(1)封装,在于明确标识出允许外部使用的所有成员函数和数据项。内部细节对外调用透明,外部调用无需修改或者关系内部实现。封装代码如下所示。
如:javabean属性私有,提供get set方法对外访问,因为属性的赋值或者获取逻辑只能有javabean本身决定,不允许外部乱改。
如:orm框架,操作书库是,不需要关系连接如何简历、sql如何执行,只需要引入mybatis调用方法即可。
点击查看代码
public class Encapsulation {
private String name;
private int no;
private int age;
/**
* 有参构造方法
* @param name
* @param no
* @param age
*/
public Encapsulation(String name, int no, int age) {
this.name = name;
this.no = no;
this.age = age;
}
public Encapsulation() {
}
/**
* 重写equals方法
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Encapsulation that = (Encapsulation) o;
return no == that.no && age == that.age && Objects.equals(name, that.name);
}
/**
* 重写toString方法
* @return
*/
@Override
public String toString() {
return "Encapsulation信息为:{" +
"name='" + name + '\'' +
", no=" + no +
", age=" + age +
'}';
}
@Override
public int hashCode() {
return Objects.hash(name, no, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Encapsulation en=new Encapsulation();//调用无参构造方法
System.out.println(en.getName());//null
Encapsulation en1 =new Encapsulation("huihui",32442,23);
System.out.println("姓名是:"+en1.getName()+",年龄是:"+en1.getAge()+",身份证号是:"+en1.getNo());//姓名是:huihui,年龄是:23,身份证号是:32442
System.out.println(en1.toString());//Encapsulation信息为:{name='huihui', no=32442, age=23} 此处toString()方法对外隐藏了细节,内部修改了具体实现,外部不会知晓
}
}
优点:良好的封装能够减少耦合,类内部的结构可以自由修改,可以对成员变量进行更精准的控制,隐藏信息实现细节。
(2)继承
类之间是is a的关系,子类继承父类的方法,做出自己的改变和扩展。子类共性的方法或者属性直接使用父类的,不需要自己定义,只需要扩展自己的。
点击查看代码
# 父类:
public class Person {
private String name;
private boolean gender;
private int age;
public String say(){
return "说话";
}
public void move(){
System.out.println("行动");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isGender() {
return gender;
}
public void setGender(boolean gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Student extends Person{
private double score;
public void study(){
System.out.println("正在学习");
}
}
public class Teacher extends Person{
public void teaching(){
System.out.println("在上课");
}
}
public class TestPerson {
public static void main(String[] args) {
Student st=new Student();
st.study();
System.out.println("学生在"+st.say());
Teacher te=new Teacher();
te.teaching();
System.out.println("老师在"+te.say());
}
}
输出是:
正在学习
学生在说话
在上课
老师在说话
2、抽取父类,定义名字,将子类中的属性和成员变量删除
(3)多态
多态存在的三个必要条件
继承
重写
父类引用指向子类对象:Parent p = new Child();
点击查看代码
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
多态的实现方式
方式一:重写:
这个内容已经在上一章节详细讲过,就不再阐述,详细可访问:Java 重写(Override)与重载(Overload)。
方式二:接口
-
生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
-
java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。具体可以看 java接口 这一章节的内容。
方式三:抽象类和抽象方法
点击查看代码
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
b.bark();
}
}
该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。
3、JDK JRE JVM三者的关系
JDK:Java Development kit Java开发工具包
JRE:Java Runtime Environment Java运行时环境
JVM:Java Virtual Machine Java虚拟机
如下图所示,通过图片可以看出,java是一次编译 处处运行,具有可移植性的特点。
4、==和equals的比较
对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址
equals:object 类的 "" 和 equals 没有区别,指的都是:A和B是同一个东西时返回true。
很多类继承了object类之后,都会重写object类的 equals() 和 toString()方法。
String 类重写了equals方法,如下所示。
点击查看代码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
5、hashCode和equals区别
hashCode作用就是获取哈希码,也称为散列码,实际上返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()定义在jdk的object.java中,java中的任何类型都包含有hashCode()函数。
例如:hashSet类的hashCode方法,hashSet会先计算对象的hashCode值来判断对象加入的位置,看该位置是否有值,如果没有会假设对象没有重复出现。但是如果发现有值,会调用equals检查两个对象是否真的相同。如果2者相同,hashSet不会让其插入操作撑过。如果不同的话,就会重新散列到其他位置。这样减少了equals的次数,相应大大提高了执行速度。
点击查看HashSet代码
HashSet<String> hs =new HashSet<>();
hs.add("feifei");
System.out.println(hs.hashCode());
System.out.println(hs);
hs.add("feifei");
System.out.println(hs.hashCode());
System.out.println(hs);//[feifei] 没有插入成功,只有一次feifei
hs.add("haha");
System.out.println(hs.hashCode());
System.out.println(hs);
点击查看hashCode代码
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
下面是string类的hashCode方法,只判断值是不是相同
点击查看代码
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
如果2个对象相等,那么hashCode一定相等;
2个对象相等,对2个对象调用equals都返回true;
2个对象有相同的hashcode值,他们不一定是相等的;
因此,equals方法被覆盖过,则hashcode方法也必须被覆盖;
hashCode()方法的默认行为是对堆上的对象产生独特值,如果没有重写hashCode(),则该class的2个对象无论如何都不会相等(即使这2个对象指向相同的数据)
6、final关键字
修饰类:表示该类不能被继承
修饰方法:表示方法不能被子类覆盖,可以重载
修饰变量:表示不可修改
7、String StringBuffer StringBuilder区别
string是final修饰的,所以 String 不是 Java 的基本数据类型。
字符串在 Java 中是不可变的,因此适合在多线程环境下使用。每次操作都会产生新的String对象。
当我们使用双引号创建一个字符串时,如下,JVM 首先在字符串池中寻找具有相同值的字符串。
String 是不可变的,而 StringBuffer 和 StringBuilder 是可变类。
StringBuffer 是线程安全和同步的,而 StringBuilder 不是。这就是 StringBuilder 比 StringBuffer 快的原因。
字符串连接运算符 (+) 在内部使用 StringBuilder 类。
对于非多线程环境中的字符串操作,我们应该使用 StringBuilder 否则使用 StringBuffer 类。
8、重载和重写的区别
重写(Override)是父类与子类之间多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Override)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。
重载:
重载(Overload)是一个类中多态性的一种表现。如果在一个类中定义了多个同名的方法,它们参数列表不同,则称为方法的重载(Overload)
区别:重载实现于一个类中;重写实现于子类中。
重载(Overload):是一个类中多态性的一种表现,指同一个类中不同的函数使用相同的函数名,但是函数的参数个数或类型不同。可以有不同的返回类型;可以有不同的访问修饰符;可以抛出不同的异常。调用的时候根据函数的参数来区别不同的函数。
点击查看代码
public class Goods { //创建一个商品类
private String ID;
private int price;
private String name;
private String manufactureDate;
//实现构造函数的重载 参数个数或类型不同
public Goods() {
super();
// TODO Auto-generated constructor stub
}
public Goods(String iD) {
super();
ID = iD;
}
public Goods(String iD, int price) {
super();
ID = iD;
this.price = price;
}
public Goods(String iD, int price, String name) {
super();
ID = iD;
this.price = price;
this.name = name;
}
public Goods(String iD, int price, String name, String manufactureDate) {
super();
ID = iD;
this.price = price;
this.name = name;
this.manufactureDate = manufactureDate;
}
}
重写(Override): 是父类与子类之间的多态性,是子类对父类函数的重新实现。函数名和参数与父类一样,子类与父类函数体内容不一样。子类返回的类型必须与父类保持一致;子类方法访问修饰符的限制一定要大于父类方法的访问修饰(public>protected>default>private);子类重写方法一定不能抛出新的检查异常或者比被父类方法申明更加宽泛的检查型异常。
点击查看代码
public class Person { //创建一个父类Person
private String name;
private int age;
//父类中写一个eat()方法
public void eat() {
System.out.println("人都要吃饭");
}
}
---------------------------------------------
package com.etime09;
public class Student extends Person { //Student子类继承Person父类
@Override
//重写eat()方法 方法名,参数,返回类型相同;方法体内容不同
public void eat() {
System.out.println("学生喜欢吃肉");
}
}
本文来自博客园,作者:Yi个人,转载请注明原文链接:https://www.cnblogs.com/feifei-cyj/p/15369179.html