java
#define java: \
I-----------------------------------------------------------------\
I-----------------------------------------------------------------\
I-----------------------------------------------------------------\
I /$$$$$ \
I |__ $$ \
I | $$ /$$$$$$ /$$ /$$ /$$$$$$ \
I | $$ |____ $$| $$ /$$/|____ $$ \
I /$$ | $$ /$$$$$$$ \ $$/$$/ /$$$$$$$ \
I | $$ | $$ /$$__ $$ \ $$$/ /$$__ $$ \
I | $$$$$$/| $$$$$$$ \ $/ | $$$$$$$ \
I \______/ \_______/ \_/ \_______/ \
I-----------------------------------------------------------------\
I-----------------------------------------------------------------\
I-----------------------------------------------------------------I
# if you work work hand enough, one day you can ascend to this level
http://durgasoft.com/
# official Java documentation
# do NOT attempt to blindly google java related questions,
# because 3th worlders operate engagement farms,
# many of which are focussed on spitting out
# programming content, especially regarding java
https://docs.oracle.com/en/java/javase/24/index.html
• automatic garbage collection (heap freeing)
• designed after C++
• radically (fully) object oriented
• all code runs on the java virtual machine
• multi-platform (with all its software)
• web browsers used to support it (with so-called applets)
• stereotypically only written by Indians
• has an incredible reflection system, to the point that every java binary
can be considered pseudo-open-source
• one of the most legitimate use case is in game development where (user) modding makes sense
• "application/x-java" owns the magic mime bytes "CAFEBABE"
○ Design principles
Simple
Object Oriented
Distributed
Robust
Secure
Architecture Neutral
Portable
Interpreted
High Performance
Multithreaded
Dynamic
"\
@egor | java rant incoming \
| i have a java program on my server that periodically needs to exec another program \
| back in the java 8 days the jdk devs replaced fork/exec with posix_spawn \
| which is generally a good idea, on systems where it exists, it's much more lightweight than doing a fork \
| this is especially important for java, which is memory hungry as fuck \
| however, posix_spawn isn't really feature-complete compared to fork/exec \
| so what do they do? they fucking posix_spawn a helper binary jspawnhelper, pipe information to it, and have it do the exec \
| keep in mind, on a certain little hobbyist unix-like operating system made by a certain finnish guy, posix_spawn is implemented in libc using \
| fork/exec \
| so there's literally no benefit \
| but they also did another stupid thing, they passed the pipe fds in argv[0] \
| this doesn't work well with things like qemu-user \
| so they made it go to argv[1] instead \
| this got backported java 17.0.10 \
| when I updated, my program started mysteriously failing \
| until I restarted it, of course \
| then in 17.0.11 they added another file descriptor to the argument, and that broke my shit again \
| the moral of the story is \
| 1) don't break inter-process API, even if it's internal, because people WILL run outdated binaries \
| 2) don't make the inter-process API so stupid that you'll need to break it in the future \
| 3) don't introduce unnecessary inter-process API in the first place (for fucks sake it's still fork/exec on linux, there's literally zero \
| benefit to all of this madness) \
| -- \
| another instance of jdk devs being retarded is the removal of version scripts in java 11 \
| the main purpose of version scripts is to implement symbol versioning \
| but they also can be used to control symbol visibility \
| basically like .def files for windows DLLs, where you can just specify a list of public symbols instead of using __declspec(dllexport) \
| gcc actually has an equivalent for dllexport, called __atatribute__((visibility("default"))) \
| *attribute \
| vast majority of project use neither version scripts nor the visibility attribute, because the default on unix systems is for all symbols to \
| be public (hooray namespace pollution) \
| anyway so the java devs decided to switch from using version scripts to those attributes \
| and they completely forgot the fact that symbol versioning also exists \
| this breaks the ABI \
| the dynamic linker will give you an undecipherable error message if you try to link to a versioned symbol, but there is only an unversioned \
| one in the .so \
| old versions of minecraft are affected. in particular, the ones with the lwjgl2 native lib, which links to the awt native interface \
| -- \
"
Programs: Programs:
JDK : "Java Development Kit"/"Java SDK"/"Java Software Development Kit"
jar <options> : create/manipulate jar-s; follows the footsteps of tar
javac <options> <file>+ : "JAVA Compiler"; translates java code to java byte code
java <options> <program> <arg>+ : java virtual machine; used to interpret(/JIT) java byte code;
the program name is enforced to not contain the extension
{
$ java HelloWorld.class
Error: Could not find or load main class HelloWorld.class
Caused by: java.lang.ClassNotFoundException: HelloWorld.class
$ java HelloWorld
Hello, World!
}
Eclipse : famous IDE; OK-ish
NetBeans : famous IDE; the current meta for Java
Maven : build system
mvn <lifecycle>
clean
build
install
Gradle : build system
SDKMAN! : package and environment manager for java
sdk <verb> <subject>
install <package>
CPP_COMPATEBLE_FEATURES: CPP_COMPATEBLE_FEATURES:
• see AT "/C++"
• commenting
• commas
• operator-s
• variable assignment
• casts
• for(); while(); do{}while() loops
• for-each loop
• method syntax
• static keyword
— close enough:
• the keyword const is replaced by final
Primitives: Primitives:
• ie. built in types
• passed by value
-----------------------
| Java Type | Size |
-----------------------
| byte | 1 byte |
| short | 2 bytes |
| int | 4 bytes |
| long | 8 bytes |
| float | 4 bytes |
| double | 8 bytes |
| char | 2 bytes |
| boolean | 1 bytes |
-----------------------
Char:
• UTF-16 (1-2 byte)
Projects: Projects:
• core java has its own characteristic folder structure
(see AT "/Organization/Project\ Structure/Core\ Java")
• many tools {maven} depend on very specific paths
Files: Files:
.java : java source code
.class : compiled java byte code
.jar : "Java ARchive"; compressed java project format
Classes: Classes:
<access> class <name> { <...> } : class declaration
• everything is a class
<access>
public : accessable from any class;
source files declaring a public class, must be named after it
/* this file HAS to be named 'MyClass.java' */
public class MyClass {}
Records: Records:
<access> record <name>(<arg>+) { <...> } : record declaration
• boilerplate reducing feature
• after thought
• immutable data storage classes
— records are equivalent to classes where:
• the <access> and <name> matches
• each arg is a final private member
• each member has a getter
• there is a constructor which takes all fields as arguments
— the following are defined:
• equals
• hashCode
• toString
• since they are immutable, records are totally useless
when dealing with JPA entities
public record MyRecord(String name, int score) {
public void function() { ; }
}
Nesting: Nesting:
• classes can be nested
• this allows for having multiple public classes in a single source file
• every pajeet that creates a tutorial not using them should be beheaded
• every instance is tied to an instance of the parent class by default
• the static keyword unties the nested class from its parent
{
public
class Parent {
class Child {
}
}
}
Packages: Packages:
• each package component has to be located in a directory named after the package
• packages can be located online
{
$ tree mypkg
mypkg/
└── MyPkg.java
$ cat mypkg/MyPkg.java
package mypkg;
public class Component {
public static void fun(){ }
}
}
import <package>.<component> : tells java to recognize <component> without its path
being specified;
ie. { mypkg.Component.fun() }
becomes { Component.fun() }
import <package>.* : import-s every component from <package>;
not recursive and cannot be made recursive
Exceptions: Exceptions:
{
try { <...>
} catch (<type> <name>) {
<...>
}
}
Specifiers:
• "throw clause"
• compile time enforced
• all calls to functions with exception specifiers must be wrapped in a throw - catch block
{
<function_head> throws <exception> <function_body>
}
Try_resource: Try_resource:
try(<declaration>) {
<...>
}
• the try-resouce block guarantees that the variables declared in the head
do not leak
• since every object is created on the heap AND there is no delete,
object lifetimes are purely managed by the garbage collector
— quote from Oracle:
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
try {
return br.readLine();
} finally {
br.close();
fr.close();
}
}
"However, this example might have a resource leak.\
A program has to do more than rely on the garbage collector (GC)\
to reclaim a resource's memory when it's finished with it.\
The program must also release the resoure back to the operating system,\
typically by calling the resource's close method.\
However, if a program fails to do this before the GC reclaims the resource,\
then the information needed to release the resource is lost.\
The resource, which is still considered by the operaing system to be in use,\
has leaked."
"In this example, if the readLine method throws an exception,\
and the statement br.close() in the finally block throws an exception,\
then the FileReader has leaked."
• due to this ''memory safe'' language leaking like a barrel,
oracle invented the try-resource block
Annotations: Annotations:
@<annotation>
{
@Retention(<policy>)
@Target(<target>)
<access> @interface <Name> {
<...>
}
}
Retention:
Retention.SOURCE - for static analisys
Retention.CLASS - for compiletime magic
Retention.RUNTIME - for runtime magic
Target:
ElementType
METHOD
FIELD
TYPE
Objects: Objects:
Builtin_methods:
Class getClass()
Method getDeclatedMethods
Type_Class:
Builtin_methods:
bool isAnnotationPresent(<annotation>.class)
Type_Method:
bool isAnnotationPresent(<annotation>.class)
setAccessible(bool) : casts accessibility; yes, it can cast away private-ness
invoke(object)
Serialization:
implements Serializable
• the process of converting an object to reconstrucable bytecode
• for an object to serializable, all fields must be serializable too
• during serialization, references are preserved
transistent <field> : <field> will not be serialized
POJO:
• "Plain Old Java Object"
• a self contained, simple as possible class
— objects which which comply with the following restrictions:
• does not extend classes
• does not implement interfaces
• does not use extern annotations (non-builtin)
Beans:
— objects which comply with the following restrictions:
• has a public, 0 argument constructor
• all fields are private
• has getters and setters for all fields
• serializable
Builtin_classes:
Math
sin
cos
tan
atan
atan2
exp
log
round
PI
E
System
out
print
println
exit
String
length
equals
equalsIgnoreCase
Core_library:
pass
?!:
final <declaration> : the subject of the declaration is const (read-only)
synchronized <function> : make <function> thread-safe
strictfp : madness.
Jakarta_EE:
JPA:
• ORM specification
interface interface JPARepository<T, ID>
findAll() : return T iteratable
findById(<ID>)
deleteById(<ID>)
save(<T>)
count()
@Entity : annotated to objects which are abstracted into the database as records
@Id : required for each @Entity; the primary key; spring manages its value
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonIgnore : hide this field when serializing to JSON
@Projection(name=<string>, types={<class>+}) : annotated to interfaces;
used to expose select fields of one or multiple classes after a query;
overrides other exposure policies {private, @JsonIgnore}
{
@Projection(name = "passwords", types = { User.class })
interface PasswordProjection {
String getPassword();
}
}
Logical_mapping:
ineterface JPARepository - DATABASE
@Entity - TABLE
@Id - PRIMARY KEY
@GeneratedValue - AUTOINCREMENT
Lombok:
• used for auto generating boilerplate code,
which interesting from a software philosophical perspective
Annotations:
class @Getter : auto generate a getter for all private methods
class @Setter : auto generate a setter for all private methods
class @NoArgsConstructor : auto generate an argumentless constructor
class @Builder
HyperSQL:
• java implementation of an SQL database
java_spring
#define java_spring::\ \
I------------------------------\
I ___ _ \
I / __|_ __ _ _(_)_ _ __ _ \
I \__ \ '_ \ '_| | ' \/ _` | \
I |___/ .__/_| |_|_||_\__, | \
I |_| |___/ \
I------------------------------I
• framework
Init:
https://spring.io/quickstart
https://start.spring.io/starter.tgz
• a directory local instance contains all dependencies
• there is a webui intended for generating new projects
• there is an API for creating new project under https://start.spring.io/starter.tgz
• there is a cli application to wrap the API
API:
name=<string>
dependencies=<style>
web
{
curl https://start.spring.io/starter.tgz -d dependencies=web -d name=simple | tar -xzvf -
}
cli:
spring <action>
init
encodepass
Building:
— supports the following build systems
gradle
maven
ant
gradle_targets:
bootRun
Dependencies:
spring-boot-starter-*
• spring serves a giant list of dependencies called starters
spring-boot-starter : core; auto config
File_structure:
webjars/ : webjars from this path are auto served
static/ : static content is served from here
public/ : static content is served from here
resource/ : static content is served from here
error/ : error pages are looked up from here;
the file name decides which page is loaded;
they have to be named after the HTTP response code;
'x' is a place holder for any digit
{ 5xx.ftlh : matches all 500 errors }
Dev_tools:
org.springframework.boot:spring-boot-devtools
• disables all caching
Classes:
SpringBootApplication : inject to the main application
— responsibilities
• logging
• running the test server
• processing configurations
methods:
static void run(class, string[]) : starts spring with the default configs
void run(string[]) : starts an instance of spring
fields:
<set|get><config>(<...>) : all environment options are available; see AT "../../Environment"
Environment:
• basically fancy configuration
• it has 15 layers of overriding and they dare to call in "sensible" in the docs
• properties part of the environment are audited by spring to
reflect their configurant values
• there are a bunch of builtin environment properties,
but new ones can be defined too by the developer
• configuration names use camelCase inside java and kebab-case outside of it
@Value("${<name>}") : marks the <name> property to be part of the environment
@ConfigurationProperties("<name>") : marks the <name> class to be part of the environment
— the following config files are autoloaded:
application.properties
application.yaml
application.yml
{
myApplication.setBannerMode(Banner.Mode.OFF);
spring:
main:
banner-mode: OFF
}
Bean:
• not to be confused with Java Bean, Spring Beans are a different concept
• any object that is managed by the spring IoC
Data:
• JPA is encouraged (see AT "/Java/JPA")
config:
spring.datasource.url
jdbc:<server>:
spring.datasource.username
spring.datasource.password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto : determines how to handle syncing to the database
none : do not reflect changes
update : sync and preserve
create : (re)create on start up; do not drop shutdown
create-drop : (re)create on start up; drop on shutdown
seeding:
• using a CommandLineRunner is a solid choice
sql_scripts:
— the following sql scripts are auto sourced on start up:
/src/main/resources/
schema.sql
data.sql
• Spring/JPA may mangle table names in unexpected ways;
to double check the correct naming, one could place the following
line into a sourced sql script and deduct from the create statements:
SCRIPT TO 'dump.sql';
config:
spring.jpa.defer-datasource-initialization=<bool> : whether to source sql scripts after JPA creates the database schema based on repositories
— the following databases are supported:
• H2 JdbcDataSource
• HikariCP
• Tomcat pooling Datasource
• Commons DBCP2
• Oracle UCP & OracleDataSource
• Spring Framework’s SimpleDriverDataSource
• PostgreSQL PGSimpleDataSource
• C3P0
Validation:
@Validated
@Size(min=..., max=...)
Logging:
• inherits the abstraction of log levels from unix like systems
class LoggerFactory
static Logger getLogger(<string>) : returns named logger;
the loggers name is only used by itself,
when printing information
class Logger
— the following methods all log with difference log levels
error(<string>)
warn(<string>)
info(<string>)
debug(<string>)
trace(<string>)
CommandLineRunner:
class CommandLineRunner
• allows for running code after spring has started up
— instances must be passed to the Application.run call:
{
@Bean
public
CommandLineRunner cmdlr(AnimalRepository repository) {
return (args) -> {
repository.save(new Animal("Bob", 3, 10));
};
}
SpringApplication.run(FarmApplication.class, args);
}
Templating:
— the following engines are supported:
FreeMarker
Groovy
Thymeleaf
Mustache
{
spring-boot-starter-groovy-templates
}
Starters:
Web:
spring-boot-starter-web
Annotations:
@RestController : any class with this annotation will be checked for mappings to bind
Mappings:
• functions can be marked as mappings
• mappings determine what a server path will return
@RequestMapping(<path>)
@GetMapping(<path>)
@PostMapping(<path>)
@PutMapping(<path>)
@DeleteMapping(<path>)
@PathVariable(<var>)
— a mapping could return one of the following:
— string:
• it is taken literally
• echod back to the user
— serializable:
{
MyBean
List<MyBean>
}
• a JSON will be created
• its returned as a JSON (not a string)
— ModelAndView:
• the ViewName property is used for template look ups;
( from "src/main/resources/templates/*" )
{
@GetMapping("/")
ModelAndView index(){
ModelAndView mav = new ModelAndView();
mav.setViewName("index");
return mav;
}
}
@Configuration(...)
@Component
@RequestBody
@ResponseBody
OAuth2:
• pulls in security
• as a side effect of security all pages will become private (auth only) by default
— setting up oauth2 is done through the environment;
using the config files is recommended { /src/main/resources/application.properties };
the following options are important:
spring.security.oauth2.client.registration.<provider>.client-id=<id>
spring.security.oauth2.client.registration.<provider>.client-secret=<secret>
• due to the nature of oauth, both the id and the secret is obtained from
the authentication provider. (usually through their website)
Supported_providers:
github
google
Security_filter_bean:
• a filter chain is basically a firewall
• it enforces response policies based on rules (logic)
• can allow, deny, ask for credentials, etc.
@Bean SecurityFilterChain <name>(HttpSecurity http) throws Exception { ... }
• override-s the default filtering chain
class HttpSecurity
authorizeHttpRequests(<delegate>(<auth>)) : ?!
fromLogin(withDefaults()) : enables on site, form based authentication
oauth2Login(withDefaults()) : enables oauth2 authentication
build() : wires the request into the mapping system
<auth>
• path can contain blobs
<filter>.<policy>()
<filter>
— filters are interpreted from top to bottom and are greedy
{
auth.requestMatchers("/secret").authenticated();
auth.requestMatchers("/*").permitAll();
auth.requestMatchers("/*").permitAll();
auth.requestMatchers("/secret").authenticated();
}
requestMatchers(<path>)
<policy>
authenticated()
permitAll()
{
@Bean
public
SecurityFilterChain myFilter(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests( auth -> {
auth.requestMatchers("/secret").authenticated();
auth.requestMatchers("/*").permitAll();
})
.oauth2Login(withDefaults())
.build()
;
}
}
Actuator:
• used for enabling useful production features
endpoints:
env
health
info
Gateway:
• basically a reverse proxy
• a server determining how to further dispatch requests
• could be used for load balancing
• promots horizontal scaling
— the root locator bean is primarly responsible for the gateway functionality:
{
@Bean
public
RouteLocator rtl(RouteLocatorBuilder b) {
return b.<...>.build();
}
}
class RouteLocatorBuilder
routes()
route(<string-id>, <Function<route, route>>)
class Route
path(<string>)
Batch:
pass
### Spring Gateway Hello World ###
1. Set up dependencies
— gateway is all we need:
spring-cloud-starter-gateway
— in case you missed it during initialization,
this is how it would look like under gradlew:
{
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
}
}
2. Run services
• netcat is going to be the easiest to set up
• we will create 2 instances continously running
$ nc -l -p 8081
$ nc -l -p 8082
• -p signals the port, make sure to make them distinct
4. Set up routing
— we will hate to add a route locator bean:
{
@Bean
public RouteLocator rl(RouteLocatorBuilder builder) {
return builder.routes().build();
}
}
• for convinience, might as well add it as a method of our (main) application
5. Add routes
• we can append route() calls to routes
• the first argument is a string id (it does not actually matter for our purposes)
• the second argument is a lambda configuring a route
• route calls can be chained
• we will add 2 routes, discriminated based on path
{
.route("netcat-1", r -> r.path("/cat1").uri("http://127.0.0.1:8081"))
.route("netcat-2", r -> r.path("/cat2").uri("http://127.0.0.1:8082"))
}
• we must reuse to port of our designated services here,
currently its those on which we are running netcat(s)
6. Compile and run
• we regularly invoke our application from the top directory of our project
$ gradlew bootRun
7. Validate
• any http connection would do
• using a browser is going to easiest (with curl we would have to acknowledge ssl)
{
127.0.0.1:8080/cat2
}
— now, even tho we contacted port 8080, the cat on port 8082 was reached because
spring forwarded the request. this can be proven by cat's output:
{
$ nc -l -p 8082
GET /cat2 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:111.0) Gecko/20100101 Firefox/111.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*
package com.example.Farm;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AnimalRepository extends JpaRepository<FarmApplication.Animal, Long> {}
package com.example.Farm;
import java.util.List;
import jakarta.persistence.*;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.*;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
public
class FarmApplication {
@Entity
public static
class Animal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
public String name;
private int weight;
private int age;
public int getAge(){
return this.age;
}
Animal(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
Animal() { ; }
}
@Bean
public
CommandLineRunner cmdlr(AnimalRepository repository) {
return (args) -> {
repository.save(new Animal("Bob", 3, 10));
};
}
@RestController
static
class Controller {
private final
AnimalRepository repository;
Controller(AnimalRepository repository) {
this.repository = repository;
}
@GetMapping("/hello")
List<Animal> say_hello(){
return repository.findAll();
}
}
public static
void main(String[] args) {
SpringApplication.run(FarmApplication.class, args);
}
}
}
#
### Minimal Mysql example with Spring ###
1. Create a new domain specific database and user
CREATE DATABASE spring;
CREATE USER 'spring'@'localhost' IDENTIFIED BY 'passwd';
GRANT ALL PRIVILEGES ON spring.* TO 'spring'@'localhost';
FLUSH PRIVILEGES;
2. Generate a Spring Boot application with the following dependencies:
jpa
mysql
3. Configure Spring to connect to mysql
// File: src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/spring
spring.datasource.username=spring
spring.datasource.password=passwd
spring.jpa.hibernate.ddl-auto=update
4. Create JTA classes to sync to the database
@Entity
public
class Sheep {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
public String name;
Sheep(String name_) {
this.name = name_;
}
}
// ---
public
interface SheepRepository
extends JpaRepository<SqlApplication.Sheep, Long> {}
5. Seed the database somehow
@Bean
public
CommandLineRunner cmdlr(SheepRepository repository) {
return (args) -> {
repository.save(new Sheep("Ross"));
repository.save(new Sheep("Joe"));
};
}
6. Validate
$ mysql -u root
> use spring;
> select * from sql_application$sheep;
+----+------+
| id | name |
+----+------+
| 1 | Ross |
| 2 | Joe |
+----+------+
#
NOTES:
• highly recommended to wrap your stuff in a package
groovy
#define groovy::\ \
I------------------------------------------\
I _____ \
I | __ \ \
I | | \/_ __ ___ _____ ___ _ \
I | | __| '__/ _ \ / _ \ \ / / | | | \
I | |_\ \ | | (_) | (_) \ V /| |_| | \
I \____/_| \___/ \___/ \_/ \__, | \
I __/ | \
I |___/ \
I------------------------------------------I
• language dependent on the java virtual machine
• compiles to java byte code
• in many ways very similar to java
• the syntax is lighter, more script-y
• commonly used for testing
• has templating support
Templating:
*.tpl
• its like PHP, if it were to override HTML syntax with C
<tagname> (<options>) {<innerHTML>}
// Translates roughly to:
<<tagname> <options>>
<innerHTML>
</<tagname>>
// E.g
div (id: 'mydiv') {
h1 { yield 'IOWA' }
}
Values:
• everything in an open convect is interpreted as a keyword or symbol name
• string interpolations use the ${} schema
// literal string 'mystring'
yield 'mystring'
// expension of variable 'myvar'
yield myvar
// string interpolation using the value of 'myvar'
yield "# - ${myvar}."
// iteration using all elements of 'myvars'
myvars.findAll().each { myvar ->
li {
yield myvar
}
Methods:
• parentheses are omitable if there is only one argument
yield(<...>) : pastes <...> into the HTML; basically PHP's echo;
auto escapes "<>"s
yieldUnescaped(<...>) : yield; but "<>"s are not escaped
comment(<...>) : pastes <...> into the HTML encapsulated inside a comment
kotlin
#define kotlin::
I-------------------------------\
I _ __ _ _ _ \
I | | / / | | | (_) \
I | |/ / ___ | |_| |_ _ __ \
I | \ / _ \| __| | | '_ \ \
I | |\ \ (_) | |_| | | | | | \
I \_| \_/\___/ \__|_|_|_| |_| \
I-------------------------------I
Files:
.kt : kotlin source file
.kts : kotlin script
Applications:
program:
• requires a main
fun main() { ... } : entry point
script:
• the global context is executed
• the compiler creates no output file and runs the code after compiling to memory
Comments:
• C/C++ style
• CAN be nested
Variables:
<var|val> <name> [: <typename>]
var : variable
val : const
• the typename is not required on assignment at declaration (behaves like auto)
• the idea is that you are only suppord to specify the type explicitly
if its not obvious what the type of the right hand side will be
{function return value}
• C# nullable syntax ('?')
typename:
• no primitive types
Boolean
Byte
Short
Int
Long
Float
Double
Char
String
Array
Pair
List
Member_functions:
first()
last()
count()
add(<typename>)
remove(<typename>)
Set
Member_functions:
count()
add(<typename>)
remove(<typename>)
Map
count()
add(<pair>)
remove(<typename>)
operator[]
keys()
values()
Any
Unit
Nothing
literals:
• normal numerics
— C style char/string literal quoting
"string"
'c'
— interpolation:
"--- ${muh_var} ---"
" = ${i * 6}"
• can contain arbitrary code
• can include unescaped '\"'s; its smart like bash
• the offical documentation refers to this as template-s
Operators:
?. : "Elvis operator";
if left handside is null
then null
else access right hand side of left hand side
{ val b : Int? = a?.size(); }
Functions:
func <name>([parameter]+) [: <typename>] { <...> }
func <name>([parameter]+) = <expression>
• first order
• the passed parameters are const (val)
• if the body can be expressed as a single expression
then no return type or return keyword is needed
• named arguments
• default values
— lambda types are defined with haskell like syntax:
var myrelation : (Int a, Int b) -> Int
{
fun sum(a: Int, b: Int): Int { return a + b }
}
Data_groups:
. : member access notation
this : refers to the current object
class:
[specifier] class <name> [argument-list] : <inheritance> { <...> }
• members are public by default
• get set syntax that drops the function call notation
• can be extended from outside of their definition
specifier:
open : can be inherited from
final : cannot be inherited from; default
data:
— the compiler auto generates the following methods:
• toString()
• equals()
• hashCode()
• final by default and this cannot be changed
abstract : the class cannot be consturcted and abstract members become allowed
value : created on the stack
inheritance:
typename : inherits from <typename>
<typename> by <var> : inherits <typename> through <var>;
which is an also an injected dependency
constructor:
super(<...>) : refers to the constructor of the parent
• a primary constructor is a constructor all other constructors must call
• if a class has no primary constructor and inherits then it must call the parents constructor
• if an argument list is given to the class definition,
that creates a primary constructor
{
class Language(val name : String, var bullshit_score : Int) {}
var kotlin = Language("Kotlin", 3);
}
methods:
<specifier> <function>
override
fields:
<var> [get] [set];
get() { <...> }
set(value) { <...> }
field : refers to the current member variable inside a getter or a setter
lateinit
enum:
pass
interface:
• like abstract classes, but they cant store state at all
SAM:
fun interface <name> { fun <...>(<parameters>): <typename> }
• "Single Abstract Method"
• radical OOP way of typedef-ing a function
object:
• syntax support for a singleton
companion object:
• static, but radically OOP because fuck you thats why
access:
private
protected
internal
public
extensions:
fun <typname>.<name> <function-declaration>
val <typname>.<name> <field-declaration>
• symbols which are added as members to a class while being declared outside of it
• resolved static-ally
• can be inside other class-es
• cannot use 'field'
nesting:
• valid
inner : allows the nested class to access the fields of its parent
Control:
when
— >
else
do while
while
for
try catch finally
Operators:
<1>...<2> : returns iterable from <1> to <2>; inclusive
<1>...<<2> : returns iterable from <1> to <2>; end exclusive
<...> in <iterable> : returns bool indicating whether <operand>
can be found inside <iterable>
<iterable> step <int> : returns interatable constructed from
every <int>th element of <iterable>
<...> is <typename> : returns bool indicating whether <...>
is of the type <typename>
<1> to <2> : returns a Pair constructed from <1> and <2>
Generics:
• they exist
Packages:
package <name>
import <name>
• no directory requirements (unlike in java)
Standard_library:
print()
println()
readln()
?!:
• if else has a value
{
val c : Int = if (a == b) { a } else { b }
}