一、java基础语法:
类:包含了属性和方法,描述了一类对象的行为和状态。类的写法:首字母大写。如果是多个单词的组合,那么每个字母的首字母都大写
对象:是类的实例。包含了类中定义的属性和方法。
实例变量:是对象的属性。每个对象都有独特的实例变量,对象的状态由这些属性决定。实例变量必须创建了对象之后才能由对象来引用这个实例变量。
面试问法:静态变量、实例变量、成员变量、局部变量的区别
静态变量用static修饰。只要程序加载了类的字节码,不需要创建实例对象,就会为静态变量分配空间。静态变量独立于方法之外,又称类变量,无论实例化多少个对象,静态变量都只有一个,也就是说所有的实例对象修改的都是同一个静态变量,存储在静态存储区。可以直接用类名调用,也可以用对象名调用。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
实例变量:独立于方法之外,不用static修饰,声明在一个类中,但在方法、构造语句和语句块之外。数值型变量默认值为0,布尔型变量默认值为false,引用类型默认值为null
成员变量:成员变量包括实例变量和静态变量,定义在方法体和语句块之外,一般定义在类的声明下。成员变量可以被类中方法、构造方法和特定类中的语句块访问。存储在堆内存的对象中
局部变量:定义在方法内部、构造方法或语句块中,不用访问控制符修饰,在栈上分配,没有默认值必须初始化。变量声明和初始化都在方法中,方法结束后变量会自动销毁
成员变量和类变量的区别:
成员变量和类变量的区别
成员变量和类变量的区别:
1、两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的回收而释放。静态变量随着类的加载而存在,随着类的消失而消失。
2、调用方式不同
成员变量只能被对象调用。 静态变量可以被对象调用,还可以被类名调用。
3、别名不同
成员变量也称为实例变量。静态变量也称为类变量。
4、数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
static 关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
特点:
1、想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
2、被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3、静态随着类的加载而加载。而且优先于对象存在。
弊端:
1、有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2、静态方法只能访问静态成员,不可以访问非静态成员。
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3、静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
什么时候定义静态成员呢?或者说:定义成员时,到底需不需要被静态修饰呢?
成员分两种:
1、成员变量。(数据共享时静态化)
该成员变量的数据是否是所有对象都一样:
如果是,那么该变量需要被静态修饰,因为是共享的数据。
如果不是,那么就说这是对象的特有数据,要存储到对象中。
2、成员函数。(方法中没有调用特有数据时就定义成静态)
如果判断成员函数是否需要被静态修饰呢?
只要参考,该函数内是否访问了对象中的特有数据:
如果有访问特有数据,那方法不能被静态修饰。
如果没有访问过特有数据,那么这个方法需要被静态修饰。
成员变量和静态变量的区别:
1、成员变量所属于对象。所以也称为实例变量。
静态变量所属于类。所以也称为类变量。
2、成员变量存在于堆内存中。
静态变量存在于方法区中。
3、成员变量随着对象创建而存在。随着对象被回收而消失。
静态变量随着类的加载而存在。随着类的消失而消失。
4、成员变量只能被对象所调用 。
静态变量可以被对象调用,也可以被类名调用。
所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
方法:方法就是行为,一个类可以有多个方法。方法的写法:所有的方法都应该是小写字母开头。如果是多个单词的组合,那么第一个单词的首字母小写,其余单词的首字母均为大写
package com.cuiinsist.myfirst.mapper;
public class BianLiang {
private int id; //private修饰的变量必须通过get\set方法设置或获取
private String name;
private String sex;
public int nua;
public static final String school="xian university"; //final修饰的成员变量必须被初始化,在主程序里用final修饰的变量不需要
public static int num;
public int getId(){
return id;
}
public String getName(){
return name;
}
public String getSex(){
return sex;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name){
this.name=name;
}
public void setSex(String sex){
this.sex=sex;
}
public void infoStu(){
String str1="我是";
String str2="瑞";
System.out.println("学生信息"+str1+str2);
num++;
System.out.printf("num:"+num);
System.out.printf("布尔默认值"+nua);
}
public static void main(String[] args) {
BianLiang bianhua=new BianLiang();
bianhua.setId(1);
bianhua.setName("lili");
bianhua.setSex("man");
bianhua.infoStu();
System.out.printf("学校:"+BianLiang.school+"学生信息"+bianhua.getId()+"姓名"+bianhua.getName()+"性别:"+bianhua.getSex());
BianLiang bianbian=new BianLiang();
bianbian.infoStu();
}
}
运行结果:
学生信息我是瑞
num:1布尔默认值0学校:xian university学生信息1姓名lili性别:man学生信息我是瑞
num:2布尔默认值0
num是static修饰,可以看出两个BianLiang对象修改的是同一个num
二、 java标识符
类名、变量名、方法名都被称为标识符。
java标识符命名规则:①所有的标识符都必须以字母(A-Z,a-z)美元符($)、下划线(_)开头,数字不能作为标识符的开头。②:首字母之后,可以是字母、数字、下划线、美元符
③:关键字不能用作标识符 ④:标识符是区分大小写的
三、java修饰符
访问控制符(用来保护对类、变量、方法、构造方法的访问)
default(默认不写):在同一个包中的可以访问,可以用来修饰类、变量、方法、接口
private:仅在同一个类中可用。可以用来修饰变量、方法,不能修饰类和接口(因为接口就是用来被访问修改的,类也是用来被访问的)
protected:对同一个包内的类和子类可用。可用来修饰变量和方法。不能用来修饰类和接口
接口里的变量都隐式声明为public static final,接口里的方法默认情况下都声明为public
private
数据域封装:为了避免对数据域的直接修改,就是将变量声明为private,私有化,使类易于维护。在定义私有域的类外的对象是不能访问这个数据域的。但是为了能够更新私有数据域,可以提供一个set方法给数据域提供新值,为了能够访问私有数据域,可以提供一个get方法返回数据域的值。被声明为 private 的方法、变量和构造方法只能被所属类访问,并且外部类和接口不能声明为 private
公有访问修饰符-public
被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。
如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。
Java 程序的 main() 方法必须设置成公有的,否则,Java 解释器将不能运行该类。
受保护的访问修饰符-protected
protected 需要从以下两个点来分析说明:
-
子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
-
子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。
接口及接口的成员变量和成员方法不能声明为 protected。
子类能访问 protected 修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。如果我们只想让该方法对其所在类的子类可见,则将该方法声明为 protected。
访问控制和继承
请注意以下方法继承的规则:
-
父类中声明为 public 的方法在子类中也必须为 public。
-
父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
-
父类中声明为 private 的方法,不能够被继承
非访问控制符
static 修饰符,用来修饰类方法和类变量。
final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
abstract 修饰符,用来创建抽象类和抽象方法。
synchronized 和 volatile 修饰符,主要用于线程的编程。
static 修饰符
-
静态变量:
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。多个对象共有一个静态变量,也就是说多个对象修改的是同一个静态变量
-
静态方法:
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。如果想使用非静态变量,必须得实例化,实例化之后用对象引用非静态变量。实例方法可以调用实例的方法、数据域,也可以调用静态的方法和数据域
final 修饰符
final 变量:
final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。
final 修饰符通常和 static 修饰符一起使用来创建类常量。
final 方法
父类中的 final 方法可以被子类继承,但是不能被子类重写。
声明 final 方法的主要目的是防止该方法的内容被修改。
abstract 修饰符
抽象类:
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
抽象类可以包含抽象方法和非抽象方法。
抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。
抽象方法不能被声明成 final 和 static。
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
抽象方法的声明以分号结尾,例如:public abstract sample();。
synchronized 修饰符
synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
transient 修饰符
序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。
volatile 修饰符
volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
一个 volatile 对象引用可能是 null。
四、java接口
在 Java 中,接口可理解为对象间相互通信的协议。接口在继承中扮演着很重要的角色。
接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类。
五、Java 源程序与编译型运行区别
如下图所示:
六、java的构造方法:
每个类都有构造方法,如果没有显示地为类添加构造方法,会默认定义一个方法体为空的无参构造方法。这个构造方法称为默认构造方法。当且仅当类中没有明确定义任何构造方法时才会自动提供。
构造方法三个特殊性:
1、构造方法必须具备和所在类相同的名字
2、构造方法没有返回值类型,甚至连void也没有
3、构造方法是在创建一个对象使用new操作符时调用的,不能由程序编写者直接调用,必须由系统调用。构造函数在对象实例化时会被自动调用,且只运行一次,而普通的方法可被调用多次。构造方法的作用是初始化对象。
4、构造方法可以重载(也就是可以有多个同名的构造方法,但他们要有不同的签名方法,也就是参数个数),更易于用不同的初始数据值来构造对象。
5、每个类可以有多个构造函数。每个构造函数可以有0个、1个或1个以上的参数。
6、构造函数不能被继承,因此他不能被覆盖。
package com.cuiinsist.myfirst.mapper;
public class BianLiang {
private String name;
private String sex;
//构造方法
public BianLiang(String newname){
name=newname;
}
public BianLiang(String newname,String newsex){
name=newname;
sex=newsex;
}
public void infoStu(){
System.out.printf("name:"+name);
}
public static void main(String[] args) {
BianLiang bianhua=new BianLiang("lily");
BianLiang bianjia=new BianLiang("jack","female");
bianhua.infoStu();
bianjia.infoStu();
}
}
7、子类可以通过super关键字显示调用父类的构造函数,当父类没有提供无参数的构造函数时,子类的构造函数中必须显示地调用父类的构造函数。如果父类提供了无参数的构造函数,此时子类的构造函数就可以不显示地调用父类的构造函数,这种情况下系统会默认调用父类提供的无参构造函数。有父类时,在实例化对象时会先执行父类的构造函数,然后执行子类的构造函数。
package com.cuiinsist.myfirst.mapper;
class Father{
Father(){
System.out.println("Father");
}
Father(int i){
int j=i;
System.out.println(j);
}
}
public class Son extends Father{//有父类时,实例化对象会先执行父类构造函数
Son(){
//super(1);//在子类的构造函数中显示调用父类的有参构造函数
System.out.println("Son");
}
public static void main(String[] args) {
Son s1=new Son();
}
}
输出结果:
Father
Son
七、java定义类和创建对象
类
可以把两个类放在同一个文件中,但是文件中只能有一个类是公共类(public)。此外,公共类必须和文件同名。源代码中的每个类都会被编译成.class文件。如下代码中,BianLiang.java编译时,会产生两个类文件:BianLiang.class,Moon.class
package com.cuiinsist.myfirst.mapper;
public class BianLiang {
//静态main方法不能引用非静态。所以Moon必须得是静态
static class Moon {
Moon(String newname){
name=newname;
}
Moon(String newname,String newsex){
name=newname;
sex=newsex;
}
//内部类的成员变量不能是static
private String name;
private String sex;
public void infoStu(){
System.out.printf("name:"+name);
}
}
public static void main(String[] args) {
Moon bianhua=new Moon("lily");
Moon bianjia=new Moon("JACK","man");
bianhua.infoStu();
bianjia.infoStu();
}
}
内部类
非静态内部类(需要先实例化外部类,通过外部类的实例来创建内部类的对象)
package com.cuiinsist.myfirst.mapper;
class Outter{
int x=10;
class Inner{
int y=x; //可以调用外部类的成员
}
}
public class Try {
public static void main(String[] args) {
Outter out=new Outter();
Outter.Inner nei=out.new Inner();
System.out.println(out.x+ nei.y);
}
}
输出结果:20
静态内部类(不需要实例化外部类的对象,可以直接new内部类的对象。但是静态内部类不能直接调用外部类的成员)
package com.cuiinsist.myfirst.mapper;
class Outter{
int x=10;
static class Inner{
int y=x;
}
}
public class Try {
public static void main(String[] args) {
Outter.Inner nei=new Outter.Inner();
System.out.println(nei.y);
}
}
输出结果:会报错。因为静态内部类不能直接调用外部类成员。除非把外部类成员变成静态的
匿名类:https://www.runoob.com/java/java-anonymous-class.html
创建对象
使用new来创建一个对象。创建对象需要以下三步:
1、声明:声明一个对象,包括对象名称和对象类型
2、实例化:使用关键字new来创建一个对象
3、初始化:使用 new 创建对象时,会调用构造方法初始化对象。
Moon bianhua=new Moon("lily");
new关键字的作用
1、为对象分配内存空间。
2、引起对象构造方法的调用。
3、为对象返回一个引用。
函数传参
传递对象
传递对象传递的是对象的地址或者引用,修改对象里面的值,实际上是在地址空间里修改这个对象的参数,则参数的值一定会被修改
package com.cuiinsist.myfirst.mapper;
class Bob{
int a=1;
int c=2;
}
public class Try {
public static void main(String[] args) {
Bob bob=new Bob();
func(bob);
System.out.printf("结果:"+"a:"+bob.a+" c:"+bob.c);
}
public static void func(Bob a){
a.a++;
a.c++;
}
}
运行结果:
结果:a:2 c:3
传递参数
传递参数时在另一个函数里修改这个参数,通过return方法只是将结果返回,但是对象里面实际的参数的值没有被改变
package com.cuiinsist.myfirst.mapper;
class Bob{
Bob(){
System.out.println("构造");
}
int a=1;
int c=2;
}
public class Try {
public static void main(String[] args) {
Bob bob=new Bob();
int num=func(bob.a);
System.out.println("return回来的值:"+num+" 对象实际的参数:"+bob.a);
}
public static int func(int a){
int b=a++;
return a;
}
}
运行结果:
构造
return回来的值:2 对象实际的参数:1
问1:为什么需要public static void main(String[] args)这个方法
答:它是java程序的入口方法,JVM在运行程序时,会首先查找main方法。JVM在启动时按照(必须有static public 修饰,返回值为void,且方法的参数为字符串数组)来查找方法的入口地址,若能找到就执行否则报错,该方法不需要实例化对象,存储在静态存储区,main是JVM识别的特殊方法名,是程序的入口方法。
问2:main()方法是否有其他可用的定义格式
1、static public void main(String[] args)
2、public static final void main(String[] args)
3、public static synchronized void main(String[] args)
不能用abstract关键字修饰
问3:同一个.java文件中是否可以有多个main()方法
可以。但是只有与文件名相同的用public修饰的类中的main方法才能作为整个程序的入口方法
问4:如何实现在main()方法执行前输出“Hello”(程序运行时最先加载main()方法,那么main()方法是程序运行时第一个被执行的模块吗)
可以在类里面写一个静态块。在java中,静态块在类被加载时就会被调用,因此可以在main()方法执行前,利用静态块实现输出“hello”的功能。如下所示。
public class Charac { static{ System.out.println("我先出"); } public static void main(String[] args) { System.out.println("我后出"); } }
问5:java程序初始化的顺序是怎样的?
java中实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象
初始化原则(优先级依次递减)
①:静态对象(变量)优先于非静态对象(变量)初始化,其中,静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次
②:父类优先于子类进行初始化
③:按照成员变量的定义顺序进行初始化
不同代码块中的执行顺序:
父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数