堆(Heap) :此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
栈(Stack) :是指虚拟机栈。虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。
方法区(Method Area) :用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
基础
public class test {
public static void main(String[] args){
System.out.println("hello world");
}
}
关键字
【基础篇】Java关键字(超详细)-CSDN博客
package
java中文件的大小分配:project--> module --> package -->class
这个关键字放置在class的顶部,用于声明这个class属于哪个package
package 顶层包名.子包名 ;
JDK中主要的包介绍:
java.lang ----包含一些Java语言的核心类,如String、Math、Integer、 System和Thread,提供常用功能
java.net ----包含执行与网络相关的操作的类和接口。java.io ----包含能提供多种输入/输出功能的类。
java.util ----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
java.text ----包含了一些java格式化相关的类
java.sql ----包含了java进行JDBC数据库编程的相关类/接口
java.awt ----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
import(导入)
为了使用定义在其它包中的Java类,需用import语句来显式引入指定包下所需要的类
- import语句,声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 如果使用a.* 导入结构,表示可以导入a包下的所有的结构。举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果已经导入java.a包下的类,那么如果需要使用a包的子包下的类的话,仍然需要导入。
- 如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的是哪个类。
- (了解) import static 组合的使用:调用指定类或接口下的静态的属性或方法
数据类型
数据类型 变量名=值
数据类型:
声明long时需要在最后加L或l,float要加f或F
long a=100000L
float b = 0.2f
类型转换--自动类型提升(小->大)
1、byte->short->int->long->float->double,按照表示数字的范围排序,小的可以转换为大的。例如 下面这种是合理的,但是反过来不行
byte a = 2; int c ;c = a //ok
byte a ; int c=2 ;a = c //no
2、在运算中,会符合运输数中最 大 的那个数据类型:
double a=7;int b=3;int c = a+b; //no
long a=7;int b=3;double c = a+b; //ok
3、byte,short,char做运算,结果都为int(从char到int会转换为字符的ascll码)
byte a=1;short b=3; short c=a+b//no,a+b的结果已经转换为了int
4、下面这个,123是int类型,转换为了long,所以不写123L也不会报错
long a = 123
5、未定义的数字,整数默认为int,小数默认为double
类型转换--强制转换(大->小)
int a = (int) 123.22;
System.out.println(a); //123
字符串
String a = "i love you";
int b =3;
short c = 4;
boolean d = false;
String e = c+b+a+d;
System.out.println(a); //i love you
System.out.println(a+b); //i love you3
System.out.println(e); //7i love youfalse
强转数据类型不可行
String a = "10";
int b =(int) a;//no
运算符
++ ,--不改变数据的类型
short a = 1;short b=++a;//合理,不等价于 short a = 1;short b=a+1(无法运行);
同理,赋值运算符也不改变数据的类型
&&只要有一个条件不一样就是不满足,如果第一个条件就是不满足就不判断后面的条件。而&要对所有的条件都进行判断。
||和|都是表示“或”,区别是||只要满足第一个条件,后面的条件就不再判断,而|要对所有的条件进行判断。
三元运算符
int a = (3>1)?2:3;
流程控制
if..else:
if (条件表达式1) {
语句块1;
} else if (条件表达式2) {
语句块2;
}
...
}else if (条件表达式n) {
语句块n;
} else {
语句块n+1;
}
从键盘获取输入
import java.util.Scanner;
public class test {
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
String name = scan.next();
System.out.println("my name is "+name);
}
}
也可以指定获取的数据类型,例如
int age = scan.nextInt();
double salary = scan.nextDouble()
Switch case
switch(表达式){
case 常量值1:
语句块1;
//break;
case 常量值2:
语句块2;
//break;
// ...
[default:
语句块n+1;
break;
]
}
按照顺序执行,出发遇到break,例如
int num = 1;
switch(num){
case 0:
System.out.println("zero");
case 1:
System.out.println("one");
case 2:
System.out.println("two");
case 3:
System.out.println("three");
default:
System.out.println("other");
//输出one two three other
所以每个case都需要带break
switch(num){
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
case 3:
System.out.println("three");
break;
default:
System.out.println("other");}
也可以在case处实现 或 的写法:
switch(num){
case 0:
case 1:
System.out.println("zero or one");
break;
case 2:
case 3:
System.out.println("two or three");
break;
default:
System.out.println("other");
}
for循环
for (①初始化部分; ②循环条件部分; ④迭代部分){
③循环体部分;
}
for(int i=0;i<10;i++){
System.out.println(i);
}
while
①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}
int i=0;
while(i<10){
System.out.println(i);
i++;
}
do-while循环
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分); //满足条件才继续循环
int i = 0;
do{
i++;
System.out.println(i);
}while(i<=20);
最简单"无限"循环格式,需要搭配break
while(true) , for(;;), for(;true;)
break和continue
用于跳出循环和进入下一次循环
在多层循环嵌套中,可以使用label指定跳出的循环,例如:
class BreakContinueTest2 {
public static void main(String[] args) {
lable:for(int i = 1;i <= 4;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0){
//break l;
continue lable;
}
System.out.print(j);
}
System.out.println();
}
}
}
数组
单层数组
初始化和定义:
double[] salary = new double[]{1.1,2.2,3.3,4.4};
String[] name = new String[]{"lmx","lby","lll"};
int[] day = {1,2,3};
int[] age = new int[6];
元素调用
System.out.println(salary[2]);
赋值
salary[2] = 7;
数组的长度
System.out.println(salary.length);
多维数组
定义
int[][] ifo1 = new int[][]{{2,3},{1,2},{3,4}};
int[][] ifo2 = {{2,3},{1,2},{3,4}};
String[][] if3 = new String[3][4];
动态定义:
String[][] if3 = new String[3][];
if3[0] = new String[]{"lmx","lby"};
if3[1] = new String[]{"lmx1","lby","ppp"};
调用
System.out.println(ifo2[1][1]);
默认值,不同的数组类型的默认值是不一样的:
int[][] ifo1 = new int[1][1];
String[][] ifo2 = new String[1][1];
boolean[][] ifo3 = new boolean[1][1];
System.out.println(ifo1[0][0]); //0
System.out.println(ifo2[0][0]); //null
System.out.println(ifo3[0][0]); //false
常用方法
Arrays.toString 转为字符串
System.out.println(Arrays.toString(ifo1));
Arrays.equals 数组比较
System.out.println(Arrays.equals(ifo2,ifo1));
Arrays.fill 替换全部
int[] ifo2 = new int[10];
Arrays.fill(ifo2,10);
System.out.println(Arrays.toString(ifo2));
//[10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
Arrays.sort 排序
Arrays.sort(ifo1);
System.out.println(Arrays.toString(ifo1));
二分查找
Arrays.binarySearch(ifo1,12)
面向对象
基础
定义类:
public class person {
int age;
String name;
public void say(String str){
System.out.println(str);
}
public void say_age(){
System.out.println(age);
}
}
创造对象,调用对象:
person p1 = new person();
p1.name="lmx";
p1.age = 22;
p1.say("ggggg");
p1.say_age();
成员变量 vs 局部变量
二者区别:
1、声明位置和方式 (1)实例变量:在类中方法外 (2)局部变量:在方法体{}中或方法的形参列表、代码块中
2、在内存中存储的位置不同 (1)实例变量:堆 (2)局部变量:栈
3、生命周期 (1)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的。 (2)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡, 而且每一次方法调用都是独立。
4、作用域 (1)实例变量:通过对象就可以使用,本类中直接调用,其他类中“对象.实例变量” (2)局部变量:出了作用域就不能使用
5、修饰符(后面来讲) (1)实例变量:public,protected,private,final,volatile,transient等 (2)局部变量:final
6、默认值 (1)实例变量:有默认值 (2)局部变量:没有,必须手动初始化。其中的形参比较特殊,靠实参给它初始化。
方法
Java里的方法不能独立存在,所有的方法必须定义在类里。
方法中可以调用类中的方法或属性,不可以在方法内部定义方法
[修饰符] 返回值类型 方法名([形参列表])[throws 异常列表]{
方法体的功能代码
}
修饰符:可选的。方法的修饰符也有很多,例如:public、protected、private、static、abstract、native、final、synchronized等。
其中,权限修饰符有public、protected、private。在讲封装性之前,我们先默认使用pulbic修
饰方法。
其中,根据是否有static,可以将方法分为静态方法和非静态方法。其中静态方法又称为类方法,非静态方法又称为实例方法。
返回值类型: 表示方法运行的结果的数据类型,方法执行后将结果返回到调用者。无返回值,则声明:void
有返回值,则声明出返回值类型(可以是任意类型)。与方法体中“ return 返回值”搭配使用
public int getIntBetweenOneToHundred(){
return (int)(Math.random()*100+1);
}
对象数组
数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用类型中的类时,我们称为对象数组。
也就是说,数组中包含的都是类的对象,例如:
String[],person[],Student[]
方法重载
方法重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可。
参数列表不同,意味着参数个数或参数类型的不同
重载的特点:与修饰符、返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
重载方法调用:JVM通过方法的参数列表,调用匹配的方法。
先找个数、类型最匹配的再找个数和类型可以兼容的,如果同时多个方法可以兼容将会报错
public class person {
int number,state,score;
static void say(int x){
System.out.println("one");
System.out.println(x);
}
static void say(String name){
System.out.println("two");
System.out.println(name);
}
}
可变个数的形参
即当定义一个方法时,形参的类型可以确定,但是形参的个数不确定,那么可以考虑使用可变个数的形参。
1. 可变个数形参的方法与同名的方法之间,彼此构成重载
2. 可变参数方法的使用与方法参数部分使用数组是一致的,二者不能同时声明,否则报错。3. 当有多个重载方法,调用形参最像的那个
4. 方法的参数部分有可变形参,需要放在形参声明的最后
5. 在一个方法的形参中,最多只能声明一个可变个数的形参
2. 可变参数方法的使用与方法参数部分使用数组是一致的,二者不能同时声明,否则报错:
public static void print(int[] nums){
System.out.println(nums[0]);
}
public static void print(int...nums){
System.out.println("@2222");
}
上面两种方法都能定义可变形参,但是两者是不能同时定义的,认为其形参一样
但是二者的调用方法是有区别的,两者方法都可以使用下面这种调用
print(new int[]{1,2,3});
但是下面这种调用只适合 int...nums 这种形参的:
print(1,2,3);
3. 当有多个重载方法,调用形参最像的那个
public class Main {
public static void main(String[] args) {
print(1); //2222
}
public static void print(int...nums){
System.out.println(nums[0]);
}
public static void print(int i){
System.out.println("2222");
}
}
封装性
java内部设置了四种修饰符:
规则:
外部类:public、缺省
成员变量、成员方法、构造器、成员内部类:public、protected、缺省、private
构造器
我们能不能在new对象时,直接为当前对象的某个或所有成员变量直接赋值呢? 可以,Java给我们提供了 构造器(Constructor) ,也称为 构造方法。
[修饰符] class 类名{
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
}
1. 构造器名必须与它所在的类名必须相同
2. 它没有返回值,所以不需要返回值类型,也不需要void。
3. 构造器的修饰符只能是权限修饰符,不能被其他任何修饰。比如,不能被static、final、 synchronized、abstract、native修饰,不能有return语句返回值。
public class Main {
public static void main(String[] args) {
person p1 = new person();
p1.say();
person p2 = new person("lll",30);
p2.say();
}
}
class person{
private String name;
private int age ;
public person(){
name = "lmx";age = 20;
}
public person(String n,int a){
name = n;
age = a;
}
void say(){
System.out.println(name);
System.out.println(age);
}
}
一个类中可以有多个构造器,彼此形成重载
可以给类的属性赋值的过程:
① 默认初始化
② 显式初始化
③ 构造器中初始化
④ 通过"对象.属性"或"对象.方法"的方式,给属性赋值
顺序:
1-2-3-4
JavaBean
JJavaBean是一种Java语言写成的可重用组件。是指符合如下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
例如
class person{
private String name;
private int age ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
this
当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量。
可以使用this调用对象的属性和方法:
class Person{ // 定义Person类
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public void getInfo(){
System.out.println("姓名:" + name) ;
this.speak();
}
public void speak(){
System.out.println(“年龄:” + this.age);
}
}
也可以调用构造器,
- this():调用本类的无参构造器
- this(实参列表):调用本类的有参构造器
public class Student {
private String name;
private int age;
// 无参构造
public Student() {
// this("",18);//调用本类有参构造器
}
// 有参构造
public Student(String name) {
this();//调用本类无参构造器
this.name = name;
}
// 有参构造
public Student(String name,int age){
this(name);//调用本类中有一个String参数的构造器
this.age = age;
}
}
继承
[修饰符] class 类A {
...
}
[修饰符] class 类B extends 类A {
...
}
class person{
int age = 20;
public void say(){
System.out.println("lllll");
}
}
class student extends person{
public void get_age(){
System.out.println(this.age);
this.say();
}
}
1、子类会继承父类所有的实例变量和实例方法
但是由于封装的原因,子类可能不能直接调用某些父类的属性和方法,子类可以重新声明父类的属性和方法,相当于重写
2、顶层父类是Object类。所有的类默认继承Object,作为父类。
可以使用s1.getClass().getSuperclass()获取父类
3、Java只支持单继承,不支持多重继承(java的单继承性)
方法重写
子类重写的方法
必须
和父类被重写的方法具有相同的方法名称、参数列表。如果父类的方法返回值是基本数据类型,则子类的必须一样。如果父类方法的返回值是引用数据类型(例如类),则子类方法返回值不能比其大(例如不能是这个类的父类)
只有方法才能重写覆盖,属性是无法重写覆盖的
super
- super可用于访问父类中定义的属性
- super可用于调用父类中定义的成员方法
- super可用于在子类构造器中调用父类的构造器
注意事项:
- 尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
- super的追溯不仅限于直接父类
- super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识
class person{
int age = 0;
public void say(){
System.out.println("aaa");
}
}
class student extends person{
int age = 22;
public void say(){
System.out.println("bbb");
}
public void test(){
this.say(); //bbb
super.say(); //aaa
System.out.println(this.age);//22
System.out.println(super.age); //0
}
}
super调用构造器
① 子类继承父类时,不会继承父类的构造器。只能通过“super(形参列表)”的方式调用父类指定的构造器。
② 规定:“super(形参列表)”,必须声明在构造器的首行。
③ 在构造器的首行可以使用"this(形参列表)",调用本类中重载的构造器,结合②,结论:在构造器的首行,"this(形参列表)" 和 "super(形参列表)"只能二选一。
④ 如果在子类构造器的首行既没有显示调用"this(形参列表)",也没有显式调用"super(形参列表)",则子类此构造器默认调用"super()",即调用父类中空参的构造器。
⑤ 由③和④得到结论:子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器。只能是这两种情况之一。
⑥ 由⑤得到:一个类中声明有n个构造器,最多有n-1个构造器中使用了"this(形参列表)",则剩下的那个一定使用"super(形参列表)"。