关于本周Java的学习情况,做如下小结,主要是对个人在学习问题中遇到的部分疑难的总结,一些与c++相通的部分会做删减,希望能用于查漏补缺.
目录
1关于Java的安装及使用环节
jdk的安装
这里推荐安装的是java8,日常的使用是足够的,且兼容性要更好一些
其他环境变量的配置等就不多赘述,网络上有详尽的教程.
另附个人遇到的小问题
此类情况可能由于系统安全性过高导致,可用管理员权限运行来解决
2数据类型和运算符
主要的关键字和保留字一览
关键字不建议刻意去记!随着学习的深入,自然就会非常熟悉了
下面是关于java数据类型的分类(暂时还不会做思维导图,先用手写的代替)
算数运算符
逻辑运算符
位运算符
字符串连接符
这四类与c++中差别不大,用法几乎相同。
自动类型转换
易出现的问题
public class Hello {
public static void main(String[] args) {
int money=100000000;//10亿
int year=20;
int total=money*year;//money*year为int型,数据会溢出
long total1=money*year;//total变为long但money*year为int型,数据会溢出
}
数据易产生溢出的问题,在条件允许时,可通过直接使用 long类型来避免溢出。
3控制语句
if-else 选择结构
for循环
switch循环
while循环
这些与c++大致相同,不多赘述
break和cotinue的使用此处在作补充
break 终止整个循环
cotinue 终止此次循环
带标签的break与conitue
Java唯一用到标签的地方是在循环语句之前,而其作用便是在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,在随同标签使用时,它们就会中断到存在标签的地方。
方法
完成特定功能的代码片段,类似于c中的函数
访问修饰符 返回值类型 方法名(参数列表){方法体}
ps:无返回值时可用void。
另一个比较重要的点便是方法的重载和递归结构
定义: 方法的重载是指一个类中可以定义多个方法名相同,但参数不同的方法。
重载的条件:形参类型、形参个数、形参顺序
以下几种情况不构成方法的重载
1.返回值不同
int a(String str){}与 void a(String str){}
2.形参的名称不同
int a(String str){}与int a(String s){}
递归结构
包含两个结构
递归头 何时不调用自身方法
递归体 何时调用自身方法
ps:递归书写程序结构简单,但运行慢,效率低,不建议使用。
4Java面向对象
此部分为本周学习的重难点所在,需重点描述。
关于此处的理解,建议去看 面向对象的内存分析详解
关于我的理解
Java虚拟机将内存分为三个区域,栈、堆、方法区。
此图为我找到的较为形象的Java内存分析的图片,
栈的特点:
1.栈属于线程私有,并不能实现线程间共享
2.存储特点为”先进后出,后进先出“(类似于枪的弹匣)
3.是一片连续的内存空间
堆的特点:
存放的是类的对象和数组等
例如
int app =99;
Person app = new Person();
此处可引出关于堆内存中内存的释放,即垃圾回收机制。
以下两种方法
1. 引用计数法
2. 引用可达法(根搜索算法)
第二种方法为主流方法
分代垃圾回收机制的主要作用原理是将不同周期的对象分为不同的状态,采取不同的方法来使用,其中JVM将堆内存划分为 Eden、Survivor 和 Tenured/Old 空间
此图为分代垃圾回收的主要运行原理和流程。
简单的讲就是先将新创建的对象存储在Eden区中,存满后触发gc清理并复制到s1中,再次满后将是中的复制至分中并清空,同时将Eden区中的不能清空的对象,也复制到s1中,重复15此后进入老年代中,当old区满后便会出发完整的gc来清理。
构造方法
定义
[修饰符列表] 构造方法名(形式参数列表){
构造方法体;
通常在构造方法体当中给属性赋值,完成属性的初始化。
}
ps:1.修饰符列表基本就是写public
2.构造方法名前禁止加void,加上后表示普通方法。
3.构造方法名称与类名要保持一致
4.定义有参构造器后,系统不会再自动生成无参构造器,此时如需调用,要自己写上
调用对象时
new 方法名(参数列表);
public class User {
int id; // id
String name; // 账户名
String pwd; // 密码
public User() {
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public static void main(String[] args) {
User u1 = new User();
User u2 = new User(101, "张三");
User u3 = new User(100, "李四", "123456");
}
}
上述代码为构造方法的重载代码。
此处可引出一个关键的知识点
this的使用
public class User {
int id;
public User() {
}
public User(int id, String name) {
this.id = id; //this用于区分局部变量id和成员变量id
}
}
同时this也可用于重载构造中。
其他的this的三点用法:
1. 在程序中产生二义性之处,应使用this来指明当前对象;普通方法中,this总是指向调用该方法的对象。构造方法中,this总是指向正要初始化的对象
2. 使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句
3. this不能用于static方法中
对象创建的过程
new来创建
Student student = new Student();
最简单的方式了
具体过程如图所示
ps:构造器中调用其他构造器要使用this,且要位于第一句。
public class Person {
private String name;
//构造器一
public Person() {
}
//构造器二
public Person(String name) {
this(); //调用构造器一
this.name = name;
}
}
static关键字
用static修饰的成员变量和方法,从属于类
普通的成员变量和方法,从属于方法
public class Code {
public static void print(Object o){
System.out.println(o); //调用了静态方法
}
public static void main(String[] args) {
Code.print("java小记"); //调用了静态方法
}
}
上述例子可看出static修饰的方法成为类的方法,此时通过 类名.方法名调用就很简单了。
静态初始化块
需要注意的是 在其中不可以直接访问static成员
以及其关于继承的一个知识点:上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。(后文讲到继承在详细介绍).
参数传递机制
Java中,所有参数的传递均为值传递。
基本数据类型 传递的是值的副本
引用数据类型 传递的是值的地址
因此通过改变副本指向地址对象的值,就能使原参数指向对象的值发生改变 。
包机制
其作用相当于文件夹对于文件的作用
package的用法
1.通常是类的第一句非注释性语句
2.命名规则:域名倒过来写
ps: 举例:com.app与com.app3.wuhu之间并非包含关系。
静态导入
package cn.app; import static java.lang.Math.*;//导入Math类的所有静态属性 import static java.lang.Math.PI;//导入Math类的PI属性 public class Test2{ public static void main(String [] args){ System.out.println(PI); System.out.println(random()); } }
以上为代码举例,内容不难,不过多赘述。
面向对象的三大特征
封装 继承 多态
继承
定义:继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
class 子类 extends 父类 {}
下面通过继承的一段代码来演示继承的运行原理
package com.jic.java1;
class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
}
class Student extends Person { // Student类继承了Person类
}
public class TestDemo {
public static void main(String args[]) {
Student stu = new Student(); // 实例化的是子类
stu.setName("java小记"); // Person类定义
stu.setAge(20); // Person类定义
}
}
不难看出,子类中的所有操作均为父类中的,也就是说,继承可以在子类不扩充父类的情况下,维持父类的操作 。
需要注意的是:
父类中的私有操作只能通过隐式继承来完成,即间接继承 通过public set/get方法进行获取和赋值。
另外如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object
方法的重写
要点:1.方法名,形参列表相同
2.返回值类型与声明异常类型,子类小于等于父类
3.访问权限,子类大于等于父类
public class TestOverride {
public static void main(String[] args) {
Vehicle v1 = new Vehicle();
Vehicle v2 = new Horse();
v1.run();
v2.run();
v2.stop();
}
}
class Vehicle {
public void run() {
System.out.println("111");
}
public void stop() {
System.out.println("222");
}
}
class Horse extends Vehicle {
public void run() { // 重写父类方法
System.out.println("000");
}
}
}
上述内容即为方法的重写
ps:object类为所有java类的基类
其后有一个重点,就是关于super 父类对象引用的部分
其作用为 访问父类中被子类覆盖掉的方法或属性 (要注意的是,此处与前文提到的一点的有联系,即不可访问父类中的私有对象)
public class A {
private String nameA="A";
public void getName() {
System.out.println("父类"+nameA);
}
public static void main(String[] args) {
}
}
public class B extends A{
private String nameB="B";
public void getName() {
System.out.println("子类"+nameB);
super.getName();
}
public static void main(String[] args) {
B b=new B();
b.getName();
}
}
还需注意的是
需要在首行写 super();
(当然不写也可以,编译器会默认加上)
封装
访问权限修饰符
修饰符 | 同类 | 同包 | 子类 | 所有类 |
---|---|---|---|---|
private | * | |||
default | * | * | ||
protected | * | * | * | |
public | * | * | * | * |
使用要点:
1.一般情况使用private访问权限
2.注意使用set get 来访问相关属性
set的使用
public void setName(String name){
this.name=name;
}
P4.setName(14);
get的使用
public void getName(){
return this.name;
}
P4.getName(14);
另需注意,bool类型的get方法,实际写起来为is方法。
多态
定义:同一个方法调用,由于对象不同,而具有不同的行为。
必要条件:
1.继承
2.方法重写
3.父类引用指向子类对象(重点)
class Animal {
public void shout() {
System.out.println("叫了一声!");
}
}
class Dog extends Animal {
public void shout() {
System.out.println("旺旺旺!");
}
public void seeDoor() {
System.out.println("看门中....");
}
}
}
public class TestPolym {
public static void main(String[] args) {
Animal a = new Dog();
animalCry(a); //a为编译类型,Dog对象才是运行时类型。
}
// 使用多态,只需要让增加的这个类继承Animal类就可以了。
static void animalCry(Animal a) {
a.shout();
}
/* 如果没有多态,我们这里需要写很多重载的方法。
static void animalCry(Dog d) {
d.shout();
}
}*/
}
容易看出,如没有多态的使用,就要写多次的重载函数,十分麻烦。
因此需灵活运用多态的灵活性,
此外父类引用指向子类对象属于向上类型转换
与此相对还有向下类型转换,即强制类型转换
举例说明
//Animal为Dog的父类
Animal d=new Dog();
//自动向上转换
Dog d2=(Dog)d;
//自动向下转换
final关键字
作用:
1.修饰变量,赋了初值后不可重新赋值
final int MAX_javaone = 10;
2.修饰方法,不可被重写,可被重载
final void learn(){}
3.修饰类,不可被继承
final class App {}
5数组
定义:
相同类型数据的有序集合,其中的每个元素均可通过下标来访问。
特点:
1.长度确定
2.语速必须为相同类型
3.数组类型可以为任何数据类型
声明方式
type[] arr_name;
int[] arr01;
ps:声明的时候并未实例化对象,即数组此时并未创建
构造数组时并未指明其长度
数组的初始化
1.静态初始化
int[] a = { 1, 2, 3 }; // 静态初始化基本类型数组;
Man[] mans = { new Man(1, 1), new Man(2, 2) };// 静态初始化引用类型数组;
2.动态初始化
int[] a1 = new int[2];//动态初始化数组,先分配空间;
a1[0]=1; //给数组元素赋值;
a1[1]=2; //给数组元素赋值;
数组的遍历
package 数组;
public class for遍历二维数组 {
public static void main(String[] args) {
//初始化数组元素的值
int Arr[][]={{5,7,15},{8,4,11},{3,6,13}};
/读取数组中元素的值
for (int i = 0; i < Arr.length; i++) {
for (int j = 0; j < Arr[i].length; j++) {
System.out.print(Arr[i][j]+" ");
}
}
}
}
另外foreach语句的遍历也是重要的方法,格式如下
for(type element: array)
{
System.out.println(element);
}
可用于读取,但不能用于修改,要注意此点。
本周学习小记完成,如有不足请指正。