构造方法
什么是构造方法
1)方法名和类名一致
2)没有具体返回类型
3)连void都没有
构造方法是支持方法重载的(方法名相同,参数列表不同,与返回值无关)
使用构造方法的注意事项:
1)一个类中如果没有提供任何构造方法,系统会默认提供一个无参构造方法
2)如果一个类中提供了有参构造方法,系统不会再提供无参构造方法,如果还要无参构造方法来创建对象,会报错
给成员变量赋值就两中方式
1)setXXX()赋值
2)有参构造方法赋值
类
一个类中的成员
一个标准类:
成员变量:属性私有化
成员方法:setXXX()/getXXX()
构造方法:无参构造方法永远给出来的!
有参构造方法(视情况而定)
带参的有返回值类型
带参的没有具体返回值类型 void代替
空参的有返回值类型的
空参的没有具体返回值类型 void代替
常用类
java.lang.Object--->所有的类父类(jdk提供的类/我们自定义的类)
equals():建议所有子类必须重写---->不重写,引用类型比较就是地址值是否相等
底层原码用的就是 ==
toString():建议所有的子类必须重写这个方法
getClass():---获取一个类的字节码文件对象 ---- >Class(jdk提供的:class对象:字节码文件对象)
clone():克隆
和线程(锁)相关的功能:
wait():线程等待
notify():线程唤醒
java.util.Scanner:键盘录入--->提供一些判断功能 hasNextXXX()
如果录入的是int--->但是接收的String line = 键盘录入对象.nextLine();
java.lang.String(开发中经常用到的)
需求:将一个数组---遍历----转换成String (必须使用String 的拼接)
拼接:
String s = "" ;
转换功能
获取功能
拼接功能:concat(String str)
分割/拆分
截取
按照字典顺序比较
需求:
键录入一个字符串
输入"Helloworld"
输出 "hELLOWORLD"
输入 "mbabm"
输出 :判断这个字符串是否为对称字符串? true/false
java.lang.StringBuffer
Integer
Character
System
Arrays:数组工具类(方便使用)
内部类
内部类----实际开发中 应用层面居多
一个类A中,有一个类B,将类B就称为类A的内部类,类A是类B的外部类
内部类的两种格式
1)成员内部类---在一个外部类的成员位置(类中,方法外)定义的类
2)局部内部类---在外部类的局部位置(方法定义中)定义的类!
内部类里面的一些访问方式
成员内部类:
可以访问外部类的成员,包括私有相关的
直接访问方法:外部类.内部类名 对象名=new 外部类名().new内部类名();
成员内部类的修饰符
成员内部类可以有private修饰,目的是为了数据安全性
成员内部类还可以static修饰符
1)静态的成员内部类只能访问外部类的静态成员
2)静态的成员内部类中无论是静态方法还是非静态方法:访问外部类成员都只能是静态的
3)想直接通过外部类来访问静态成员内部类的成员信息,访问格式
外部类名.内部类名
局部内部类:
特点和成员内部类一样,局部内部类也可以直接访问外部类的包括私有
//特点和成员内部类一样,局部内部类也可以直接外部类的包括私有!
class Outer{
public void method(){
class Inner{
public void show(){
//局部变量
int num = 20 ;//jdk7(jdk7以前):此时num必须显示的加入final
//jdk8--final省略了,但是是存在!(必须为常量)
}
}
//创建Inner类对象,调用show()方法
Inner in = new Inner();
in.show() ;
}
}
//面试题:局部内部类访 访问它的成员方法里面的局部变量,局部变量有什么特点?
匿名内部类
匿名内部类(重点)
没有名字的类
应用范围:
在局部位置中(方法定义中或者声明上)
格式:
new抽象类名或者接口名(){
//重写抽象类或者接口方法(){
...完成逻辑
}
};
本质:就是继承了该(抽象)类或者是实现了该接口的子类对象!
成员变量(什么时候将变量定义为成员变量)
变量定义的时候,如果能够描述这个事物的属性---定义成员变量
成员变量和静态变量的区别?
1)存储位置不同:
成员变量 堆内存
静态变量 static静态区中
2)生命周期不同
成员变量:随着对象的创建而存在,随着对象的创建完毕而等待垃圾回收
静态变量:随着类的加载而存在,随着类的加载完毕而消失(非自定义变量)
3)初始化不同:
成员变量 它可以不初始化,存在默认初始化,通过set/get或者有参构造方法显示初始化
静态变量 也可以不初始化,或者直接初始化
4)访问方式不同
成员变量:创建对象 类名.对象名=new 类名() 对象.成员变量
静态变量:不推荐使用对象名来访问 类名.静态方法名()
static关键字(重点)
本身的含义“共享/共用”
被static修饰符的变量及方法
static的特点:
1)随着类的加载而加载,类在加载的时候,静态相关的成员(类成员:静态的变量或者静态的方法),随着类的加载而先进内存(静态区)
2)优先于对象存在,不能和this共存
3)static能体现“共享,公用”的意思
如果需求中有“共用含义”,这个变量直接使用static修饰
4)被static修饰的成员(变量/方法),推荐的访问方式是使用类名.静态变量
类名.静态方法名()
在使用静态相关变量/方法,他们的注意事项:
1)非静态的方法,既可以静态的,也可以访问非静态的(要么访问静态变量/静态方法)
2)静态只能访问静态
代码块–{}
/*(重点掌握:代码块的优先级,静态代码,构造代码,构造方法)
静态代码块:类就加载一次,所以static代码块只执行一次!
static{}(实际开发中,使用居多)
构造代码块{}(在类的成员位置):
作用:在执行构造方法之前,先行执行构造代码块,在执行构造方法
可以将构造方法中共性内容,放在构造代码块中!
局部代码块:在局部位置(方法定义中)定义的{}
作用:限定某个变量的生命周期*/
class Root {
static {
System.out.println("Root的静态初始化块");//1)
}
{
System.out.println("Root的普通初始化块"); //4)
}
public Root() {
System.out.println("Root的无参数的构造器");//5)
}
}
class Mid extends Root {
static {
System.out.println("Mid的静态初始化块");//2)
}
{
System.out.println("Mid的普通初始化块"); //6)
}
public Mid() {
//隐藏super();访问无参构造方法
super() ;
System.out.println("Mid的无参数的构造器");//7)
}
public Mid(String msg) { //"hello"
this(); //访问的本类中无参构造方法
System.out.println("Mid的带参数构造器,其参数值:" + msg);//8)
}
}
class Leaf extends Mid {
static {
System.out.println("Leaf的静态初始化块");//3)
}
{
System.out.println("Leaf的普通初始化块");//8)
}
public Leaf() {
super("hello");//显示的访问父类有参构造方法
System.out.println("Leaf的构造器"); //9)
}
}
public class LeafTest {
public static void main(String[] args) {
new Leaf();
}
}
继承
引入 继承(extends)
1.什么是继承
将多个事物(类)的共性内容,抽取到一个独立的事物(类)中,这个事物(类)和其他事物(类)之间会产生一种关系,称为“继承”(extends)。
格式:
class 父类名{
共性内容:属性私有化
对外提供公共的访问方法
}
class 子类名 extends 父类名{
}
2.继承的特点、好处和弊端
继承的特点:
1)类和类之间的关系,只支持“单继承”
2)不支持多继承,但是可以“多层继承”
继承的好处:
1)提高了代码的复用性
2)提高了代码的维护性(方便后期维护)
3)类与类产生的继承关系,是多态的前提条件
继承的弊端:
类和类之间的继承关系是存在局限性的,不要为了使用部分功能而使用继承
3.继承的注意事项和使用时机
继承里面的注意事项:
1)子类继承父类:继承父类的非私有成员,私有成员可以直接访问
2)子类继承父类,构造方法是不能继承的,通过一个关键字super()访问
使用继承的时机:
如果一个类A是类B的一种,或者B类是A类的一种,这个时候使用继承
4.继承的成员变量访问问题
/*所有开发原则都必须遵循:“低耦合,高内聚”
耦合:类和类的关系越少越好(耦合度只能降低,不能避免)
内聚:某一个类完成某件事情的能力!(一个类能完成的,尽量一个类去写)
继承的成员变量访问问题
1)子类继承父类,如果子类和父类的成员变量名称不一致(分别访问即可)
2)子类继承父类,子类和父类的成员变量名一致,访问采用(就近原则)
就近原则机制
1)首先在子类的局部位置找,如果有就使用
2)如果子类的局部位置没有,那么就在子类的成员位置找
3)如果子类的成员位置也没有,就在弗雷的成员位置找
*/
class Father {
public int num1 = 10 ;
public int number = 100 ;
}
//子类
class Son extends Father{
public int num2 = 20 ;
public int number = 200 ;
//成员方法
public void show(){
//局部变量
// int number = 300 ;
//System.out.println(num1) ;//10
//System.out.println(num2) ;//20
System.out.println(number);
}
}
//测试类
public class ExtendsDemo2 {
public static void main(String[] args) {
//创建子类对象
Son s = new Son() ;
s.show();
}
}
5.继承的构造方法问题
继承的构造方法访问问题
1)子类继承父类,子类的所有构造方法的默认第一句话都super();访问父类的无参构造方法
子类的所有构造方法都默认访问父类的无参构造方法(子类的多余构造方法的第一句话是super()可以省略不写)
6.继承的成员方法访问问题
/*继承的成员方法访问问题
子类继承父类,如果子类和父类的成员方法名称不一致,分别调用即可
如果一致而且一模一样,方法重写override(方法覆盖/方法重写),重写的时候必须要保证他的访问权限足够大
方法重写:
继承中使用,子类出现了父类一模一样的方法,目的就是为了将父类的进行重写*/
class Fu{
void show(){
System.out.println("show Fu");
}
}
//子类
class Zi extends Fu{
//@Override
// jdk提供注解:标记的当前这个方法重写父类的方法,可以省略不写(只要你的方法和父类的一模一样,代码前面就有o标记)
/* void show(){ //访问不能更低
// super.show() ; //间接访问父类的成员方法
System.out.println("show Zi") ;
}*/
@Override
public void show() {//访问权限要足够大!
//完成子类的自己业务...
}
public void method(){
System.out.println("method Zi");
}
}
//测试类
public class ExtendsDemo4 {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi() ;
zi.show();
zi.method();
}
}
7.面试题—继承
如果父类没有给出无参构造方法,子类会出现什么情况?如何解决?
1)解决方法1:永远给出类的无参构造方法
2)如果不给出无参构造方法,让子类的所有构造方法显示的访问父类的有参构造方法!(只要父类出现初始化,:执行构造方法就是初始化)
3)子类的所有构造方法中的某一个只要能让父类初始化即可
创建Zi zi=new Zi();在执行Zi类的无参构造方法的时候
让它先执行子类的有参构造方法 this(xx) ;
让后在子的有参构造方法中,让它先让父类初始化 super(xx) ; 访问父类的有参构造方法
使用继承关系 编码的时候:----idea生成 alt+ins---->constructor--->
子类的无参构造方法 访问父类的无参构造方法
子类的有参构造方法 直接访问父类的有参构造方法
8. final关键字
特点:
1)可以修饰类,该类不能被继承
2)修饰成员变量,此时这个变量是常量! (自定义常量)
3)final也可以修饰成员方法,但是不能被重写
class Father{
public int num = 100; //变量
//被final:这个成员变量只能被赋值一次!
public final int num2 = 20; //如果final修饰成员变量 必须赋值!(基本类型)
public void show(){
final int num3 ; //局部位置定义变量
num3 = 20 ;
// num3 = 100; //被final修饰的局部变量,只能被赋值一次
System.out.println(num3);
}
public final void function(){
System.out.println("function Fu");
}
}
class Son extends Father{
public void method(){
System.out.println(num) ;
System.out.println(num2);
}
//不能重写父类的final的方法
/* public void function(){
}*/
}
//测试类
public class FinalDemo {
public static void main(String[] args) {
Son s = new Son() ;
s.method();
s.num = 200 ;
//s.num2 = 10 ;
s.show() ;
s.function() ;
}
}
9. final面试题
修饰基本数据类型和引用类型的区别
被final修饰的基本数据类型,它的数据值不能再改变了
被final修饰的引用数据类型,引用类型空间地址之不再改变
class Student{
int age ;
}
//测试类
public class FinalDemo2 {
public static void main(String[] args) {
//final修饰的基本数据类型
int x = 10 ;//没有加入final修饰
x = 20 ;
System.out.println("x:"+x);
System.out.println("---------------------------------") ;
final int y = 30 ;//加入final修饰
// y = 40 ; //被final修饰的变量,它的数据值不能再改变了
System.out.println(y);
System.out.println("----------------------------------");
Student s = new Student() ;//创建学生对象
s.age = 20 ;
s = new Student() ; //重新堆内存开辟空间
s.age = 30 ;
System.out.println(s.age);
System.out.println("----------------------------------");
final Student s2 = new Student() ;
//s2 = new Student() ; //final修饰引用数据类型, 引用类型 空间地址值不再改变!
s2.age = 40 ;
System.out.println(s2.age);
}
}
10. this和super的区别
this:代表当前类对象的地址值引用
super:代表父类的空间表示(父类的对象的地址值引用)
使用不一样:
this.变量名:访问本类的成员变量
super.变量名:访问父类的成员变量
this.方法名():访问本类的成员方法
super.方法名():访问父类的成员方法
this.():访问本类的无参构造函数
this.(xx):访问本类的有参构造函数
super():访问父类的无参构造函数
super(xx):访问父类的有参构造函数
11.方法重写和方法重载的区别
方法重载Overload:
定义方法的时候,多个方法的方法名相同,参数列表不同,与返回值无关(目的:提高了方法扩展性)
参数列表不同:
1)参数个数
2)参数类型
3)先后顺序
方法重写Override:
在继承中,子类出现和父类一模一样的方法声明,子类会将父类的方法覆盖,使用子类的一些自己功能;
重写的时候,要保证访问权限足够大!(重写的目的:)
多态
引入概念—多态(重点)
1.多态的概念、前提
多态的概念:
从现实世界事物中考虑:“多态”一个事物的多种形态
Java面向对象中“多态”:一个类体现出内存的变化
多态的前提:
1)必须有继承关系
2)必须存在方法重写
3)必须要存在父类引用指向子类对象
格式
父类名 对象名 = new 子类名();
2.多态的成员访问特点
多态的成员访问特点:
1)成员变量:编译看左,运行看左
2)成员方法:编译看左,运行看右(非静态成员方法)
静态方法:算不上方法重写,这种跟类相关,类
一加载就可以直接使用(类名.方法名())
3)构造方法:由于存在继承,构造方法在执行的时候,分层初始化,让父类先初始化,然后再是子类进行构造
3.多态的好处、特点和弊端
多态的好处:
1)提高代码的扩展性(父类引用指向子类对象)
2)可以提高代码复用性以及维护性
多态的特点
多态的弊端:
父类引用你指向子类对象;这种格式无法访问子类的特有功能
解决方案:
1)直接创建子类对象 子类名 对象名=new 子类名()
虽然可以,但是new 子类名(),需要开辟对内存空间
2)推荐向下转型
将父类引用强转为子类引用
父类名 父类引用=new 子类名();向上转型
Fu f= new Zi()
子类名 对象名=(子类名)父类的引用;向下转型 前提必须有向上转型
Zi z=(Zi) f;
可能存在问题:
如果向下转型(将父类强转为子类),使用不当,会导致程序出现异常,类转换异常
抽象
abstract关键字(抽象)
什么是抽象类?
一个事物的某个行为在具体的事物中的具体体现,将这个事物顶层次(父类)定义为"抽象"
抽象的定义:abstract class 类名{}
有抽象方法的类一定是抽象类,抽象类不一定都是抽象方法!
抽象方法的格式:
权限修饰符 返回值类型 方法名(空参/无参);
抽象类的成员特点:
1)抽象类不能实例化
2)如果抽象类的子类也是抽象类,不能实例化,一定会提供最具体的子类 完成实列 如果子类下面没有子类(没有任何意义!)
抽象类的成员特点:
成员变量:
既可以是变量,也可以是常量
成员方法:
既可以存在抽象方法(强制子类必须重写),也可以定义非抽象方法
构造方法:
无参/有参构造方法都可以存在,
面试题:抽象
如果一个类没有任何抽象方法,把这个类定义为抽象类的意义?
意义是,不让外界类直接创建对象(抽象类不能创建对象)----需要提供具体的子类进行实例化
abstract在使用他时,和哪些关键字冲突
不能和private一块用:被private修饰的成员需要在当前类进行访问,而如果加入abstract,强制子类完成
不能和final一块儿应:被final修饰的成员方法,不能被重写!而abstract抽象方法,必须强制子类重写
不能和static一块用:被static修饰的成员方法,算不上重写!
应用范围:
1)定义类---抽象类
2)定义方法---抽象方法
接口
接口(比抽象还抽象的一种概念)
什么是接口?
接口 体现的是事物本身不具备的功能,额外的功能;
接口的定义:java代码定义
关键字interface 接口名{}
接口标识符---->和类名起名字一直“大驼峰命名法”
要实现接口里面的额外功能 才具备这功能
开发中定义接口的实现类名
class 接口名+Impl implement(实现) 接口名{
}
接口的特点:
1)接口的方法不能有方法体,只能是抽象方法,而且隐藏public abstract(可以不写)
2)接口不能实例化(不能创建对象)
3)如果接口的实现类是一个抽象类(不能实例化),肯定有一个具体的接口的实现类来进行new
接口多态:
接口不能new,但接口的具体的子实现类可以new
Jump junp=new Cat();
接口的成员特点:
成员变量:只能是常量---存在默认修饰符 public static final
成员方法:只能是抽象方法---存在默认修饰符 public abstract
构造方法:没有构造方法
类与接口的关系:
实现关系----->implements
class 子实现类名 implement 接口名{}
方法的形式参数如果是引用类型—>类,调用方法实际参数如何传递?
//如果形式参数传递的是具体类---->需要调用的时候,传递当前具体类 对象
interface Inter{
void add(User user);
}
class User{
private String name;//
private String password;
}
class InterImpl implements Inter{
void add(User user){
User[] users=new User[5];
}
}
面试题:接口—类
接口和抽象类的区别?
1)成员的区别
抽象类:
成员变量:既可以是常量,也可以是变量
成员方法:既可以是抽象方法,也可以是非抽象方法
构造方法:无参/有参构造都存在,子类父类继承,需要分层初始化接口
接口:
成员变量:只能是常量
成员方法:只能是抽象方法
构造方法:没有,需要借助子类实现类进行实例化
2)关系的区别
类与类:可能是一些抽象类,继承关系,支支持单继承不支持多继承,但是可以多层继承
类与接口:实现关系implements,一个类继承另一个类(可能也是抽象类)的同时,话可以实现多个接口
接口与接口:继承关系 extends,支持单继承,也可以多继承,多层继承
3)设计理念的区别
抽象类---不能实例化
需要通过具体的子类实现类(继承关系)
核心设计理念都是一种“is a”的关系(xxx是xx的一种)
接口----不能实例化
需要通过具体的子类实现类进行实例化(实现关系impls)
设新设计理念体现的是事物的额外功能看成“like a”的关系(xxxx像xxx一样)
关于类与类,类与接口,接口与接口的关系
Java中最基本的单元就是类! Java中只支持单继承
类与类:只支持单继承,不支持多继承,但是可以多层继承
类与接口:是实现关系,一个类继承另一个类的同时,可以实现多个接口
接口与接口:(继承关系)不仅可以单继承,也可以多继承
形式参数的问题和返回值问题
方法形式参数如果是引用类型
数组 需要传递数字对象
类
具体类----实际参数,需要传递当前类对象
抽象类----抽象类不能实例化,,实际参数传递该抽象类的子类对象
接口
接口不能实例化,实际参数需要传递该接口的子实现对象(接口多态)
方法的返回值问题:
1)返回值基本类型,需要什么基本数据类型,使用对应的类型接受
2)研究引用类型
类:
具体类:需要返回的是当前具体类的对象!
抽象类:需要返回的是当前抽象类的子类对象(抽象多态)
接口
需要返回的是接口的子实现类对象(接口多态)
包
包package的含义
package包---本质就是文件夹(目录)
程序员编写代码存储的地址
包--->开发中(公司域名反写,多个包中间.隔开)
包---为了维护代码结构的
com.qf.pojo/domain/entity 存放Java实体类(满足JavaBean规范)
1)这个类是私有类
2)属性私有化(属性必须全部字母小写)
3)对外提供公共的set/get
权限修饰符
在同一个包 | 在同一个包 在不同包 在不同包
下的同一个类 | 下的子类/无关类中 下的子类中 的不同类中
默认修饰符 Y | Y Y N
private Y | N N N
protected Y | Y N N
public Y | Y Y Y
私有修饰符private:权限最小(开发中,也就是定义实体类(描述现实事物),属性私有化)
public:权限最大
protected:一般源码中见到(二阶段前后端交互)
面试题:内部类
局部内部类访问它的成员方法里面的局部变量,局部变量有什么特点
jdk7以前版本:局部内部类访问局部变量的时候,局部变量不许使用final修饰
局部变量它随着方法的调用而存在,随着方法的调用结束而消失,但是现在通过局部对象调用它的成员方法还在使用这个局部变量,局部变量必须为常量(加入final)---局部内部类对象不会立即消失,等待gc回收!
jdk8以及jdk8以后 jvm已经对这个局部变量优化 ,将final已经省略了!
外部类和内部类:没有继承关系
选择排序
选择排序
数组角标从开始,将它对应元素依次和后面的元素比较,将小的往前放,第一次比较完毕,最小值就出现在最小索引处!一次这样比较,可以得到一个排好序的数组!
规律
1)每一次都是某个角标对应元素都要依次后面角标对应的元素比较后面的元素比前面的小,将后面的元素往前方
//测试类
public class ArrayTest {
public static void main(String[] args) {
//提供一个数组,静态初始化
int[] arr = {24,69,87,56,13} ;
System.out.println("排序前:") ;
String str = printArray(arr) ;
System.out.println(str) ;
System.out.println("------------------------------------") ;
System.out.println(printArray(arr)) ;
int[] arr2 = selectSort(arr);
System.out.println(Arrays.toString(arr2));//Arrays数组工具类toString--->将数组转换成String
}
//定义一个选择排序的方法
public static int[] selectSort(int[] arr){
for(int x = 0 ; x < arr.length - 1;x++){//比较的次数
for(int y = x+1; y < arr.length;y++){ //元素进行判断 比较
//如果前面的元素比较后面元素大,将后面的元素往前放
if(arr[x] > arr[y]){
int temp = arr[x] ;
arr[x] = arr[y] ;
arr[y] = temp ;
}
}
}
return arr;
}
//遍历数组 --->没有返回值类型void--->直接输出
public static String printArray(int[] arr){
//定义一个字符串
String s = "" ; //结果变量
s+= "[" ;
//遍历数组
for(int x = 0 ; x < arr.length ; x++){
if(x==arr.length-1){
//取到最大索引值,对应最后一个元素
s+=arr[x] ;
s+="]" ;
}else{
//中间角标对应的元素
s+= arr[x] ;
s+=", ";
}
}
return s;
}
}
object
Java常用类之 java.lang.Object类
表示所有的类的根类(超类或者父类),所有的类默认继承自Object,拥有这个类的所有非私有方法
public final Class getClass() :("反射"后面讲的)获取任意Java类型的字节码文件对象 (返回值表示正在运行的那个类或者接口)
面试题
在Java中获取一个类的字节码文件对象的方式有几种?
三种方式
public final Class getClass() 任意java对象调用getClass()
任意Java类型的class属性
Class类有一个静态方法 forName("包名.类名") ---反射中讲
ublic class ObjectDemo {
public static void main(String[] args) {
//创建两个学生对象
Student s1 = new Student() ;
Student s2 = new Student() ;
System.out.println(s1);
System.out.println(s2);
System.out.println(s1==s2) ; //== 连接的两个引用类型 :比较的是地址值是否相同 false
System.out.println("----------------------------------------------") ;
// public final Class getClass() :获取字节码文件对象 (Class类对象)
//s1和s2两个对象调用getClass()
Class c1 = s1.getClass();
System.out.println(c1);
Class c2 = s2.getClass();
System.out.println(c2);
System.out.println(c1==c2) ;
System.out.println("------------------------------") ;
Class c3 = Student.class ;
System.out.println(c3);
System.out.println(c1==c3);
System.out.println(c2==c3);
System.out.println(Demo.class) ;
//JNI---Java Native Interface --->Java本地接口
}
}
class Demo{}