文章目录
文章 | 链接 |
---|---|
Java语法 | https://blog.csdn.net/weixin_45606067/article/details/107049186 |
一维数组与二维数组、内存解析 | https://blog.csdn.net/weixin_45606067/article/details/107049178 |
面向对象(1/3)类和对象 | https://blog.csdn.net/weixin_45606067/article/details/108234276 |
面向对象(2/3)封装性、继承性、多态性 | https://blog.csdn.net/weixin_45606067/article/details/108234328 |
面向对象(3/3)抽象类、接口、内部类、代码块 | https://blog.csdn.net/weixin_45606067/article/details/108258152 |
异常处理 | 待更新 |
多线程(1/2) | https://blog.csdn.net/weixin_45606067/article/details/107067785 |
多线程(2/2) | https://blog.csdn.net/weixin_45606067/article/details/107067857 |
常用类 | https://blog.csdn.net/weixin_45606067/article/details/108283203 |
枚举与注解 | 待更新 |
集合(1/5)Collection、Iterator、增强for | https://blog.csdn.net/weixin_45606067/article/details/107046876 |
集合(2/5)List、ArrayList、LinkedList、Vector的底层源码 | https://blog.csdn.net/weixin_45606067/article/details/107069742 |
集合(3/5)set、HashSet、LinkedHashSet、TreeSet的底层源码 | |
集合(4/5)Map、HashMap底层原理分析 | https://blog.csdn.net/weixin_45606067/article/details/107042949 |
集合(5/5)LinkHashMap、TreeMap、Properties、Collections工具类 | https://blog.csdn.net/weixin_45606067/article/details/107069691 |
泛型与File | https://blog.csdn.net/weixin_45606067/article/details/107124099 |
IO流与网络编程 | https://blog.csdn.net/weixin_45606067/article/details/107143670 |
反射机制 | 待更新 |
Java8新特性 | https://blog.csdn.net/weixin_45606067/article/details/107280823 |
Java9/10/11新特性 | 待更新 |
1、java.lang.Object
1.Object类是所有 java 类的根父类
2.如果在类的声明中未使用 extends 关键字指明其父类,默认类的父类为 java.lang.Object 类。
3.Object类中的功能(属性,方法)具有通用性。
- 属性:无。
- 方法:equals() / toString() / getClass()获取当前对象的所属类 / hashCode()/ clone()克隆 / finalize()垃圾回收 / wait() / notify() / notifyAll()
4.Object类只声明了一个空参构造器
面试题:
final、finally、finalize的区别?
1. ==和equals()的使用
==:运算符
1.==可以使用在基本数据类型和引用数据类型变量中
2.如果比较的是基本数据类型变量,比较两个变量保存的数据是否相等(不一定类型要相同)。
如果比较的是引用数据类型变量,比较两个变量的地址值是否相等。即两个引用是否指向同一个对象实体。
equals()方法的使用:
1.equals()是一个方法,不是运算符。
2.只能适用引用数据类型。
3.Object类中equals的定义:
public boolean equals(Object obj) {
return (this == obj);
}
说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
4.像String、Date、File、包装类等都重写了Object类中的equals()方法。
重写以后,比较的不是两个引用地址是否相同,而是比较两个对象的"实体内容"是否相同。
练习:
Customer cust1 = new customer("tom",21);
Customer cust2 = new customer("tom",21);
System.out.println(cust1 == cust2);//false
String str1 = new String("atguigu");
String str2 = new String("atguigu");
System.out.println(str1 == str2);//false
System.obj.println(cust1.equals(cust2));//false
System.obj.println(str1.equals(str2));//true
2. equals()方法的重写
通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。
那么我们就需要对Object类中的equals()进行重写。
重写的规则:比较两个对象的实体内容是否相同。
//手动实现
public boolean equals(Object obj) {
if (this == obj){
return true;
}
if(obj instanceof Customer){
Customer cust = (Customer)obj;
//比较两个对象的每个属性是否相同
// if(this.age == cust.age && this.name.equals(cust.name)){
// return true;
// }else{
// return false;
// }
//或
return this.age == cust.age && this.name.equals(cust.name);
}else{
return false;
}
}
//自动生成的
右键生成
3. toString()的使用
1.当我们输出一个对象的引用,实际上就是调用当前对象的toString()
2.Object类中对toString()的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
3.向String,Date,File。包装类等都重写了Object的toString方法。
使得在调用对象的toString方法时,返回实体对象信息。
4.自定义类重写toString方法
2、JUnit单元测试的使用
步骤:
1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 -下一步
2.创建java类,进行单元测试
此时的java类要求:①此类是public的 ②此类提供公共的无参的构造器
3.此类中声明的单元测试方法。
测试的单元测试方法:方法的权限是public ,没有返回值类型,没有形参
4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入import org.junit.Test;
5.声明好单元测试方法以后就可以在方法体内测试相关代码。
6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
说明:
1.如果执行没有任何异常:绿条
2.如果执行结果出现异常:红条
3、包装类
包装类的使用:
1.java提供了中基本数据类型对应的包装类,使得基本数据类型的变量都具有类的特征。
2.掌握的:基本数据类型、包装类、String三者之间的相互转化
public static void main(String[] args) {
//基本数据类型 ---> 包装类 :调用包装类的构造器
Integer int1 = new Integer("123");
System.out.println(int1.toString());
Float f1= new Float(12.3);
Float f2= new Float("12.3");
System.out.println(f1+","+f2);
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("true123");
System.out.println(b1+","+b2);
//包装类 ---> 基本数据类型 :调用包装类的xxxValue()
Integer int1 = new Integer(12);
int i1 = int1.intValue();
System.out.println(i1 + 1);
/*
* JDK 5.0新特性:自动装箱与自动拆箱
* 自动装箱:基本数据类型 ---> 包装类
* 自动拆箱:包装类 ---> 基本数据类型
*/
int num1=10;
Integer num2=num1;//自动装箱
Integer a=10;
int b=a;//自动拆箱
//基本数据类型和包装类 ---> String的转换
int num=10;
//方式一:连接运算
String s1=num + "";//int->String
//方式二:调用String的valueOf(Xxx xxx)
String s2=String.valueOf(num);//int->String
//String的转换 ---> 基本数据类型和包装类
String str1 = "123";
//调用包装类的parsetXxx(String s);
int num3=Integer.parseInt(str1);//String->int
注意:转化时,可能会报NumberFormatException异常
}
面试题
//三目运算符后面两个条件语句对应的类型会在比较前进行统一
//1.
Object o1=true?new Integer(1):new Double(2.0);
System.out.println(o1);//1.0
//2.
Object o2;
if(true){
o2 =new Integer(1);
}else{
o2 =new Double(2.0);
}
System.out.println(o2);//1
//3.
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false
//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
//保存了从-128到+127范围的整数。如果我们使用自动装箱的方式,
//给Integer赋值的范围在-128到+127范围内时,可以直接使用数组中元素,不用再去new了。
Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true
Integer x = 128;
Integer y = 128;
System.out.println(x == y);//false
4、static关键字的使用
1.static:静态的
2.static可以用来修饰属性、方法、代码块、内部类
3.使用static修饰属性:静态变量(类变量)
3.1 属性:按是否使用static修饰,又分为:静态属性(静态变量) VS 非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都的拥有一套类中的非静态属性。当修改其中一个对象的
非静态属性时,不会到时其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享用一个静态变量。当通过某一个对象修改静态变量时,
会导致其他对象调用此静态变量时,是修改过的。
3.2 static修饰属性的其他说明:
①静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用。
②静态变量的加载早于对象的创建。
③由于类只会加载一次,则静态变量在内存中也只存在一份,存在方法区的静态域中。
④ 类变量 实例变量
类 yes no
对象 yes yes
3.3 静态属性举例:System.out;Math.PI;
4.使用static修饰方法:静态方法
① 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用。
② 静态方法 非静态方法
类 yes no
对象 yes yes
③ 静态方法中,只能调用静态的方法或属性
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性。
5.static注意点:
①在静态的方法内,不能使用this关键字、super关键字
②关于静态属性和静态方法的使用,都从生命周期的角度去解决。
6.开发中如何确定一个属性要声明为static?
> 属性被多个对象所共享的,不会随着对象的不同而不同的。
> 类中的常量也常常声明static
开发中如何确定一个方法要声明为static?
> 操作静态属性的方法,通常设置为static的
> 工具类中的方法,习惯上声明为static的
5、设计模式
1.1理解
设计模式是在大量的实践中总结和理论化之后优的代码结构、编程风格、以及解决问题的思考方式。
1.2常用设计模式--- 23种经典的设计模式
创建型模式,共5种, 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共种:适配器模式、装饰器横式、代理模式、外观模式、桥接模式、组合横式、享元横式。
行为型模式,共11种: 策略模式、模板方法模式、观察者横式、迭代器模式、责任链模式、命令模式、备忘录模式、状态横式、访问者模式、中介者模式、解释器模式。
单例设计模式
1.所谓类的单利设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例。
2.如何实现?
饿汉式 VS 懒汉式
3.饿汉式和懒汉式的区别
饿汉式:坏处,对象加载时间过长。
好处,线程安全的。
懒汉式:好处,延迟对象的创建。
坏处,线程不安全的。
4.应用场景:
网站计数器,应用程序的日志应用,数据库连接池,Application。
代码:
public class SingletonTest{
public static void main(String[] args){
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);//true
}
}
//饿汉式
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.内部创建类的对象
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance;
}
}
//懒汉式
class Bank{
//1.私有化类的构造器
private Bank(){
}
//2.声明当前类的对象,没有初始化
private static Bank instance = null;
//3.声明public static的返回当前类对象的方法
public static Bank getInstance(){
if(instance == null){
instance=new Bank();
}
return instance;
}
}
main()方法的使用说明:
1.main()方法作为程序的入口
2.main()也是一个普通的静态方法
3.main()方法可以作为我们与控制台交互的方式(之前:使用Scanner)
模板方法的设计模式
1.解决的问题
在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。
但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。
2.举例
abstract class Template{
//计算某段代码执行所需要花费的时间
public void spendTime(){
long start = System. currentTimeMillis();
this.code();//不确定的部分、易变的部分
1ong end = System. currentTimeMillis();
System.out.println("花费的时间为:”+ (end - start));
}
public abstract void code();
}
class SubTemplate extends Template{
@Override
public void code() {
for(int i = 2;i <= 1000;1++){
boolean isFlag = true;
for(int j = 2;j <= Math.sqrt(i);j++){
if(i%j==0){
isFlag = false;
break;
}
}
if(isFlag){
System.out.println(i);
}
}
}
}
3.应用场景
模板方法设计模式是编程中经常用得到的模式。各个框架、类库中都有他的影子,比如常见的有:
数据库访问的封装
Junit单元测试
JavaWeb的Servlet中关于doGet/doPost方法调用
Hibernate中模板程序
Spring中JDBCTemlate、HibernateTemplate等
6、类的成员之四:代码块
1.代码块(初始化块)作用:用来初始化类、对象。
2.代码块如果有修饰的话,只能使用static。
3.分类:静态代码块 VS 非静态代码块
非静态能调用静态的属性方法,静态的不能掉用非静态的属性方法。
4.静态代码块
- 内部可以有输出语句
- 随着类的加载而执行,只执行一次
- 作用:初始化类的信息
- 如果一个类中定义了多个静态代码块,则按声明的先后顺序执行
- 静态代码块的执行要优先于非静态代码块的执行
- 静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构
5.非静态代码块
- 内部可以有输出语句
- 随着对象的创建而执行
- 每创建一个对象,就会执行一次非静态代码块。
- 作用:可以在创建对象时,对对象的属性等进行初始化
- 如果一个类中定义了多个非静态代码块,则按声明的先后顺序执行
- 非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
对属性可以赋值的位置
对属性可以赋值的位置:
1)默认初始化
2)显示初始化
3)构造器初始化
4)有了对象以后,可以通过"对象.属性"或"对象.方法"的方式进行赋值
5)在代码块中赋值
执行的先后顺序:1 - 2 - 5 - 3 - 4
总结:由父及子,静态先走
7、final关键字的使用
final:最终的
1.final可以用来修饰的结构:类、方法、变量
2.final用来修饰一个类:此类不能被其他类所继承。
比如:String类,System类,StringBuffer类
3.final用来修饰方法:表明此方法不能被重写。
比如:Object类中的getClass();
4.final用来修饰变量
此时的变量就称为常量。
4.1 final修饰属性:
可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化。
4.2 修饰局部变量
尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
static final:用来修饰属性:全局常量
8、抽象类与抽象方法
abstract关键字的使用
1.abstract抽象的
2.abstract可以用来修饰的结构:类、方法
3.abstract修饰类:抽象类
> 此类不能实例化
> 抽象类中一定有构造器,便于子类实例化时调用。
> 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作。
4.abstract修饰方法:抽象方法
public abstract void test();
> 抽象方法只有方法的声明,没有方法体。
> 包含抽象方法的类一定是抽象类;反之,抽象类中可以没有抽象方法的。
> 若子类重写了父类类中的所有的抽象方法后,此子类方可实例化。
若子类没有重写了父类类中的所有的抽象方法,则子类也是一个抽象类,需要使用abstract修饰。
5.注意
1)abstract不能用来修饰:属性,构造器等结构。
2)abstract不能用来修饰私有方法、静态方法、final方法、final的类。
创建匿名子类的匿名对象
method1(new Person(){
@Override
public void eat(){
System.out.println("吃好吃的")
}
@Override
public void breath(){
System.out.println("好好呼吸空气")
}
});
9、接口(interface)
1.接口的使用interface来定义
2.Java中,接口和类是并列的两个结构。
3.如何定义接口,定义接口的成员
3.1 jdk7以前:只能定义全局常量和抽象方法
> 全局常量:public static final的。但是书写时,可以省略不写
> 抽象方法:public abstract的。但是书写时,可以省略不写
3.2 jdk8:除了定义全局常量和抽象方法外,还可以定义静态方法、默认方法。
4.接口中不能定义构造器,意味着接口不能实例化。
5.Java中,接口通过让类去实现(implements)的方式来使用。
如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
6.Java类中可以实现多个接口。
格式:class AA extends BB implements CC,DD{}
7.接口与接口之间可以继承,也可以多继承
8.接口的具体使用,体现多态性。
9.接口实际上可以看做是一种规范。
10.开发中体现了面向接口的编程。
Java8中关于接口的新规范
//知识点1:接口中定义的静态方法,只能通过接口来调用。
//知识点2:通过实现类的对象,可以调用接口中的默认方法。
//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没重
写此方法的情况下,默认调用的是父类中的同名同参数的方法。-->类优先原则
//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
//那么在实现类没重写此方法的情况下,报错。-->接 口冲突。
//这就需要我们必须在实现类中重写此方法
//知识点5:如何在子类(或实现类)的方法中调用父类、 接口中被重写的方法
public void myMethod(){
method3();//调用自己定义的重写的方法
super.method3();//调用的是父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
面试题:抽象类与接口的异同
相同点:
不能实例化;都可以包含抽象方法的。
不同点:
抽象类:通过extends来继承,只能继承一个抽象类(单继承),
抽象类中一定有构造方法,创建子类对象时被调用。
抽象类中不光有抽象方法,还可以有其他方法。
接口:接口通过implements来实现,允许实现多个接口(多继承),
接口中不存在构造方法,
jdk7及以前接口中只能声明全局常量和抽象方法,
jdk8以后还可以定义静态方法和默认方法,
jdk9以后还可以定义私有方法。
接口的应用:代理模式
1.解决的问题:
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个对象的访问。
2.应用场景:
安全代理、远程代理、延迟加载
分类:
静态代理、动态代理
3.代码:
/**
* 代理模式:将两者都要实现的行为封装在接口中,被代理对象和代理对象都继承该接口
* 代理对象中声明被代理对象属性,并创建拥该属性的构造器,通过创建代理对象完成
* 被代理对象的方法。
*/
class NetWorkTest{
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
interface NetWork {
public void browse();
}
//被代理类
public class Server implements NetWork {
@Override
public void browse(){
System.out.println("真实的服务器访问网络");
}
}
//代理类
public class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work){
this.work = work;
}
public void check(){
System.out.println("网络之前的检查工作");
}
@Override
public void browse(){
check();
work.browse();
}
}
10、类的成员之五:内部类
1.Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类。
2.内部类的分类:成员内部类(静态,非静态)VS 局部内部类(方法内,代码块内,构造器内)
3.成员内部类:
一方面,作为外部类的成员:
> 调用外部类的结构
> 可以被static修饰
> 可以被4种不同的权限修饰
另外一方面,作为一个类:
> 类内可以定义属性、方法、构造器等
> 可以被final修饰,表示此类不能被继承。言外之意,不适用final,可以被继承。
> 可以被abstract修饰
4.关注如下的3个问题
4.1 如何实例化成员内部类的对象
4.2 如何在成员内部类中区分调用外部类的结构
4.3 开发中局部内部类的使用
public class TnnerClassTest{
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类)
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
System.out.println();
bird.display("黄鹂");
System.out.println();
}
}
class Person{
String name = "小明";
int age;
public void eat(){
System.out.println("人吃饭");
}
//静态成员内部类
static class Dog{
String name = "鸟";
int age;
public void show(){
System.out.println("卡拉是条狗");
// eat();
}
}
//非静态成员内部类
final class Bird{
String name = "杜鹃";
public Bird{
}
public void sing(){
System.out.println("我是一只小鸟");
Person.this.eat();//调用外部的非静态属性
//eat();
}
public void display(String name){
System.out.println(name);//方法的形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
}
}
public void method(){
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方式一:
class MyComparable implements Comparable{
@Override
public int compareTo(Object o){
return 0;
}
}
return new myComparable();
//方式二:
return new Comparable(){
@Override
public int compareTo(Object o){
return 0;
}
};
}
}
注意点:
在局部内部类的方法中(比如: show)如果调用局部内部类所声明的方法(比如: method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
jdk 7及之前版本:要求此局部变量显式的声明为final的
jdk 8及以后的版本:可以省略final的声明
5.总结:
成员内部类和局部内部类,在编译以后,都会生成字节码文件
格式:成员内部类:外部类$内部类名.class
局部内部类:外部类$数字 内部类.class
面试题:创建静态内部类对象和非静态内部类对象:
//静态内部类对象
Person.Dog dog=new Person.Dog();
//非静态内部类对象
Person p=new Person();
Person.Bird bird=new p.bird();
如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客