一、新建工程
1.新建Java项目
2.新建Class类
按下回车键,新建类便完成了
二、第一个程序hello world
//单行注释,注释代码便于理解,不参与运行
/*
多行注释,不嵌套使用
*/
/**
文档注释(说明性文字和一些JavaDoc标签,后期写项目时可生成项目API)
*/
public class HelloWorld {//HelloWorld类
public static void main(String[] args) {//main方法,程序的入口点,即程序开始的地方
System.out.println("Hello World");//输出Hello World
}
}
- public是访问修饰符,访问修饰符用于指定类、方法或变量的访问范围。
- public :表示该类或方法可以被任何其他类访问。
- main须用 public,以便让 JVM 能够访问和执行它
- void表示main方法没有返回值(return),对于main方法来说,不需要返回值,JVM 只需要执行方法体中的代码。
- String[] args 是 main 方法的参数;
- String是一个类,用来创建和提供操作字符串,args表示数组名(可自行定义);
- String[] args是Java的标准写法,也可以写成String args[].
- System.out.println 是 Java 中的标准输出方法,它会将括号内的内容打印到控制台。
- System 是 Java 类库中的一个类,out 是 System 类的一个静态字段,代表标准输出流,println 是一个方法,用来输出文本并换行。(print 只输出文本不换行)
三、命名规范
使用Unicode字符集包括汉字
汉字(不建议)、字母、下划线、$、数字(不能开头)的任意组合,不能是关键字
类名:每个单词首字母大写,
方法名和变量名:第一个单词首字母小写,其余首字母大写(驼峰原则)
常量:字母全为大写字母和下划线组合
关键字/保留字,class,new,static等,用的时候再记;
四、常量与变量
常量:不可更改的量,用final修饰
变量:代表“存储空间”,给变量赋值,即在对应的存储空间放置一个值
声明:
<类型> <变量名> ;(int x;)
要素:
变量类型,变量名,作用域()
①变量类型:
分为基本数据类型和引用类型,决定了该变量存储单元大小
基本数据类型:
整数:有符号,以二进制补码表示 | 浮点数:符合IEEE 754标准 | 其他 |
---|---|---|
byte 8位 short 16位 int 32位 long 64位 | float 单精度32位 double 双精度64位 | Boolean 布尔类型 true/false(不能用1/0代替) char 16位Unicode字符 |
(自动类型转换,容量小→容量大,否则可以强制转换:(类型)变量)
引用类型
(类、接口、数组),默认值为null.
②变量名
可自行定义,但须是合法标识符
③作用域
局部变量:方法或语句块内部定义的变量,生命周期从声明位置开始到方法或语句块执行完毕为止;须先声明后赋值
成员变量(实例变量):方法外部,类内部定义的变量。生命周期伴随该对象始终
静态变量(类变量 static):生命周期伴随类始终,从类的加载到卸载
五、运算符(优先级从上到下)
- 括号()
-
逻辑运算符 位运算符 算术运算符 关系运算符 其他 !非!true=false
~按位取反~0=1
++自增1,--自减1
*乘,/除,%取余
+加,-减
<<左移,>>右移,>>>无符号右移
<小于,<=小于等于,>大于,>=大于等于
instanceof判断类/接口的类型,返回true/false
==等于,!=不等于
&与,全真为真,但两边都会运算
^按位异或,不同为真
|或,全假为假,但两边都会运算
|按位或
&&与,全真为真,左边为假时右边不计算
||或,全假为假,左边为真时右边不计算
?:三目运算符,判断?结果(真):结果(假)
赋值运算符,=,+=,-=,*=,/=,%=,&=,
|=,
^=,~=,<<=,>>=,>>>=
转义字符
转义符 | 含义 |
---|---|
\b | 退格 |
\n | 换行 |
\r | 回车 |
\t | 制表符 |
\" | 双引号 |
\' | 单引号 |
\\ | 反斜杠 |
六、控制语句
1.选择结构
①if
- 单选择结构:
if(条件){
执行语句;
}
- 双选择结构
if(条件){
执行语句;
}else{
执行语句
}
- 多选择结构
if(条件){
执行语句;
}else if(条件){
执行语句
}else {
执行语句
}
②switch多选择结构
switch (表达式){
case 值/符号:(如果与表达式值相等则执行)执行语句;
case 值/符号:(如果与表达式值相等则执行)执行语句;
.....
default:
(不存在上述值/符号时执行)执行语句;
}
2.循环结构
①while先判断后执行
while(布尔表达式){
循环体
}如果布尔表达式为真,则一直执行循环体
②do...while先执行后判断
do{
循环体
}while(布尔表达式);
③for
for(初始化表达式;布尔表达式;迭代因子){ (例如int i=1;i<3;i++)
循环体
}
三个表达式都可以没有,但分号一定在,可以若只有布尔表达式,则相当于while
3.break和continue
break强行退出一个循环(注:if语句不是循环),不执行剩下的语句
continue退出一次循环,继续执行下次循环
4.goto
goto的随意跳转,容易使结构混乱;
属于Java的一个保留字,但并未给予有关Java的goto语句,未正式使用;
但可以使用带标签的break和continue来跳转
- 标签名(自定义):代码;
- 当continue:标签名;时便会跳转到上述代码中
七、方法
类似于函数
1.声明格式
[修饰符] 返回值类型 方法名(形式参数){
Java语句;
return 值;(无返回值,返回值类型写void,也可作为结束方法运行的一种)
}
2.调用:
创建一个属于该方法所在类的对象
类名 对象名=new 类名();
对象名.方法名(实参);
形式参数,用于方法声明时接收外界值
实参:调用时所传给方法的数据(传递原则:传递的都是数据的副本即copy值)
Java中方法的参数都是值传递
3.方法的重载(overload)
不同的方法,但名称相同
不同在于:形参类型/个数/顺序不同
八、递归与迭代
递归结构包括:
定义递归头:即递归结束条件;
递归体:什么时候调用自身方法
示例:求阶乘n!
public class HelloWorld {
public static void main(String[] args) {
long d1 = System.currentTimeMillis();//返回当前时刻
System.out.printf("%d阶乘的结果为%s\n",10,factorial(10));
long d2 = System.currentTimeMillis();
System.out.printf("递归费时%s\n",d2-d1);
}
//求阶乘的方法
static long factorial(int n) {
if (n == 1){
return 1;
}else {
return n * factorial(n - 1);
}
}
}
缺点:递归调用时会占用大量系统堆栈,内存耗用较多,比循环慢
注:任何可以用递归解决的都可以使用迭代解决,若不强调效率可以采用递归
九、面向过程和面向对象
面向过程和面向对象都是对软件分析、设计和开发的一种思想,它指导着人们以不同的方式去分析、设计和开发软件。
面向过程思想思考问题时,我们首先思考“怎么按步骤实现?”并将步骤对应成方法,一步一步,最终完成。这个适合简单任务,不需要过多协作的任务。
面向对象适合比较复杂的问题,需要多方协作,思考“任务对象有哪些构造“,并且一一实现其组成部件。
1、都是解决问题的思维方式,都是代码组织的方式。
2、解决简单问题可以使用面向过程
3、解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。
对象
对象(Object,instance实例)和类
类class可以看成对象的模板,多个对象的相同特征抽象可以得到一个类,即该类对象的模板
//示例:新建Students类并调用
public class Student {
int id; //学号属性
String name; //名字
int age; //年龄
// 光有属性没有方法类似与C语言的结构体
//方法:表现行为特征
void study(){
System.out.println("Student study");
}
void play(){
System.out.println("Student play");
}
//main程序执行入口,放哪个类都行,但必须要有
public static void main(String[] args) {
Student s = new Student();//创建类的对象
s.study();//调用方法
}
}
public class Student {
int id; //学号属性
String name; //名字
int age; //年龄
Computer comp;
// 光有属性没有方法类似与C语言的结构体
//方法:表现行为特征
void study(){
System.out.println("我学习使用"+comp.brand);
}
void play(){
System.out.println("我玩游戏使用"+comp.brand);
}
//main程序执行入口,放哪个类都行,但必须要有
public static void main(String[] args) {
Student stu = new Student();//创建一个Student对象
stu.id=1001;//调用属性并定义
stu.name="张三";
stu.age=18;
Computer c1 = new Computer();//创建一个Computer对象
c1.brand="荣耀";//给该对象命名
stu.comp=c1;//stu对象使用的电脑是c1
stu.study();//调用方法
stu.play();
}
}
class Computer{
String brand;
}
//栈、堆、方法区也参考这个代码
对象创建的过程和this的本质
创建一个对象分为如下四步
- 1.分配对象空间,并将对象成员变量初始化为0或空
- 2.执行属性值的显示初始化
- 3.执行构造方法
目录
- 4.返回对象的地址给相关的变量
this的本质就是“创建好的对象的地址”!由于在构造方法调用前,对象已经创建。因此,在构造方法中也可以使用this代表:“当前对象”
this最常的用法:
1.在程序中产生二义性之处,应使用this来指明当前对象;普通方法中,this总是指向调用该方法的对象。构造方法中,this总是指向正要初始化的对象。
2.使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。
3. this不能用于static方法中。
//this代表“当前对象”的示例
public class HelloWorld {
int a,b,c;//成员变量
HelloWorld(int a,int b){
// a=a;报错,第一个a指本方法里的a
this.b=b;//给当前对象(中成员变量b)赋值本方法的b所指值
}
HelloWorld(int a,int b,int c){
this(a,b);//构造器的调用即HelloWorld(int a,int b),且必须位于第一句
this.c=c;
}
}
十、内存分析(栈、堆、方法区)
Java虚拟机的内存可以分为三个区域:栈stack、堆heap、方法区method area
栈stack
- 1.栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
- 2.JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
- 3.栈属于线程私有,不能实现线程间的共享!
- 4.栈的存储特性是“先进后出,后进先出’
- 5.栈是由系统自动分配,速度快!栈是一个连续的内存空间!
堆heap
- 1.堆用于存储创建好的对象和数组(数组也是对象)
- 2.JVM只有一个堆,被所有线程共享
- 3.堆是一个不连续的内存空间,分配灵活,速度慢!
方法区method area(又叫静态区)
- 1.JVM只有一个方法区,被所有线程共享!
- 2.方法区实际也是堆,只是用于存储类、常量相关的信息!
- 3.用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
代码在上面
十一、构造器/构造方法(constructor)
用于对象的初始化
- 1.通过new关键字调用!!
- 2.构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用return返回某个值。
- 3.如果我们没有定义构造器,则编译器会自动定义一个无参的构造函数。如果已定义则编译器不会自动添加!
- 4.构造器的方法名必须和类名一致!
构造方法的重载跟方法的重载类似
十二、垃圾回收机制(Garbage Collection)
Java引入了垃圾回收机制。方便内存管理,大大的提高了开发效率。
内存管理
Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。
对象空间的分配:使用new关键字创建对象即可
对象空间的释放:将对象赋值null即可。垃圾回收器将负责回收所有”不可达”对象的内存空间。
垃圾回收相关算法
1.引用计数法
堆中每个对象都有一个引用计数。被引用一次,计数加1.被引用变量值变为nul,则计数减1,直到计数为0,则表示变成无用对象。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。
//循环引用示例
public class student {
String name;
Student friend;
public static void main(string[] args) {
Student s1 = new student();
Student s2 = new student();
s1.friend = s2;
s2.friend = s1;
s1 = nu11;
s2 = nu11;
}
}//s1和s2互相引用,导致其引用计数不为零,无法进行识别
2.引用可达法(根搜索算法)
程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。
通用分代垃圾回收:
不同的对象的生命期是不一样的。因此,不同生命周期的对象可以采取不同的回收算法,以便提高回收效率。我们将对象分为三种状态:年轻代、年老代、持久代。JVM将堆内存划分为 Eden、Survivor和Tenured/Old 空间。
1.年轻代
所有新生成的对象首先都是放在Eden区。 年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC,每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法频繁的操作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域。
2.年老代
在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。年老代对象越来越多,我们就需要启动Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域。
3.持久代
用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响。
.Minor Gc:
用于清理年轻代区域。Eden区满了就会触发一次MinorGC。清理无用对象,将有用对象复制到“Survivor1”“Survivor2”区中(这两个区,大小空间也相同,同一时刻Survivorl和Survivor2只有一个在用,一个为空)
·Major GC :
用于清理老年代区域。
·Full GC :
用于清理年轻代、年老代区域。成本较高,会对系统性能产生影响。
垃圾回收过程
1、新创建的对象,绝大多数都会存储在Eden中
2、当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区
3、当Eden区再次满了,会将S1中的不能清空的对象存到另外一个Survivor中,如S2同时将Eden区中的不能清空的对象,也复制到S1中,保证Eden和S1,均被清空
4、重复多次(默认15次)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)区中
5、当Old区满了,则会触发一个一次完整地垃圾回收(FuGC),之前新生代的垃圾回收称为(minorGC)
在对JM调优的过程中,很大一部分工作就是对于Ful GC的调节。有如下原因可能导致Full GC
1.年老代(Tenured)被写满
2.持久代(Perm)被写满
3.System,gc()被显式调用(程序建议GC启动,不是调用GC)4.上一次GC之后Heap的各域分配策略动态变化
十三、static关键字
修饰的变量/方法为静态变量/方法
在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。
static修饰的成员变量和方法,从属于类。
普通变量和方法从属于对象的。
//示例
public class User2 {
int id; // id
String name; //账户名
String pwd; //密码
static String company = "AAA"; //
public User2(int id, String name) {
this.id = id;
this.name = name;
}
public void login() {
System.out.println("登录:" + name);
}
public static void printCompany() {
// login();//调用非静态成员,编译就会报错
System.out.println(company);
}
public static void main(String[] args) {
User2 u = new User2(101, "高小七");
User2.printCompany();
User2.company = "北京阿里爷爷";
User2.printCompany();
}
}
十四、静态初始化块
构造方法用于对象的初始化,
静态初始化块,用于类的初始化操作,在静态初始化块中不能直接访问非static成员
静态初始化块执行顺序:
- 1.上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到类的静态初始化块为止上。
- 2.构造方法执行顺序和上面顺序一样
十五、包
包机制是Java中管理类的重要手段。开发中,我们会遇到大量同名的类,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理。包对于类,相当于文件夹对于文件的作用。
我们通过package实现对类的管理
- 1.包通常是类的第一句非注释性语句。
- 2.包名:域名倒着写即可,再加上模块名,便于内部管理类。
- 3.写项目时都要加包,不要使用默认包。
//导入包
import java.util.*//全导入
import java.sql.Date//选择性导入Date
//package的命名举例
Com.sun.test;
Com.oracle.test;
cn.sxt.gao.test;
cn.sxt.gao.view;
cn.sxt.gao.view.model;
//package的使用
package cn.sxt;
public class Test{
public static void main(string[] args){
System.out.println("helloworld");
}
}
JDK中的主要包 | |
---|---|
Java中的常用包 | 说明 |
java.lang | 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。 |
java.awt | 包会了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 |
java.net | 包会执行与网络相关的操作的类 |
java.io | 包会能提供多种输入/输出功能的类。 |
java.util | 包含一些卖用工具类,如定义系统特性、使用与日期目历相关的函数 |
十六、继承、封装、多态
1.继承(extends)
子类继承父类,子类可以使用父类的属性和方法,如Person为父类,Student为子类继承extend父类Person,那么Person类定义的名字、身高、学习等属性/方法,子类可以当作自己定义的属性方法来使用
父类也称作超类、基类、派生类等。
Java中类只有单继承,接口有多继承。
子类继承父类,可以得到父类的全部属性和方法(除了父类的构造方法),但不见得可以直接访问(比
如,父类私有的private属性和方法)。
如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
2.方法发重写override
在继承里,父类的方法不满足子类使用需求时,可以让子类重写父类的方法,用自身行为替换父类的行为;方法的重写时实现多态的必要条件
方法重写要求
- 方法名、形参列表相同。
- 返回值类型和声明异常类型,子类小于等于父类。
- 访问权限,子类大于等于父类。
3.Object类
是所有Java类的根基类,也就意味着所有的Javà对象都拥有Object类的属性和方法。
打印(print)一个对象实际上是调用了Object的toString()方法
(按住Ctrl键点击类/方法可以跳转至定义其的页面)
toString方法也可以进行重写
4.“==”和equals 方法
代表比较双方是否相同。如果是基本类型则表示值相等,如果是引用类型则表示地址相等即是同一个对象。
Object的 equals 方法默认就是比较两个对象的hashcode
是同一个对象的引用时返回 true/false
Object类中定义有:public boolean equals(Objectobj)方法,提供定义“对象内容相等”的逻辑。
5.super关键字
super是直接父类对象的引用。可以通过super来访问父类中被子类覆盖的方法或属性。
package text;
public class TestSuper01 {
public static void main(String[] args) {
new ChildClass().f();
}
}
class FatherClass {
public int value;
public void f() {
value = 100;
System.out.println("FatherClass.value=" + value);
}
}
class ChildClass extends FatherClass {
public int value;
public void f() {
super.f();//调用父类对象的普通方法
value = 200;
System.out.println("ChildClass.value="+value);
System.out.println(value);
System.out.println(super.value); //调用父类对象的成员变量
}
}
6.封装
封装就是把对象的属性和操作结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
提高代码的安全性和复用性。
“高内聚”:封装细节,便于修改内部代码,提高可维护性。
“低耦合”:简化外部调用,便于调用者使用,便于扩展和协作。
用访问控制符实现封装
访问控制符:private、default、protected、public
- 1. private 表示私有,只有自己类能访问
- 2.default表示没有修饰符修饰,只有同一个包的类能访问
- 3.protected表示可以被同一个包的类以及其他包中的子类访问
- 4.public表示可以被该项目的所有包中的所有类访问
7.类的属性的处理:
一般使用private访问权限。
提供相应的get/set方法来访问相关属性,这些方法通常是public修饰的,以提供对属性的赋值与读取操作(注意:boolean变量的get方法是is开头!
快捷方法:右键选择souce→create
一些只用于本类的辅助性方法可以用private修饰,希望其他类调用的方法用public修饰
8.多态(polymorphism)
多态指的是同一个方法调用,由于对象不同可能会有不同的行为。现实生活中,同一个方法,具体实现会完全不同。
- 1.多态是方法的多态,不是属性的多态(多态与属性无关)。
- 2.多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
- 3.父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
9.对象转型(casting)
父类引用指向子类对象,这个过程为向上转型,属于自动类型转换。向上转型后的父类引用变是只能调用它编译类型的方法,不能调用它运行时类型的方法。这时,我们就需要进行类型的强制转换,我们称之为向下转型
10.final关键字
1.修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
final int MAX_SPEED =120;
2.修饰方法:该方法不可被子类重写。但是可以被重载!
final void study(){}
3.修饰类: 修饰的类不能被继承。比如:Math、String等。
final class A{}
十七、数组
数组是相同类型数据的有序集合。
- 1.长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
- 2.其元素必须是相同类型
- 3.数组类型可以是任何数据类型,包括基本类型和引用类型。
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组的初始化方式总共有三种:静态初始化、动态初始化、默认初始化来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值
public class test01 {
public static void main(String[] args) {
//两种数组声明方式
int[] arr1;//Type[] arr_name;推荐使用
int arr2[];//Type arr_name[];
//注:
//1.声明的时候并没有实例化任何对象,只有在实例化数组对象时,JVM才分配空间,这时才与长度有关。
//2.声明一个数组的时候并没有数组真正被创建
//3.构造一个数组,必须指定长度。
int[] arr3 = new int[10];//构建数组,分配空间
arr1 = new int[10];
//for循环数组赋值和打印
for (int i = 0; i < 10; i++) {
arr3[i] = i;
}
for (int i = 0; i < arr3.length; i++) {//arr3.length返回arr3数组长度
System.out.print(arr3[i] + " ");
}
//増强for循环for-each是JDK1.5新增加的功能,
// 专门用于读取数组或集合中所有的元素,即对数组进行遍历。
for (int m: arr3) {
System.out.print(m + " ");
}
User[] arr4 = new User[3];
arr4[0] = new User("张三",12);
arr4[1] = new User("李四",13);
arr4[2] = new User("王五",14);
// 存放的是对应的地址
for (int i = 0; i < arr4.length; i++) {
System.out.print(arr4[i].getName() + " ");
}
}
}
class User{
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
//快捷生成get/set:右键选择Generate
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;
}
}
package textarrays;
public class test02 {
public static void main(String[] args) {
//静志初始化
int[] a ={2,4,65};
User[] b ={
new User("高淇",1001),
new User("张三",1002),
new User("李四",1003)
};
//默认初始化
int[] c=new int[3]; //默认给数组的元素进行赋值。赋值的规则和成员变量默认赋值规则一致。
//动态初始化
int[] a1 = new int[2];//动态初始化数组,先分配空间;
a1[0]=1;//给数组元素赋值;
a1[1]=2;//给数组元素赋值;
}
}
标签:Java,String,对象,代码,idea,System,int,方法,public
From: https://blog.csdn.net/m0_75262878/article/details/144113906