java 语法机制
语法
八个基本变量
- 整型
byte,short,int,long - 浮点型
float,double - 布尔型
boolean - 字符型
char
引用类型/包装类型
- Integer
默认为null - string
功能上可以扩展,如方便互相转换
java还是以类为基础的,操作参数大都为object类型。
object更普适,允许null
如集合对象-List,数据库返回类型
同时包类型和基本类型是自动装箱,拆箱。
比较
"=="
基本数据时,比较的是值
引用类型时,比较的是内存地址。也就是同一个对象实例。
当String s1="xx",String s2="xx"时,
原来理解是引用类型,那应该地址不一样。
但这里说是常量是有专门一块内存区域。
分配时,当该区域已经有一样值时,返回该值地址。
所以比较结果一样
当String s1=new String("xx")时
就是在堆中分配地址给xx
结果就不一样
equals
这个是Objcet中的就有的方法,
各个类会重写。
引用类基本会重写成比较包含的值是否相同
如Integer,String
所以比较值要用equals。
转换
String->Integer
Integer.valueOf(String)
Integer->String
Integer.toString()
String.valueOf()
数组
type []
Arrays数组的工具类
Arrays.copyOfRange(int[] original, int from, int to)-复制
Arrays.toString()
Arrays.sort()--排序
集合
arrayList
set--数据不重复,一般用HashSet实现类
map--键值映射,这个Key也是不重复的,一般用HashMap实现类
map->set setA.addAll(hashMapA.values());
collection->Iterable(Iterator/迭代器)
是一个接口。集合都是实现这些接口的,
才能foreach都适用?
转化
array->List
(java.util.Arrays)List list = (java.util.Arrays.ArrayList)Arrays.asList(strArray);
这种转出来的List不是同一个基类,没有add(),remove()等方法。适用于读取。
ArrayList<String> list = new ArrayList<String>(Arrays.asList(strArray))
list->array
String[] array2 = testList.toArray(new String[testList.size()]);
这里应该也有那种从'符号分隔的字符串',数组,集合的那种上下转换链。
Stream
不知道咋形容,属于Lambda那一类的函数式?功能流水式,转换特别强。
不是以前那种文件流,网络流这种操作byte,和list类似都是对象实例。
粗略比较,一种是把东西拿过去,处理好后拿回来,一种是把操作方法拿过来执行。
惰性实时计算
Stream<BigInteger> naturals = createNaturalStream(); // 不计算
Stream<BigInteger> s2 = naturals.map(BigInteger::multiply); // 不计算
Stream<BigInteger> s3 = s2.limit(100); // 不计算
s3.forEach(System.out::println);
- map
传入一种转换方法,返回转换后的数据。 - filter
- reduce
- collect
数组转入
Arrays.stream()
转出list
collect(Collectors.toList())
转出Array
toArray()
String[] imei
List<NameValuePair> nameValuePairs = Arrays.stream(imei).map(item -> {
return new BasicNameValuePair("devices[]", item);
}).collect(Collectors.toList());
各种集合混合处理。。
从一个字符数组,转成stream,map成内容变为obj,再转成list。
函数
同名函数--方法重载
参数不能设置默认值。
可以再写一个同名函数中继下,里面写上调用的默认值。
private String ctrl(String imei, String type ) {
return ctrl(imei, type,"",null) ;
}
隐式函数
实例方法隐含地传入了一个this变量。
private double salary;
public void ariseSalary(double em){
double employ = this.salary * em;
this.salary += employ; //这部分操作的就是该类的实例域salary
}
这里this也可以不用些,js中都要写上this
参数中有三个点
表示可变长度的参数,类似于一个数组,不一样的是可以不传。。
类
Object是原类,所有类的基础。
如果没有指明extends父类。自动从Object继承。
一些概念在mix language记录
构造流程
有三块
- A-静态语句块
static{} - B-实例化代码块
直接{}里面写 - C-构造代码块
classname()
{
}
A只会执行一次,不论这个类被new 了几个实例。第一个执行。
B,C每次new都会执行。B会在C之前执行。
B,C执行时能调用类里面的方法,访问属性。
这个感觉和印象中其它语言不同,好像都是new好了以后才能调用方法。
可能由于已经在静态语句块那一环已经初始化过了吧。
全局参数这个用到static{}
泛类型 <>
https://blog.csdn.net/qq_27093465/article/details/73229016
很多类只是数据类型不同,规则是一样的,需要一个通用的类型作为参数。
有点像可以装不同头的扳手。
java本身类型都是从Object继承的,为啥不直接用object作为参数。
主要是object太通用了,输入输出都是不确定的,每个地方都需要强制转化,类型错了,编译时也没法判断。
ObjectPoint integerPoint = new ObjectPoint();
integerPoint.setX(new Integer(100));
Integer integerX=(Integer)integerPoint.getX();
泛型相对来说,定义的时候是通用类型,但实例化时是用确定的类型,这样在编译时输入输出都相当于确定类了。
泛型的代表字母
- E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>
- K,V — Key,Value,代表Map的键值对
- N — Number,数字
- T — Type,类型,如String,Integer等等
泛型可以用在类,接口,也可以用在函数
Class<T>
Class<?>
https://segmentfault.com/a/1190000039835272
- 实例化的时候
<T>实例化时要指定一个具体类型List<Number>
<?>不需要指定类型List<?> list = new ArrayList<Integer>();
list = new ArrayList<Number>();
也没看出有啥用处
- 定义的时候
代码里不涉及具体的类型。
Set<?> s1
for (Object o : s1)
引用时用基类Object表示就行。
那和定义Set<object> s1 有啥区别。可能Set<>既能填T,也能填?..
记得c++模板其实是底层每种类型都实现一遍。
- 不涉及具体的类型操作,只是一些规则流程性的代码,输出跟着输入类型就行。
public interface FuncCtrl<T> { T getCommand(String product); } public class MonitorFuncCtrl implements FuncCtrl<MonitorFunction.Command> Interface Command {} 输入输出都时接口
- 要处理具体类型的计算,类型集合先实现好,再根据输入类型来调用。
类型是无法穷举的,也是根据业务来定义可能的几种。TypeConverter regist(Integer.class, new IntegerConverter()); regist(int.class, new IntegerConverter()); ... 各种类型的处理方法加入converterMap IConverter<?> converter = converterMap.get(type);
- 大部分时候都是在系统已有的泛型类上再去操作,底层已经实现好各类型?
public <T> T get(Object key) {}
可能看不懂这个含义,把<T>忽略,就是返回一个T类型的值。
大概有几种形式。
- 类似ArrayList,实例化时参数传入类型
- 继承某个类时,传入类型。
泛型往往和反射相关联
这里的实现机制叫擦除,会把类型信息抹掉。
String userString = "[{\"userId\":\"111\",\"userName\":\"Tom\"},{\"userId\":\"222\",\"userName\":\"Jerry\"}]";
List<UserInfo> input = new ArrayList<>();
List<UserInfo> userInfoList = JSON.parseObject(userString, input.getClass());
这样只能知道是个List,里面是什么类型得不到的。
同时这个泛型是作为一个附加信息来传递的。
就要另外传递类型进去。
List<UserInfo> userInfoList = JSON.parseObject(userString, new TypeReference<List<UserInfo>>() {});
这里就比较迷惑,为了传递类型又弄了个泛型类,类似下面的机制获得。
那为啥input不直接getGenericSuperclass。
感觉只能是该类继承某个泛型父类时指定类型,属于类里面的信息。
直接实例化时传入类型是不行的。
ArrayList里面应该是能获取到类型的。
https://blog.csdn.net/lvxiangan/article/details/94836504
当一个类继承了某个泛型类,getSuperclass也是一样道理,
public class Person<T> {}
public class Student extends Person<Student>
Student st = new Student();
Class clazz = st.getClass();
Type type = clazz.getGenericSuperclass();--这个是所有类型的信息更全的接口了。
ParameterizedType p = (ParameterizedType)type;--泛型类型的接口
Class c = (Class) p.getActualTypeArguments()[0]--取参数数组的第一个。
匿名类
定义类的最终目的是创建一个类的实例,但是如果某个类的实例只是用一次,则可以将类的定义与类的实例化,放到与一起完成.
必须继承一个父类或者实现一个接口。
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
System.out.println("Salut " + name);
}
};
前面就和实例化一样的,后面直接跟了{},里面写类的定义。
原先的流程是要弄一个类名,再定义这样吧。
private void retrofitExecute() {
new Thread(new Runnable() {}).start();
}
进一步实例名称也没有了。
new Thread((Runnable)()->{})
idea显示时又给简化了变成这个箭头。实际代码是上面这样。
感觉java都是用类做载体,缺少更轻量的结构体,也没有函数回调传递。就算只是一个方法也得弄成类或者接口。写起来会很繁琐。
内部类
一个类定义在另一个类的内部,这个类就是Inner Class
然后这里有个叫匿名内部类的,感觉比较混乱,有说就是匿名类的别称。。
函数式/Lambda
虽然是一种底层独立的范式,但在这里和匿名类结合的很紧密。
有一大堆单方法的接口,用匿名类简化后,也还是繁琐。
用lamba又简化了很多。基本只要写最后实际的回调代码
然后lambda是后面引进的,并不是啥地方都能用。
首先着这个函数传进去是对应哪个接口函数的。
没有函数名,只能是一个单方法的接口,或者只有一个抽象方法的接口。
这个接口用注解@FunctionalInterface标记
里面内容也很多
这个比较综合,泛类型这些都会涉及。
主要的几种用法
输入 返回
Consumer<T>--消费型接口 T /
Supplier<T>--供给型接口 / T
Function<T,R>--处理返回型接口 T R
Prodicate<T>--断定型接口 T Bool.
这些都是预先定义在java.util.function,看着就是一些正常的接口
public interface Consumer<T>
里面其实也包含多个函数的,但除了一个要实现的函数,其它都是有default默认实现的。
编写函数式风格。
- 先要申明一个接口,这里已经有模板了。
- 申明函数时参数填上述接口 Fun(Function<Record,FuncResult> proc)
这里应该泛型参数应该是要实例化类型的,
stream.map这种不指定类型的,Function<? super T, ? extends R> 是用?通配符
函数里面调用resp=proc.apply(record) - 调用的时候就可以 Fun(record->{process,return FuncResult})
接口的实例化
Function<Integer, Integer> times2 = i -> i*2; 看着挺怪的。。
然后Function里还有一些其它函数。compose,andThen这些
这些可以用来嵌套加入处理逻辑。
https://blog.csdn.net/anLA_/article/details/78191494
大致就是用在集合类型。然后stream是原生就是lambda设计。
有种双冒号 (::)的写法,更是简洁到只剩下方法名了
https://blog.csdn.net/zhoufanyang_china/article/details/87798829
叫方法引用。
map(Integer::valueOf)
单继承/多接口
extends xxx
implements xxx,xxx,xxx
public Thread(Runnable targer)此构造方法接受Runnable的子类实例..
接口定义
public interface OnRefreshListener {
public void onRefresh();
}
接口实现
implements SwipeRefreshLayout.OnRefreshListener
重载接口函数
@Override
public void onRefresh() {
Log.d("Swipe", "onRefresh");
retrofitCallBack();
}
全局类
classA
staic classA instance
static ClassA getInstance()
{
if instance==null
{
instance=new classA
}
return instance
}
也有 synchronized (classA.class) {nstance=new classA}
这样获取到的都是同一个实例。
也有
class TableMapping
private static TableMapping me = new TableMapping();
public static TableMapping me() {
return me;
}
**级联调用**
类似Jquery这种可以流水式的一直配置下去
方法内部通过返回this,
Obj.setA().setB()....
**静态/static**
* 属性--是放在一个单独的静态控件里,不属于实例空间。可以直接访问。
所以也不是线程安全的。
* 方法--静态方法属于class不属于实例,无法访问this,实例属性。
* 类-只有内部类可以声明静态。
* 内部类--java一个文件只能是一个public类,有时候一个模块内部比较复杂,需要建几个类,但这些类不需要被其它模块用,建文件存放冗余。
* 静态内部--可能是作为辅助类,功能是比较独立的,而不是要通过外部类实例化后再去用。
lamp系统中用于内部的数据结构,
interface/接口
能两层结构
public interface LedFunction {
public interface Response {
xx
}}
能继承
public interface Command extends LedFunction.Command
可以import 类中的方法。。
import static com.hc.lamp.config.rabbitmq..RabbitPluginsend;
可以定义一个默认实现
default void eat(){
System.out.println("eat");
}
instanceof
判断obj是否为某个类的实例/是否是某个接口的实现
ThreadLocal
会需要一个静态的空间,但不同线程要区隔开。
private static final ThreadLocal<String> local = new ThreadLocal<>();
看着是一个静态的map集合,这样里面就能放各自线程的值。
结构体
有些属性直接public propertyA
有些属性是private ,然后用public set,get 方法读写
枚举值
限定了范围,名称和值一体。以前常用来比较的时候直接看出含义。==EnumA.MON
这里看着丰富一些。
说其实是一个枚举类,在类的机制上加入了自己的机制。
编译出来后大概是
public final class Color extends Enum { // 继承自Enum,标记为final class
// 每个实例均为全局唯一:
public static final Color RED = new Color();
public static final Color GREEN = new Color();
public static final Color BLUE = new Color();
// private构造方法,确保外部无法调用new操作符:
private Color() {}
}
每个枚举值都是一个实例。
有用类静态属性的,这是干啥?两者没啥关系,只是说把枚举值的序号再定义下。
class nameA{
static int propertya=1;
static int propertyb=2;
}
public enum typea{
propertya,
propertyb}
定义属性,方法。
这里拓展成像类一样,调用里面的函数。
变成类似字典类型的用法。
enum Product {
HUIDU("HUIDU"), XIXUN("XIXUN"), MOCK("MOCK"), HC("HC");
Product(String value) {
this.product = value;
}
private final String product;
public String getProduct() {
return product;
}
}
Product.HUIDU;
Product.HUIDU.getProduct();
Enum的一些方法
可以直接有==比较
name()--获得这个枚举值的字符名称
valueOf(String)--将字符名称转为枚举值
ordinal()--序数,从0开始
两个花括号
这还挺绕的。。。
两个花括号是拆开看的。
第一个花括号是生成匿名类,
第二个花括号是这个匿名类里面的构造流程中的实例化代码块。
new JSONObject() {{
put("userName", username);
put("password", password);
}}
这里put是JSONObject里面定义好的函数。
感觉用来初始化类里的一些数据。
异常处理
函数抛出异常
throw new HcException("没有节目信息");
如果调用者没有处理,那么控制台直接报错,程序退出。
反射
http://blog.csdn.net/lfsf802/article/details/7239652
getDeclaredConstructor 获取构造函数
http://hold-on.iteye.com/blog/1906731
InjectBean
字符串<-->调用
字符串-->类
clazz=Class.forName("xx.classname")
字符串-->方法
Method method=clazz.getMethod("methodname", String[].class);
method.invoke(clazz,argvalue)
这里遍历方法的时候,对于参数也要有个转换
Class<?>[] types = method.getParameterTypes();
object argvalue=convert(types[0], paraValue)
这里用了泛型。
熟悉这些要对java的原始类型比较熟悉,
class java.lang.String
interface java.util.Map
annotation/注解
注解是专门有个注解类的。public @interface ax。需要实现申明。
注解类有特殊的属性定义
@Target
ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.METHOD:能修饰方法
ElementType.FIELD:能修饰成员变量
......
@Retention
RetentionPolicy.SOURCE: 注解只在源代码中存在,编译成class之后,就没了。@Override
RetentionPolicy.CLASS: 注解在java文件编程成.class文件后,依然存在,但是运行起来后就没了。@Retention的默认值
RetentionPolicy.RUNTIME: 注解在运行起来之后依然存在,程序可以通过反射获取这些信息
@Inherited
@Documented
@Repeatable
被标记后用法
MyTable myTable= (MyTable) clazz.getAnnotation(MyTable.class)
myTable.name();
成为一个标记类。
一般会用的组合Retention-RUNTIME,@Target-TYPE/METHOD/FIELD
一般的用处
- 标记作用
申明@interface中没有属性定义。只用@interface的名字
用的时候m.getAnnotation(MyId.class)!=null来判断有无标记。 - 有参数控制
申明@interface中定义属性。
标记时@MyTable(name="hero_"),设置好值。
调用时标记类的用法。 - 类的自动注入
https://blog.csdn.net/qq_24871519/article/details/85066838
属性有两种情况- 属性是类,只需标注,
- 属性是接口,那就需要传入实现类。
大致流程
遍历属性 --getDeclaredFields。
判断是否有相关标记
对该属性值的设置。-declaredField.set(xx);
这里有几个关键点。
- 这个是在何时,何地执行的
类的创建肯定要被外部代理才能解析这些注解。
类的托管,这里就涉及到spring这些容器的实现机制了。 https://fzsens.github.io/spring/2018/09/02/spring-framework-03/
感觉是通过扫描包,然后可以把类加到容器里去。然后这个类的生命周期就由spring来管理。
然后这个类的调用也不是显式的,是被管线所调用。 - 注解类的动态创建。
反射啥的
这里就是AOP,IOC这些的应用,还是没转的过来弯。
以往的类就一个创建步骤,现在已经演变出了生命周期。
看着也就是省略了类的实例化过程。。
Thread
Thread/Runnable
简单用Runnable就行,Thread可能涉及方面多。
涉及--资源共享,继承的灵活性。。
和主线程的同步
https://www.jianshu.com/p/128476015902
CountDownLatch
主线程等子线程都完成后,再继续执行。完成的依据是一个计数器,计数量是线程的数量
主线程等待 --await()
子线程完成后减计数器-- countDown()
RemoteService
synchronized
同一时刻只有一个方法可以进入到临界区。
每一个对象都可以作为锁。
这里主要是锁的对象各式各样,锁对象,锁方法,锁类。看是否静态。
web请求处理
数据格式
- x-www-form-urlencoded
getParameter() - form-data
要用request.getInputStream()或request.getReader()
raw - request.getReader()
jfinal中包装成getRawData
一般都是Json格式,用JsonObj来转换
request.getParameter()、request.getInputStream()、request.getReader()这三种方法是有冲突的,因为流只能被读一次。
Map<String, String[]> paraMap = request.getParameterMap();
这里value是数组,是因为传入的参数中可能key值会有一样的。
如keya=v1&keya=v2 ,checkbox也是
单个key获取的话用String[] getParameterValues